redis分布式鎖的續鎖方案

2021-10-16 22:02:28 字數 2758 閱讀 5079

基於redis的分布式鎖,很多人都有用過。今天簡單介紹基於redison客戶端的分布式鎖原始碼分析,重點內容是關於續鎖的問題,具體內容如下。

1)、基於redison客戶端建立分布式鎖工具,具體**如下圖:

從圖1可以看出,這個工具類裡面主要的內容是初始化redisson客戶端,嘗試加鎖,釋放鎖三個操作。

2)、使用redissonlockutils對業務**進行加鎖,處理完業務後釋放鎖,具體**如下圖:

從圖2可以看出,釋放鎖的操作是放在finally塊中的,而不是直接放到業務**後面的。這個是為了防止業務**異常結束,鎖沒有釋放。

1)、找到redissonclient的trylock方法的具體實現原始碼,如下圖:

從圖3可以看出,trylock方法中主要的操作是呼叫tryacquire去嘗試加鎖,當加鎖未成功後,判斷到當前為止,加鎖的耗時是否超過加鎖等待時間(waittime),若超過就返回false,表示加鎖失敗,若沒有超過就通過自旋繼續加鎖,直到加鎖成功或超時返回。

2)、看一下tryacquire方法的原始碼,如下圖:

從圖4可以看出,在進行加鎖前會判斷使用者在進行加鎖操作的時候是否有傳鎖的超時時間,如果沒有就預設為30秒。然後呼叫tryacquireasync方法進行加鎖。

3)、看一下tryacquireasync方法的原始碼,如下圖:

從圖4可以看出,這裡的加鎖是通過執行lua指令碼,將給key賦值操作和給key設定超時時間操作合併成乙個操作,保證操作的原子性。這樣不會出現已經給key賦值了但超時時間沒有設定上的問題。

上面介紹了如何使用redis分布式鎖和分析了加鎖的原始碼。這裡我們先來看乙個問題:對乙個業務**進行加鎖,在執行業務**的過程中,鎖的超時時間到了,鎖被釋放了,而此時該執行緒的業務邏輯還沒處理完。這個時候如果其他執行緒獲取到了鎖,就會導致各種問題。對於這樣的問題,就需要在超時時間快到的時候,進行續鎖操作(即給鎖重新設定超時時間)。續鎖方案如下:

redisson內部提供了乙個監控鎖的看門狗,它的作用是在redisson例項被關閉前,不斷的延長鎖的超時時間。先來看下tryacquire的原始碼,如下圖:

從圖6可以看出,當我們沒有設定鎖的超時時間的時候,會自動設定超時時間(lockwatchdogtimeout),預設30秒。如下圖:

這個自動設定超時時間加鎖和我們設定超時時間加鎖的區別在於,自動設定超時時間加鎖後啟動乙個看門狗(watch dog),每隔一段時間檢查一下,如果業務1還持有鎖key,那麼就會不斷的延長鎖key的生存時間。具體的操作是scheduleexpirationrenewal(threadid),原始碼如下圖:

這使用這種方式時需要注意,如果加鎖的業務**一直阻塞會導致這個鎖一直被占用,無法釋放。

通常,我們在使用分布式鎖的時候,會根據業務的需要,在進行加鎖的時候,設定合理的超時時間。但如果設定了鎖的超時時間,就不會觸發方案一中的看門狗(watch dog)自動延期機制,這個時候就需要自己來設計續鎖方案了。在設定續鎖方案之前,先看下這個鎖在redis中怎樣儲存的,具體如下圖:

其實自定義續鎖方案其實和看門狗(watch dog)自動延期機制差不多,就是在加鎖的時候,另開乙個執行緒呼叫續鎖的**。具體**如下圖:

介紹以下這個續鎖的**,它主要的步驟如下:

1)、根據鎖key ,獲取持有鎖的執行緒在key中的字段和值。

2)、根據自己設定的鎖的超時時間,定義乙個自旋的時間。

3)、開始自旋再次獲取現在redis中鎖key中的字段和值。

4)、看再次獲取到的字段和值是否存在,不存在就結束續鎖操作。若存在就進行下一步。

5)、判斷當前的鎖key的欄位名稱和需要續鎖key的欄位名稱是否一樣,不一樣就可以結束續鎖操作。一樣就進行下一步。

6)、獲取鎖的剩餘時間,判斷剩餘時間是否小於等於鎖超時時間的1/4。是,就重新設定超時時間,讓持有鎖的執行緒繼續持有鎖。

7)、每隔超時時間的1/4就進行一次續鎖判斷,看是否需要鎖。

測試下上面的續鎖的**,測試**如下:

執行下,看下redis中key的剩餘時間,如下圖:

從這個圖可以看出,續鎖成功了。這個續鎖方案可以根據自己需要設定合理的超時時間,在續鎖的時候,也可以設定個對續鎖操作的超時時間,防止乙個持有鎖的執行緒一直阻塞,導致鎖一直被占用無法釋放。

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不存在。如給定的...