中国体彩网唯一官网
目錄 搜索
Cluster cluster addslots(集群 槽位) cluster count failure reports(集群計數失敗報告) cluster countkeysinslot cluster delslots cluster failover cluster forget cluster getkeysinslot cluster info cluster keyslot(集群鍵槽) cluster meet cluster nodes(集群節點) cluster replicate(集群復制) cluster reset(集群重置) cluster saveconfig cluster set config epoch cluster setslot cluster slaves cluster slots readonly readwrite Connection auth echo ping quit select swapdb Geo geoadd geodist geohash geopos georadius georadiusbymember Hashes hdel hexists hget hgetall hincrby hincrbyfloat hkeys hlen hmget hmset hscan hset hsetnx hstrlen hvals HyperLogLog pfadd pfcount pfmerge Keys del dump exists expire expireat keys migrate move object persist pexpire pexpireat pttl randomkey rename renamenx restore scan sort touch ttl type unlink wait Lists blpop brpop brpoplpush lindex linsert llen lpop lpush lpushx lrange lrem lset ltrim rpop rpoplpush rpush rpushx Pub/Sub psubscribe publish pubsub punsubscribe subscribe unsubscribe Scripting eval evalsha script debug script exists script flush script kill script load Server bgrewriteaof bgsave client getname client kill client list client pause client reply client setname command command count command getkeys command info config get config resetstat config rewrite config set dbsize debug object debug segfault flushall flushdb info lastsave monitor role save shutdown slaveof slowlog time Sets sadd scard sdiff sdiffstore sinter sinterstore sismember smembers smove spop srandmember srem sscan sunion sunionstore Sorted Sets zadd zcard zcount zincrby zinterstore zlexcount zrange zrangebylex zrangebyscore zrank zrem zremrangebylex zremrangebyrank zremrangebyscore zrevrange zrevrangebylex zrevrangebyscore zrevrank zscan zscore zunionstore Strings append bitcount bitfield bitop bitpos decr decrby get getbit getrange getset incr incrby incrbyfloat mget mset msetnx psetex set setbit setex setnx setrange strlen Transactions discard exec multi unwatch watch
文字

SETNX key value

自1.0.0起可用。

時間復雜度: O(1)

如果不存在,則設置key為保存字符串。在這種情況下,它等于SET。當已經保存一個值時,不執行任何操作。SETNX 是短期的“ SET如果? OT? X派”。valuekeykey

返回值

整數回復,具體為:

  • 1 如果密鑰已設置

  • 0 如果密鑰沒有設置

例子

redis>  SETNX mykey "Hello" (integer) 1 redis>  SETNX mykey "World" (integer) 0 redis>  GET mykey "Hello"

設計模式:鎖定 SETNX

請注意:

  1. 以下模式不利于Redlock算法,該算法實現起來稍微復雜一些,但提供了更好的保證并具有容錯能力。

  1. 無論如何,我們記錄舊的模式,因為某些現有的實現鏈接到此頁面作為參考。此外,Redis 命令如何用于裝載編程原語是一個有趣的例子。

  1. 無論如何,即使假定一個單實例鎖定原語,從2.6.12開始,可以創建一個更簡單的鎖定原語,與此處討論的等價,使用 SET 命令獲取鎖,以及一個簡單的 Lua 腳本來釋放鎖。該模式記錄在SET命令頁面中。

也就是說,SETNX 可以被用作歷史上被用作鎖定原語。例如,要獲取密鑰的鎖定foo,客戶端可以嘗試以下操作:

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

如果 SETNX 返回1客戶端獲得的鎖定,則將該lock.foo關鍵字設置為不再認為該鎖定有效的 Unix 時間。客戶端稍后將使用DEL lock.foo以釋放鎖。

如果 SETNX 返回0該鍵已被某個其他客戶端鎖定。如果它是非阻塞鎖,我們可以返回給調用者,或者輸入一個循環重試以保持鎖,直到我們成功或某種超時過期。

處理死鎖

在上述鎖定算法中存在一個問題:如果客戶端出現故障,崩潰或無法釋放鎖,會發生什么情況?可以檢測到這種情況,因為鎖定鍵包含 UNIX 時間戳。如果這樣的時間戳等于當前的 Unix 時間,則該鎖不再有效。

發生這種情況時,我們不能僅僅通過調用 DEL 來移除鎖,然后嘗試發出 SETNX,因為這里存在爭用條件,當多個客戶端檢測到過期的鎖并嘗試釋放它時。

  • C1和C2讀取lock.foo以檢查時間戳,因為它們0在執行SETNX 之后都收到,因為鎖仍然由持有鎖之后崩潰的 C3 持有。

  • C1發送 DEL lock.foo

  • C1發送SETNX lock.foo并成功

  • C2發送 DEL lock.foo

  • C2發送SETNX lock.foo并成功

  • 錯誤:由于競爭條件,C1和C2都獲得了鎖定。

幸運的是,使用以下算法可以避免此問題。讓我們看看我們的理智客戶C4如何使用好的算法:

  • C4發送SETNX lock.foo以獲取鎖

  • 崩潰的客戶端C3仍然擁有它,所以Redis將回復0給C4。

  • C4發送GET lock.foo來檢查鎖是否過期。如果不是,它會睡眠一段時間并從一開始就重試。

  • 相反,如果鎖由于 Unix 時間lock.foo比當前 Unix 時間早而過期,C4會嘗試執行:

GETSET lock.foo <current Unix timestamp + lock timeout + 1>

  • 由于 GETSET 語義,C4可以檢查存儲的舊值key是否仍然是過期的時間戳。如果是這樣,那就得到了鎖。

  • 如果另一個客戶端(例如C5)比C4速度更快并通過 GETSET 操作獲取了鎖定,則C4 GETSET 操作將返回一個未過期的時間戳。C4將從第一步重新開始。請注意,即使C4在未來幾秒鐘內將鍵設置為幾秒,這也不是問題。

為了使這種鎖定算法更加健壯,持有鎖的客戶端應該始終檢查超時在 DEL 用于解鎖密鑰之前沒有過期,因為客戶端失敗可能很復雜,不僅會崩潰,而且會阻止大量時間對付某些操作并嘗試在很長時間后發出 DEL(當 LOCK 已被另一客戶端占用時)。

上一篇: 下一篇:
中国体彩网唯一官网