在分布式系統中,在介面沒***冪等性或者在某些場景下相同的服務需要有且僅有乙個服務執行的情況下,需要使用分布式鎖來保證系統的安全執行。
分布式鎖的執行順序,有服務a,分別部署了三個節點為a1、
a2、a3,為滿足我們上述需求,我們需要在共享的資料載體中做標記,即,
a1開始執行的話,a2、
a3不能在執行,直到
a1執行完之後,
a2或者
a3才能繼續執行。
redis的做法:
1、a1在進入系統後先判斷
redis
中有沒有這個標記(
key),沒有的話,在
redis
中放入一條資料。
setnx
2、a2或者
a3在進入方法時同樣執行這個操作,如果有了這個
key,則不再執行該方法。
使用該順序則可保證在分布式系統中某服務有且僅有乙個相同的方法在執行。
但是一般在生產環境redis都是集群部署的,主節點負責寫入,從節點負責讀取,
redis
集群內部的主從複製廣播是需要時間的,主節點接收到,但是還沒有往從節點寫入,
a2就去從節點查了,沒有,
a2就會發起
setnx
,造成分布式鎖失效。
這時候作者antirez提出了
redlock
方式:
1、**中獲取當前時間,毫秒
2、依次向redis所有節點放置,相同的
key和具有唯一性的
value
(雪花、
uuid
等),當向
redis
請求獲取鎖時,客戶端應該設定乙個網路連線和響應超時時間,這個超時時間應該小於鎖的失效時間。例如你的鎖自動失效時間為
10秒,則超時時間應該在
5-50
毫秒之間。這樣可以避免伺服器端
redis
已經掛掉的情況下,客戶端還在死死地等待響應結果。如果伺服器端沒有在規定時間內響應,客戶端應該盡快嘗試去另外乙個
redis
例項請求獲取鎖。
3、客戶端使用當前時間減去開始獲取鎖時間(步驟1記錄的時間)就得到獲取鎖使用的時間。當且僅當從大多數(
n/2+1
,這裡是
3個節點)的
redis
節點都取到鎖,並且使用的時間小於鎖失效時間時,鎖才算獲取成功。
4、如果取到了鎖,key的真正有效時間等於有效時間減去獲取鎖所使用的時間(步驟
3計算的結果)。
5、如果因為某些原因,獲取鎖失敗(沒有在至少n/2+1個
redis
例項取到鎖或者取鎖時間已經超過了有效時間),客戶端應該在所有的
redis
例項上進行解鎖(即便某些
redis
例項根本就沒有加鎖成功,防止某些節點獲取到鎖但是客戶端沒有得到響應而導致接下來的一段時間不能被重新獲取鎖)。
這些其實在redisson裡面已經有了很好的實現,截個圖吧。
其實,這寫下來還有很多疑問,redis的崩潰選舉使用的
raft
協議,可是資料同步的這一塊兒還沒有仔細搞清楚,另外哨兵監控感覺也有疑問,慢慢來吧。
Redis做分布式鎖
在分布式系統中,在介面沒 冪等性或者在某些場景下相同的服務需要有且僅有乙個服務執行的情況下,需要使用分布式鎖來保證系統的安全執行。分布式鎖的執行順序,有服務a,分別部署了三個節點為a1 a2 a3,為滿足我們上述需求,我們需要在共享的資料載體中做標記,即,a1開始執行的話,a2 a3不能在執行,直到...
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的分布式鎖.首先,為了確保分布式鎖可用,我們至少要確保鎖的實現同時滿足以下四個條件 互斥性。在任意時刻,只有乙個客戶端能持有鎖。不會發生死鎖。即使有乙個客戶端在持有鎖的期間崩潰而沒有主動解鎖,也能保...