Redis分布式鎖

2021-10-01 02:03:48 字數 1548 閱讀 2182

關於redis相關基本概念,前文有過具體的描述。

1. 對redis特性進行一次總結:

支援豐富的資料型別,如string、list、map、set、zset等。

支援資料持久化,rdb和aof兩種方式

支援集群工作模式,分割槽容錯性強

支援事務

單執行緒,順序處理命令

2. redis實現分布式鎖有兩種實現方式:

一是使用redis的watch命令進行實現,二是使用redis的setnx(set if not exists)命令進行實現,下文主要對setnx命令進行具體的描述

3. 實現方式

set方法中nxx引數為nx,表示當key不存在時才會set值,保證了互斥性;若給定的 key 已經存在,則 setnx 不做任何動作

set值的同時設定過期時間(過期後del此key),客戶端宕機或網路延遲時不會一直持有鎖,避免了死鎖發生;

set方法中的value,比如uuid之類的,用來表示當前請求客戶端的唯一性標識;

因為是redis單例,暫時沒有考慮容錯性;

4. 可能出現的問題:

加鎖後,業務併發訪問這個執行緒都返回了失敗,只有少部分獲取到鎖的執行緒才能處理,這種情況下是非常不通情理的

使用reddison已經內部實現的自旋鎖來進行鎖的等待,獲取不到鎖就while迴圈一直嘗試加鎖,知道鎖的獲取成功才返回結果,但是這是悲觀鎖

加完鎖後,每次獲取完鎖時就對乙個特定值+1,執行完後對特定值進行釋放,但是執行緒拿到鎖後,丟擲異常時,無法執行最後釋放鎖操作

加finally塊執行釋放鎖操作

加了finally塊後,這個塊中的業務失敗了,或者程式掛了,redis連線失敗了,無法釋放鎖(

對鎖加超時時間

加了超時時間後,在持有鎖這個業務中的執行時間比超時時間長,在業務執行的時候,鎖超時釋放了,這時,其他的請求的執行緒就能獲取到這個鎖了,出現了執行緒的重複進入

對redis鎖的key值用乙個uuid來設計,同個執行緒內獲取這個鎖都需要生成乙個唯一的id,釋放時只能讓同個執行緒內存放的id匹配釋放

第二個執行緒執行了業務,而且這個業務執行後,比第乙個執行緒快,並且鎖超時解鎖解了第乙個鎖

獲取到這個鎖的時候,另外開闢乙個執行緒,比如超時時間是10秒,這個執行緒就每5秒就查詢一下這個鎖是否失效,如果沒有失效就增加5秒中,保持這個鎖的有效性

執行緒如果獲取分布式鎖失敗,為什麼不嘗試重新獲取鎖?

redis的setnx命令,如果key已經存在,則不會做任何操作,所以setnx實現的分布式鎖並不是可重入鎖。當然,也可以自己通過**實現重試n次或者直至獲取到分布式鎖為止。但是,這不能保證競爭的公平性,某個執行緒會因為一直等待鎖而阻塞。因此,redis實現的分布式鎖更適用於對共享資源一寫多讀的場景。

程獲取分布式鎖成功後,設定了鎖的失效時間,這個失效時間長短如何確定?

分布式鎖必須設定失效時間,而且失效時間必須大於業務處理所需的時間(保證資料一致性)。所以,在測試階段盡可能準確的**出業務正常處理所需的時間,設定失效時間是防止因為業務處理過程的某些原因導致死鎖的情況。

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