distributed readers/writer lock

366 views
Skip to first unread message

Aaron Boxer

unread,
Nov 6, 2010, 8:14:54 AM11/6/10
to redi...@googlegroups.com
Hello!
Would it be feasible to use Redis for a distributed readers/writer lock?
Thanks!
Jorge

Demis Bellot

unread,
Nov 6, 2010, 10:19:30 AM11/6/10
to redi...@googlegroups.com
Sure, 

This behaviour is already present in many redis clients. ServiceStack C# Redis Client has a page on it here:

It uses SETNX under the hood - Salvatore has a good explanation on how to do this on the SETNX operation page:

- Demis




--
You received this message because you are subscribed to the Google Groups "Redis DB" group.
To post to this group, send email to redi...@googlegroups.com.
To unsubscribe from this group, send email to redis-db+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/redis-db?hl=en.


Ludger Sprenker

unread,
Nov 6, 2010, 4:07:06 PM11/6/10
to Redis DB
> This behaviour is already present in many redis clients. ServiceStack C#
> Redis Client has a page on it here:http://code.google.com/p/servicestack/wiki/RedisLocks

I don't like the 'exponential retry' thing in that solution. I started
to remodel this solution in the C++ client with a token pushed to a
list. This has the advantage that you can wait non-busy on the release
of the token using BLPOP (with or without timeout) or just try to lock
without any waiting (using LPOP). But it is hard to make it bullet-
proof in case of client crashes when the token is never pushed back ...

Aaron Boxer

unread,
Nov 6, 2010, 5:51:38 PM11/6/10
to redi...@googlegroups.com
Thanks, Demis! Will try this out.

Aaron Boxer

unread,
Nov 6, 2010, 10:37:54 PM11/6/10
to redi...@googlegroups.com
Demis,

reader/writer lock seems a lot more complex than simple lock:

A client can hold a reader lock or a writer lock, but not both at the
same time.

Readers and writers are queued separately. When a client releases the
writer lock, all clients waiting in the reader queue at that instant
are granted reader locks; when all of those reader locks have been
released, the next client waiting in the writer queue, if any, is
granted the writer lock, and so on. In other words, ReaderWriterLock
alternates between a collection of readers, and one writer.

While a client in the writer queue is waiting for active reader locks
to be released, clients requesting new reader locks accumulate in the
reader queue. Their requests are not granted, even though they could
share concurrent access with existing reader-lock holders; this helps
protect writers against indefinite blockage by readers.

I would need:


1 writer lock (a key set with SETNX)
N reader locks (N keys set with SETNX)
a LIST of queued requests for reader locks (use client IP as value)
a LIST of queued requests for writer locks (use client IP as value)

Reader:

1) check if writer lock exists
2) if it doesn't, then cycle through reader locks, acquiring the first
available lock
3) if all locks are taken, then add itself to reader lock request
queue, and loop and check
until a reader lock is available, and this reader as at the head of the queue
4) once available, acquire the lock and remove itself from request queue

OR

1) if writer lock exists, then add itself to reader lock request
queue, and keep looping
and checking

Writer:

1) check if writer lock exists
2) if it doesn't then acquire it, and keep looping until all reader
locks are deleted.
3) once all readers are deleted, then start writing
4) when finished, release the lock

OR

1) if writer lock exists, then add itself to writer queue, and keep
looping until writer is at the head of the queue
2) once at the head of the queue, keep checking until writer lock is available
3) once available, acquire it, remove itself from writer queue, and
start writing
4) when finished, release the lock


Is there an easier way of doing this?

Thanks!

Jorge

On Sat, Nov 6, 2010 at 10:19 AM, Demis Bellot <demis....@gmail.com> wrote:

Demis Bellot

unread,
Nov 7, 2010, 8:59:24 AM11/7/10
to redi...@googlegroups.com
Yeah that would be more complex to implement.

I think you're on the right track where a combination of SETNX and LIST sounds like the right path to go down.
I don't know if an IP Address is going to have enough granularity, I would think you will also need the srcPort as well to distinguish the client connection since you can have multiple connections from the same host (e.g. when using connection pooling, etc).

I think other Redis constructs that may be of use is the WATCH command so you can ensure that the states haven't changed between detecting the state of the locks and acquiring a lock.
Also using Redis's PubSub messaging features will be a good way to notify all clients the state of locks have changed, providing a more event-based rather than poll-based notification to your clients.

- Demis

Aaron Boxer

unread,
Nov 7, 2010, 1:42:59 PM11/7/10
to redi...@googlegroups.com
Thanks, Demi. Yes, IP:PORT would work better. Also, forgot about
pub/sub; that would work nicely here.

I would rather have the server do all of the management of locks and queues,
perhaps I would need to write a server-side extension to do this properly.

Salvatore Sanfilippo

unread,
Nov 7, 2010, 4:23:28 PM11/7/10
to redi...@googlegroups.com
+1, with WATCH you can do all this atomically, without any trick.

Cheers,
Salvatore

--
Salvatore 'antirez' Sanfilippo
http://invece.org

"We are what we repeatedly do. Excellence, therefore, is not an act,
but a habit." -- Aristotele

Aaron Boxer

unread,
Nov 7, 2010, 10:24:19 PM11/7/10
to redi...@googlegroups.com
Thanks, Salvatore. I will have to investigate further....
Reply all
Reply to author
Forward
0 new messages