Movatterモバイル変換


[0]ホーム

URL:


Products
Resources
DocsPricing
LoginBook a meetingTry Redis

SETNX(deprecated)

As of Redis version 2.6.12, this command is regarded as deprecated.

It can be replaced bySET with theNX argument when migrating or writing new code.

Syntax
SETNX key value
Available since:
Redis CE 1.0.0
Time complexity:
O(1)
ACL categories:
@write,@string,@fast,

Setkey to hold stringvalue ifkey does not exist.In that case, it is equal toSET.Whenkey already holds a value, no operation is performed.SETNX is short for "SET ifNot eXists".

Examples

SETNX mykey "Hello"SETNX mykey "World"GET mykey

Design pattern: Locking withSETNX

Please note that:

  1. The following pattern is discouraged in favor ofthe Redlock algorithm which is only a bit more complex to implement, but offers better guarantees and is fault tolerant.
  2. We document the old pattern anyway because certain existing implementations link to this page as a reference. Moreover it is an interesting example of how Redis commands can be used in order to mount programming primitives.
  3. Anyway even assuming a single-instance locking primitive, starting with 2.6.12 it is possible to create a much simpler locking primitive, equivalent to the one discussed here, using theSET command to acquire the lock, and a simple Lua script to release the lock. The pattern is documented in theSET command page.

That said,SETNX can be used, and was historically used, as a locking primitive. For example, to acquire the lock of the keyfoo, the client could try thefollowing:

SETNX lock.foo <current Unix time + lock timeout + 1>

IfSETNX returns1 the client acquired the lock, setting thelock.foo keyto the Unix time at which the lock should no longer be considered valid.The client will later useDEL lock.foo in order to release the lock.

IfSETNX returns0 the key is already locked by some other client.We can either return to the caller if it's a non blocking lock, or enter a loopretrying to hold the lock until we succeed or some kind of timeout expires.

Handling deadlocks

In the above locking algorithm there is a problem: what happens if a clientfails, crashes, or is otherwise not able to release the lock?It's possible to detect this condition because the lock key contains a UNIXtimestamp.If such a timestamp is equal to the current Unix time the lock is no longervalid.

When this happens we can't just callDEL against the key to remove the lockand then try to issue aSETNX, as there is a race condition here, whenmultiple clients detected an expired lock and are trying to release it.

  • C1 and C2 readlock.foo to check the timestamp, because they both received0 after executingSETNX, as the lock is still held by C3 that crashedafter holding the lock.
  • C1 sendsDEL lock.foo
  • C1 sendsSETNX lock.foo and it succeeds
  • C2 sendsDEL lock.foo
  • C2 sendsSETNX lock.foo and it succeeds
  • ERROR: both C1 and C2 acquired the lock because of the race condition.

Fortunately, it's possible to avoid this issue using the following algorithm.Let's see how C4, our sane client, uses the good algorithm:

  • C4 sendsSETNX lock.foo in order to acquire the lock

  • The crashed client C3 still holds it, so Redis will reply with0 to C4.

  • C4 sendsGET lock.foo to check if the lock expired.If it is not, it will sleep for some time and retry from the start.

  • Instead, if the lock is expired because the Unix time atlock.foo is olderthan the current Unix time, C4 tries to perform:

    GETSET lock.foo <current Unix timestamp + lock timeout + 1>
  • Because of theGETSET semantic, C4 can check if the old value stored atkey is still an expired timestamp.If it is, the lock was acquired.

  • If another client, for instance C5, was faster than C4 and acquired the lockwith theGETSET operation, the C4GETSET operation will return a nonexpired timestamp.C4 will simply restart from the first step.Note that even if C4 set the key a bit a few seconds in the future this isnot a problem.

In order to make this locking algorithm more robust, aclient holding a lock should always check the timeout didn't expire beforeunlocking the key withDEL because client failures can be complex, not justcrashing but also blocking a lot of time against some operations and tryingto issueDEL after a lot of time (when the LOCK is already held by anotherclient).

RESP2/RESP3 Reply

One of the following:


RATE THIS PAGE
Back to top ↑
See also
APPEND
DECR
DECRBY
GET
GETDEL
GETEX
GETRANGE
GETSET
INCR
INCRBY
INCRBYFLOAT
LCS
MGET
MSET
MSETNX
PSETEX
SET
SETEX
SETNX
SETRANGE
STRLEN
SUBSTR

[8]ページ先頭

©2009-2025 Movatter.jp