目錄搜索
Clustercluster addslots(集群 槽位)cluster count failure reports(集群計數失敗報告)cluster countkeysinslotcluster delslotscluster failovercluster forgetcluster getkeysinslotcluster infocluster keyslot(集群鍵槽)cluster meetcluster nodes(集群節點)cluster replicate(集群復制)cluster reset(集群重置)cluster saveconfigcluster set config epochcluster setslotcluster slavescluster slotsreadonlyreadwriteConnectionauthechopingquitselectswapdbGeogeoaddgeodistgeohashgeoposgeoradiusgeoradiusbymemberHasheshdelhexistshgethgetallhincrbyhincrbyfloathkeyshlenhmgethmsethscanhsethsetnxhstrlenhvalsHyperLogLogpfaddpfcountpfmergeKeysdeldumpexistsexpireexpireatkeysmigratemoveobjectpersistpexpirepexpireatpttlrandomkeyrenamerenamenxrestorescansorttouchttltypeunlinkwaitListsblpopbrpopbrpoplpushlindexlinsertllenlpoplpushlpushxlrangelremlsetltrimrpoprpoplpushrpushrpushxPub/SubpsubscribepublishpubsubpunsubscribesubscribeunsubscribeScriptingevalevalshascript debugscript existsscript flushscript killscript loadServerbgrewriteaofbgsaveclient getnameclient killclient listclient pauseclient replyclient setnamecommandcommand countcommand getkeyscommand infoconfig getconfig resetstatconfig rewriteconfig setdbsizedebug objectdebug segfaultflushallflushdbinfolastsavemonitorrolesaveshutdownslaveofslowlogtimeSetssaddscardsdiffsdiffstoresintersinterstoresismembersmemberssmovespopsrandmembersremsscansunionsunionstoreSorted SetszaddzcardzcountzincrbyzinterstorezlexcountzrangezrangebylexzrangebyscorezrankzremzremrangebylexzremrangebyrankzremrangebyscorezrevrangezrevrangebylexzrevrangebyscorezrevrankzscanzscorezunionstoreStringsappendbitcountbitfieldbitopbitposdecrdecrbygetgetbitgetrangegetsetincrincrbyincrbyfloatmgetmsetmsetnxpsetexsetsetbitsetexsetnxsetrangestrlenTransactionsdiscardexecmultiunwatchwatch
文字

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 已被另一客戶端占用時)。

上一篇:下一篇:
澳洲幸运8在哪里开奖