redis分布式鎖 setnx del

2021-10-05 11:23:06 字數 2010 閱讀 5780

將key的值設為value,並且僅當key不存在。

若給定的key已經存在,則setnx不做任何操作。

setnx 是set if not exists的簡寫。

返回整數,具體為

1,當 key 的值被設定

0,當 key 的值沒被設定

使用setnx實現分布式鎖

多個程序執行以下redis命令:

如果 setnx 返回1,說明該程序獲得鎖,setnx將鍵 lock.foo 的值設定為鎖的超時時間(當前時間 + 鎖的有效時間)。

如果 setnx 返回0,說明其他程序已經獲得了鎖,程序不能進入臨界區。程序可以在乙個迴圈中不斷地嘗試 setnx 操作,以獲得鎖。

解決死鎖

正常第一反應利用setnx實現分布式鎖可能是這樣的

然後釋放鎖的時候就直接 del掉;

簡單思路是這樣,但是這樣會有很多問題

如果乙個程序獲得鎖之後,斷開了與redis的連線(程序結束通話或者網路中斷),那麼鎖一直的不斷釋放,其他的程序就一直獲取不到鎖,就出現了 「死鎖」

然而,鎖超時時,我們不能簡單地使用 del 命令刪除鍵 lock.foo 以釋放鎖。考慮以下情況,程序p1已經首先獲得了鎖 lock.foo,然後程序p1掛掉了。程序p2,p3正在不斷地檢測鎖是否已釋放或者已超時,執行流程如下:

1 . p2和p3程序讀取鍵 lock.foo 的值,檢測鎖是否已超時(通過比較當前時間和鍵 lock.foo 的值來判斷是否超時)

2.p2和p3程序發現鎖 lock.foo 已超時

3.p2執行 del lock.foo命令

4.p2執行 setnx lock.foo命令,並返回1,即p2獲得鎖

5.p3執行 del lock.foo命令將p2剛剛設定的鍵 lock.foo 刪除(這步是由於p3剛才已檢測到鎖已超時)

6.p3執行 setnx lock.foo命令,並返回1,即p3獲得鎖

7.p2和p3同時獲得了鎖

從上面的情況可以得知,在檢測到鎖超時後,程序不能直接簡單地執行 del 刪除鍵的操作以獲得鎖。

為了解決上述演算法可能出現的多個程序同時獲得鎖的問題,我們再來看以下的演算法。

我們同樣假設程序p1已經首先獲得了鎖 lock.foo,然後程序p1掛掉了。接下來的情況:

程序p4執行 setnx lock.foo 以嘗試獲取鎖

由於程序p1已獲得了鎖,所以p4執行 setnx lock.foo 返回0,即獲取鎖失敗

p4執行 get lock.foo 來檢測鎖是否已超時,如果沒超時,則等待一段時間,再次檢測

如果p4檢測到鎖已超時,即當前的時間大於鍵 lock.foo 的值,p4會執行以下操作

getset lock.foo

由於 getset 操作在設定鍵的值的同時,還會返回鍵的舊值,通過比較鍵 lock.foo 的舊值是否小於當前時間,可以判斷程序是否已獲得鎖

假如另乙個程序p5也檢測到鎖已超時,並在p4之前執行了 getset 操作,那麼p4的 getset 操作返回的是乙個大於當前時間的時間戳,這樣p4就不會獲得鎖而繼續等待。注意到,即使p4接下來將鍵 lock.foo 的值設定了比p5設定的更大的值也沒影響。

另外,值得注意的是,在程序釋放鎖,即執行 del lock.foo 操作前,需要先判斷鎖是否已超時。如果鎖已超時,那麼鎖可能已由其他程序獲得,這時直接執行 del lock.foo 操作會導致把其他程序已獲得的鎖釋放掉。

程式**

用以下python**來實現上述的使用 setnx 命令作分布式鎖的演算法。

redis分布式鎖

redis分布式鎖 直接上 我寫了四個redis分布式鎖的方法,大家可以提個意見 第一種方法 redis分布式鎖 param timeout public void lock long timeout thread.sleep 100 catch exception e override publi...

Redis分布式鎖

分布式鎖一般有三種實現方式 1.資料庫樂觀鎖 2.基於redis的分布式鎖 3.基於zookeeper的分布式鎖.首先,為了確保分布式鎖可用,我們至少要確保鎖的實現同時滿足以下四個條件 互斥性。在任意時刻,只有乙個客戶端能持有鎖。不會發生死鎖。即使有乙個客戶端在持有鎖的期間崩潰而沒有主動解鎖,也能保...

redis分布式鎖

使用redis的setnx命令實現分布式鎖 redis為單程序單執行緒模式,採用佇列模式將併發訪問變成序列訪問,且多個客戶端對redis的連線並不存在競爭關係。redis的setnx命令可以方便的實現分布式鎖。setnx key value 將key的值設為value,當且僅當key不存在。如給定的...