|
SetnxCommand
We moved to Redis.io!Redis home moved to http://redis.io, please visit our new home. |
► Sign in to add a comment
|
Search
|
|
SetnxCommand
We moved to Redis.io!Redis home moved to http://redis.io, please visit our new home. |
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.
@birukoff: this is not possible as for Redis semantic of delete-on-write attempt of keys with an EXPIRE set.
Do you mean that when another client tries to SETNX lock, it will delete previous lock even if SETNX attempt did not succeed? oO
o.O this is horrible.
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.
Thoughts?
Looking for a Ruby EventMachine? implementation? Check it out there : http://gist.github.com/457269 (tests : https://gist.github.com/fc527b26509e9492c3c0)
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.
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 [*]eli.algranti wrote:
- 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...