My favorites | Sign in
Project Home Downloads Wiki Issues Source
Search
for
SetnxCommand  
Updated Dec 21, 2010 by anti...@gmail.com

We moved to Redis.io!

Redis home moved to http://redis.io, please visit our new home.

Comment by biruk...@gmail.com, Dec 5, 2009

In case the client fails before releasing the lock, it gets complicated. It would be much easier if there was an opportunity to set EXPIRE together with SETNX (as one command). Then it times out automatically.

Comment by project member anti...@gmail.com, Dec 5, 2009

@birukoff: this is not possible as for Redis semantic of delete-on-write attempt of keys with an EXPIRE set.

Comment by biruk...@gmail.com, Dec 5, 2009

Do you mean that when another client tries to SETNX lock, it will delete previous lock even if SETNX attempt did not succeed? oO

Comment by tommi.vi...@gmail.com, Jan 29, 2010

o.O this is horrible.

Comment by alecatho...@gmail.com, Mar 4, 2010

If EXPIRE, or a similar command, did not have delete-on-write semantics, I believe a much simpler locking algorithm could be implemented. Possibly something like this:

Lock holders acquire the lock with SETNX + EXPIREX. While the lock is held, the holder periodically calls SET + EXPIREX - purely to reset the expiration time.

eg.

  • C1 and C2 are both contending for a lock held by C3.
  • C3 dies.
  • Lock times out and key is deleted.
  • C1's SETNX is first, C2's SETNX fails. C1 has the lock.

Thoughts?

Comment by julien.g...@gmail.com, Jun 29, 2010

Looking for a Ruby EventMachine? implementation? Check it out there : http://gist.github.com/457269 (tests : https://gist.github.com/fc527b26509e9492c3c0)

Comment by eli.algr...@gmail.com, Jul 5, 2010

Using EXPIRE is good to get rid of stale (timed out) locks in most situations but do not solve the underlying problem:

What happens if a client dies before calling EXPIRE.

An atomic SETNX with EXPIRE would provide the full solution. Using GETSET as outlined in the article to obtain a stale lock is OK as long as the lock time-out for all clients trying to obtain the lock is the same. If not we run the risk of shortening the time-out for a lock held by another client. If the assumption that the lock time is constant holds using GETSET could still increase the time out of a lock for another client.

Comment by sh33run, Jul 18, 2010
"What happens if a client dies before calling EXPIRE."
 UNLOCKED = "SETNX lock $clientname"
 if UNLOCKED
   "EXPIRE lock $timeout" [*]
   // do some code 
 else
   if "TTL lock" > 0
     // wait TTL seconds
   else
     // client crashed (did't set TTL)
     "SET lock $clientname"
     goto [*]
Comment by and...@turkino.net, Dec 16, 2010

eli.algranti wrote:

"Using GETSET as outlined in the article to obtain a stale lock is OK as long as the lock time-out for all clients trying to obtain the lock is the same. If not we run the risk of shortening the time-out for a lock held by another client. If the assumption that the lock time is constant holds using GETSET could still increase the time out of a lock for another client."

- Couldn't this issue be avoided by implementing a new atomic command: "SETIFNOTCHANGED key expectedValue newValue"? In the article above C4 could use this instead of GETSET, and thereby avoiding completely the chance of changing the value of lock.foo if some other client has changed it in the meantime. Believe such a string command could come in handy in other cases as well apart from lock acquisition, e.g. in order to perform simple transactions, but need to play more with redis in order to be more concrete...


Sign in to add a comment
Powered by Google Project Hosting