redis分布式锁实现原理_redis分布式锁实现分析与实践
前言: 在分布式環境中, 我們有些情況下需要使用到鎖進行并發控制, 可供基于的 redis, zookeeper,mysql類數據庫 基于數據庫類的實現是樂觀鎖, 基于redis,zookeeper的實現可以認為是悲觀鎖.. 樂觀鎖與悲觀鎖最根本的區別是在于線程之間是否相互阻塞.
背景:一個訂單,客戶正在前臺修改地址,管理員在后臺同時修改備注。地址和備注字段的修改,都必須正確更新,這二個請求同時到達的話,如果不借助db的事務,很容易造成行鎖競爭,但用事務的話,db的性能顯然比不上redis輕量。
解決思路:A,B二個請求,誰先搶到分布式鎖(假設A先搶到鎖),誰先處理,搶不到的那個(即:B),在一旁不停等待重試,重試期間一旦發現獲取鎖成功,即表示A已經處理完,把鎖釋放了。這時B就可以繼續處理了。
但有二點要注意:
a、需要設置等待重試的最長時間,否則如果A處理過程中有bug,一直卡死, 或宕機,或者未能正確釋放鎖,B就一直會等待重試,但是又永遠拿不到鎖。
b、等待最長時間,必須小于鎖的過期時間。否則,假設鎖2秒過期自動釋放,但是A還沒處理完(即:A的處理時間大于2秒),這時鎖會因為redis key過期“提前”誤釋放,B重試時拿到鎖,造成A,B同時處理。(注:可能有同學會說,不設置鎖的過期時間,不就完了么?理論上講,確實可以這么做,但是如果業務代碼有bug,導致處理完后沒有unlock,或者根本忘記了unlock,分布式鎖就會一直無法釋放。所以綜合考慮,給分布式鎖加一個“保底”的過期時間,讓其始終有機會自動釋放,更為靠譜)
那在設計上到底如何實現呢,直接上可用的:
從redis2.6.12版開始, redis為set命令增加(set [key] NX/XX EX/PX [expiration]);
- EX seconds – 設置鍵key的過期時間,單位時秒
- PX milliseconds – 設置鍵key的過期時間,單位時毫秒
- NX – 只有鍵key不存在的時候才會設置key的值
- XX – 只有鍵key存在的時候才會設置key的值
set mylock nx ex 10 加鎖
為了防止死鎖,redis至少設置一個過期時間,: 一旦設置過期時間就引申出來以下情況: - 當鎖自動釋放了,但是程序并沒有執行完畢這個做發有二種: 1)加鎖與釋放鎖控制中間邏輯, 使其在可控時間內執行完(這個有些廢話了).2)在還沒有釋放的時候,給這個鎖續上時間, 比如這次枷鎖需要執行20分鐘, 過期時間設置的10秒, 那就可以使用一個線程每過5秒檢測一下這個鎖是否被我這個進程枷鎖,如果是并且檢測出來過期時間小于5秒, 給這個鎖續上10秒. 那引發了一個問題:怎么知道這個鎖是否被本進程鎖著呢,
這時候value值派上用場了 set mylock my+threadID+隨機數 nx ex 10 我在這里value使用 serverid + 進程ID+ 隨機數 這樣確保唯一性, 光使用進程ID會重的的
這樣做的好處在于:
1) 每個獲取redis鎖的線程應該釋放自己獲取到的鎖,而不是其他線程的.
2) 在釋放鎖的時候需要判斷當前鎖是否屬于自己,如果屬于自己才釋放,這里涉及到邏輯判斷語句,至少是兩個操作在進行,那么我們需要考慮這兩個操作要在一個原子內執行,否者在兩個行為之間可能會有其他線程插入執行,導致程序紊亂
如果你這樣做基本就可以滿足一般的需求了.
我們來分析一下:redlock
- 更可靠的鎖; 單實例的redis(這里指只有一個master節點)往往是不可靠的,雖然實現起來相對簡單一些,但是會面臨著宕機等不可用的場景,即使在主從復制的時候也顯得并不可靠(因為redis的主從復制往往是異步的)。 文章分析得出,這種算法只需具備3個特性就可以實現一個最低保障的分布式鎖。
- 安全屬性(Safety property): 獨享(相互排斥)。在任意一個時刻,只有一個客戶端持有鎖。
- 活性A(Liveness property A): 無死鎖。即便持有鎖的客戶端崩潰(crashed)或者網絡被分裂(gets partitioned),鎖仍然可以被獲取。
- 活性B(Liveness property B): 容錯。 只要大部分Redis節點都活著,客戶端就可以獲取和釋放鎖.
第一點安全屬性意味著悲觀鎖(互斥鎖)是我們做redis分布式鎖的前提,否者將可能造成并發;
第二點表明為了避免死鎖,我們需要設置鎖超時時間,保證在一定的時間過后,鎖可以重新被利用;
第三點是說對于客戶端來說,獲取鎖和手動釋放鎖可以有更高的可靠性。
更進一步分析,結合上文提到的關鍵問題,這里可以引申出另外的兩個問題:
- 怎么才能合理判斷程序真正處理的有效時間范圍?(這里有個時間偏移的問題)
- redis Master節點宕機后恢復(可能還沒有持久化到磁盤)、主從節點切換,(N/2)+1這里的N應該怎么動態計算更合理?
接下來再看,redis作者對redlock的解說:
總結
以上是生活随笔為你收集整理的redis分布式锁实现原理_redis分布式锁实现分析与实践的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: bootstrap项目实例_Spring
- 下一篇: eslint git提交不上_Git常用