日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

redisson redlock(基于redisson框架和redis集群使用分布式锁)

發布時間:2025/3/15 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 redisson redlock(基于redisson框架和redis集群使用分布式锁) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、關于分布式鎖的兩篇文章

文章1
文章2

二、redis分布式鎖存在的問題

redis實現分布式鎖有很多種方案,比較完善的方案應該是用setNx + lua進行實現。簡單實現如下:

  • java代碼-加鎖,相當于
set lock_key_name unique_value NX PX 5000;
  • lua腳本-解鎖,原子性操作
if redis.call("get", KEYS[1] == ARGV[1]) thenreturn redis.call("del", KEYS[1]) elsereturn 0 end
  • 解釋
  • NX:僅在不存在 key 的時候才能被執行成功;
  • PX:失效時間,傳入 30000,就是 30s 后自動釋放鎖;
  • unique_value:就是隨機值,可以是線程號之類的。主要是為了更安全的釋放鎖,釋放鎖的時候使用腳本告訴 Redis: 只有 key 存在并且存儲的值和我指定的值一樣才能刪除成功。
  • 為什么要設置隨機值:主要是為了防止鎖被其他客戶端刪除。
  • 客戶端 A 獲得了鎖,還沒有執行結束,但是鎖超時自動釋放了;
  • 客戶端 B 此時過來,是可以獲得鎖的,加鎖成功;
  • 此時,客戶端 A執行結束了,要去釋放鎖,如果不對比隨機值,就會把客戶端 B 的鎖給釋放了。
  • 當然前面看過 Redisson 的處理,這個unique_value存放的是 UUID:ThreadId 組合成的一個類似 931573de-903e-42fd-baa7-428ebb7eda80:1 的字符串。
  • 注意:

  • value需要具有唯一性,可以采用時間戳、uuid或者自增id實現;
  • 客戶端在解鎖時,需要比較本地內存中的value和redis中的value是否一致,防止誤解鎖;(case:clientA獲取鎖lock1,由于clientA執行的時間比較久,導致key=lock1已經過期,redis實例會移除該key;clientB獲取相同的鎖lock1,clientB正在占有鎖并執行業務,此時clientA業務已經執行完畢,準備釋放鎖;如果沒有比較value的邏輯,那么clientA會把clientB持有的鎖釋放掉,這個顯然不行的,由于value值不同,那么clientA釋放鎖的時候只會釋放自己加的鎖,不會誤釋放別的客戶端加的鎖)。
  • 注意,不能一味認為鎖過期的時間應該比key的expire要長,因為接下來要介紹的redisson框架中有續期機制(看門狗機制),該機制的核心就是:如果線程仍舊沒有執行完,那么redisson會自動給redis中的目標key延長超時時間

    在分布式系統中,為了避免單點故障,提高可靠性,redis都會采用主從架構,當主節點掛了后,從節點會作為主繼續提供服務。該種方案能夠滿足大多數的業務場景,但是對于要求強一致性的場景如交易,該種方案還是有漏洞的,原因如下:

  • redis主從架構采用的是異步復制,當master節點拿到了鎖,但是鎖還未同步到slave節點,此時master節點掛了,發生故障轉移,slave節點被選舉為master節點,丟失了鎖。這樣其他線程就能夠獲取到該鎖,顯然是有問題的。
  • 因此,上述基于redis實現的分布式鎖只是滿足了AP,并沒有滿足C。

    三、redlock

  • redlock出現的背景:當鎖遇到故障轉移
    單實例肯定不是很可靠吧?加鎖成功之后,結果 Redis 服務宕機了,就涼了。這時候會提出來將 Redis 主從部署。即使是主從,也是存在巧合的!
    • 主從結構中存在明顯的競態:
  • 客戶端 A 從 master 獲取到鎖
  • 在 master 將鎖同步到 slave 之前,master 宕掉了。
  • slave 節點被晉級為 master 節點
  • 客戶端 B 取得了同一個資源被客戶端 A 已經獲取到的另外一個鎖。安全失效!
  • 有時候程序就是這么巧,比如說正好一個節點掛掉的時候,多個客戶端同時取到了鎖。如果你可以接受這種小概率錯誤,那用這個基于復制的方案就完全沒有問題。

    • 如果使用集群呢

    我們知道對集群進行加鎖的時候,其實是通過 CRC16 的 hash 函數來對 key 進行取模,將結果路由到預先分配過 slot 的相應節點上。發現其實還是發到單個節點上的!

    • 正是因為上述redis分布式鎖存在的一致性問題,redis作者提出了一個更加高級的基于redis實現的分布式鎖——RedLock。原文可參考 Distributed locks with Redis,也可以參考這篇文章。
  • RedLock是什么
  • RedLock是基于redis實現的分布式鎖,它能夠保證以下特性:

    • 互斥性:在任何時候,只能有一個客戶端能夠持有鎖;
    • 避免死鎖:當客戶端拿到鎖后,即使發生了網絡分區或者客戶端宕機,也不會發生死鎖;(利用key的存活時間)
    • 容錯性:只要多數節點的redis實例正常運行,就能夠對外提供服務,加鎖或者釋放鎖;

    而非redLock是無法滿足互斥性的,上面已經闡述過了原因。

  • RedLock算法
  • 假設有N個redis的master節點,這些節點是相互獨立的(不需要主從或者其他協調的系統)。N推薦為奇數。具體算法如下:

    • 注意:為什么N推薦為奇數呢?
    • 原因1:本著最大容錯的情況下,占用服務資源最少的原則,2N+1和2N+2的容災能力是一樣的,所以采用2N+1;比如,5臺服務器允許2臺宕機,容錯性為2,6臺服務器也只能允許2臺宕機,容錯性也是2,因為要求超過半數節點存活才OK。

    • 原因2:假設有6個redis節點,client1和client2同時向redis實例獲取同一個鎖資源,那么可能發生的結果是——client1獲得了3把鎖,client2獲得了3把鎖,由于都沒有超過半數,那么client1和client2獲取鎖都失敗,對于奇數節點是不會存在這個問題。

    參考文章

  • 失敗時重試
    • 當客戶端無法獲取到鎖時,應該隨機延時后進行重試,防止多個客戶端在同一時間搶奪同一資源的鎖(會導致腦裂,最終都不能獲取到鎖)。客戶端獲得超過半數節點的鎖花費的時間越短,那么腦裂的概率就越低。所以,理想的情況下,客戶端最好能夠同時(并發)向所有redis發出set命令。

    • 當客戶端從多數節點獲取鎖失敗時,應該盡快釋放已經成功獲取的鎖,這樣其他客戶端不需要等待鎖過期后再獲取。(如果存在網絡分區,客戶端已經無法和redis進行通信,那么此時只能等待鎖過期后自動釋放)

    不明白為什么會發生腦裂???

  • 釋放鎖
  • 向所有redis實例發送釋放鎖命令即可,不需要關心redis實例有沒有成功上鎖。

    redisson在加鎖的時候,key=lockName, value=uuid + threadID,采用set結構存儲,并包含了上鎖的次數(支持可重入);解鎖的時候通過hexists判斷key和value是否存在,存在則解鎖;這里不會出現誤解鎖

  • 性能、 崩潰恢復和redis同步
    • 如何提升分布式鎖的性能?以每分鐘執行多少次acquire/release操作作為性能指標,一方面通過增加redis實例可用降低響應延遲,另一方面,使用非阻塞模型,一次發送所有的命令,然后異步讀取響應結果,這里假設客戶端和redis之間的RTT差不多。

    • 如果redis沒用使用備份,redis重啟后,那么會丟失鎖,導致多個客戶端都能獲取到鎖。通過AOF持久化可以緩解這個問題。redis key過期是unix時間戳,即便是redis重啟,那么時間依然是前進的。但是,如果是斷電呢?redis在啟動后,可能就會丟失這個key(在寫入或者還未寫入磁盤時斷電了,取決于fsync的配置),如果采用fsync=always,那么會極大影響性能。如何解決這個問題呢?可以讓redis節點重啟后,在一個TTL時間段內,對客戶端不可用即可。

    四、redlock已經在最新本的redisson中被棄用了

    看著 RedLock 好像是解決問題了:

  • 客戶端 A 鎖住了集群的大多數(一半以上);
  • 客戶端 B 也要鎖住大多數;
  • 這里肯定會沖突,所以 客戶端 B 加鎖失敗。
  • 那實際解決問題了么?推薦大家閱讀兩篇文章:

    • Martin Kleppmann:How to do distributed locking

    • Salvatore(Redis 作者):Is Redlock safe?

    最終,兩方各持己見,沒有得出結論。具體的源碼分析棄用原因,可以參考這篇文章

    五、結論

    Redisson RedLock 是基于聯鎖 MultiLock 實現的,但是使用過程中需要自己判斷 key 落在哪個節點上,對使用者不是很友好。Redisson RedLock 已經被棄用,直接使用普通的加鎖即可,會基于 wait 機制將鎖同步到從節點,但是也并不能保證一致性。僅僅是最大限度的保證一致性。

    基于MultiLock 實現的分布式鎖

    總結

    以上是生活随笔為你收集整理的redisson redlock(基于redisson框架和redis集群使用分布式锁)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。