一、引言
我們先來談談分布式鎖,為什麼要有分布式鎖呢? 實現 jdk 提供的 synchronized、lock 等鎖不是很好嗎? 這是因為在單程序的情況下,多個執行緒訪問同乙個資源,可以使用 synchronized 和 lock 來實現; 在多個程序的情況下,即在分布式的情況下,需要使用分布式鎖來實現對同一資源的併發請求。 Redisson 元件可以實現 Redis 的分布式鎖,Redisson 也是官方推薦的 Redis 分布式鎖實現方案,封裝後讓使用者實現分布式鎖更加方便簡潔。
2. 分布式鎖的特點
相互排斥任何時候,只有乙個客戶端可以獲取乙個鎖,並且沒有兩個客戶端可以同時獲取乙個鎖。 身份鎖只能由持有鎖的客戶端刪除,不能由其他客戶端刪除。 重入持有鎖的客戶端可以繼續鎖定鎖並續訂鎖。 容錯當乙個鎖失敗(超過其生命週期結束時)時,鎖會自動釋放(金鑰無效),其他客戶端可以繼續獲取該鎖以防止死鎖。 3. Redisson分布式鎖原理
在下文中,我們從五個方面分析了雷迪森分布式鎖的原理:鎖機制、鎖互斥機制、鎖更新機制、可重入鎖機制和鎖釋放機制。
3.0 整體分析
注意:Redisson 版本 324.4-snapshot
**微信***老周聊天架構】*公共類RedissonLockTest終於 }
初始化 redissonlock
** 鎖定方式 * param leasetime 鎖定過期時間(-1:使用預設值 30 秒) *param 單位時間單位 * param 可以中斷 * 丟擲 interruptedException * private void lock(long leasetime, timeunit unit, boolean interruptibly) 丟擲 interruptedexception 訂閱分布式鎖,解鎖時通知。 completablefuture future = subscribe(threadid); pubsub.timeout(future); redissonlockentry entry;如果 (interruptablely) else try waiting for message 如果鎖過期時間大於零,則執行具有過期時間的阻塞取取。 if (ttl >= 0) catch (interruptedexception e) entry.getlatch().tryacquire(ttl, timeunit.milliseconds); else else }finally }
當鎖定超時時間為 -1 且成功獲取鎖定時,將啟動看門狗定時任務,自動續訂鎖定
每次續鎖時,都需要判斷鎖是否已經鬆開,如果續鎖成功,您將再次安排自己繼續續鎖操作。
為了保證原子性,見31 鎖定機構。
3.1 鎖定機構。
鎖定機制的核心就是這一部分,其中 lua 指令碼被包裹在 redisoon 中,最後通過 netty 傳輸。
rfuture trylockinnerasync(long waittime, long leasetime, timeunit unit, long threadid, redisstrictcommand command)
當你去乙個波時,斷點很清楚:
keys[1]) 鍵ar**[1]:金鑰的存活時間,預設為 30 秒。
ar**[2]:鎖定的客戶端 ID (uuidrandomuuid())threadid)
上一段中帶鎖的 lua 指令碼的作用是:第乙個 if 判斷語句是使用 exists mylock 命令來判斷,如果要鎖定的鎖鍵不存在(第乙個鎖)或者鍵的字段存在(reentrant lock),則將其鎖定。 如何鎖定它? 使用 hincrby 命令設定雜湊結構,類似於在 Redis 中執行的操作,如下所示:
整個 lua 指令碼鎖定過程如下圖所示:
如您所見,最新版本的邏輯比以前的版本更簡單、更清晰。
3.2 鎖定互斥機制
此時,如果客戶端 2 嘗試鎖定它,該怎麼辦? 首先,第乙個 if 判斷將執行存在 mylock,並且會發現鎖鍵 mylock 已經存在。 那麼第二個if判斷就是判斷mylock鎖鍵的雜湊資料結構是否包含客戶端2的ID,這顯然不是,因為它包含了客戶端1的ID。 因此,客戶端 2 執行:
return redis.call('pttl', keys[1]);
返回的數字,表示 mylock 金鑰的剩餘生存時間。
鎖互斥機制實際上是主要過程3.0 整體分析你可以看到這個組織redisson.redissonlock#lock(long, j**a.util.concurrent.timeunit,布林值)。
3.3 鎖倉續期機制
客戶端 1 新增的鎖鍵預設生存時間為 30 秒,如果超過 30 秒,客戶端 1 想要保留鎖應該怎麼做?
Redisson 提供了一種續訂機制,該機制在客戶端 1 被鎖定後立即啟動看門狗。
3.4 再入鎖定機構
看門狗機制實際上是乙個後台排程任務執行緒,在成功獲取鎖後,持有鎖的執行緒會被放入乙個redissonbaselock中過期續費對映,然後每 10 秒檢查一次(internallockleasetime 3),客戶端 1 是否仍然持有鎖鍵(判斷客戶端是否還持有金鑰,其實就是遍歷過期續費對映中的執行緒 ID,然後根據執行緒 ID 在 redis 中檢查,如果存在, 鑰匙的時間會延長),然後鎖會不斷延長鑰匙的壽命。
注意:3.5 鎖定釋放機制如果服務宕機,看門狗機制執行緒會消失,金鑰的過期時間不會延長,30s後會自動過期,其他執行緒可以拿到鎖。
如果呼叫具有過期時間的鎖定方法,則監視程式任務不會啟動以自動續訂。
確定 keys[1] 中是否存在 ar**[3]。"if (redis.call('hexists', keys[1], ar**[3]) == 0) then " + "return nil;" +"end; "+ 替換 ar**[3] val - 1 中的鍵 [1]"local counter = redis.call('hincrby', keys[1], ar**[3], 1); "+ 如果返回值大於 0,則證明它是可重入鎖"if (counter > 0) then "+ 重置過期時間"redis.call('pexpire', keys[1], ar**[2]);" + "return 0; " +"else "+ 刪除鍵[1]。"redis.call('del', keys[1]);"+ 等待執行緒或程序資源可用的通知阻止"redis.call('publish', keys[2], ar**[1]);" + "return 1; " +"end; " +"return nil;"
keys[1]: mylock同樣,鎖釋放斷點也會出現波浪:keys[2]: redisson_lock_channel:
ar**[1]: 0
ar**[2]:30000(過期時間)。
ar**[3]: 66a84a47-3960-4f3e-8ed7-ea2c1061e4cf:1 (雜湊中的鎖定字段)。
鎖釋放機制摘要:
移除鎖(注意此處的可重入鎖)會廣播一條訊息以釋放鎖,通知阻塞等待過程(到名為 Redisson Lock Channel 的通道:發布解鎖訊息)以取消看門狗機制,即 RedissonLock刪除到期續費對映中的執行緒 ID,並取消 Netty 的定時任務執行緒。
四、主從Redis架構中分布式鎖的問題
執行緒 A 向主 Redis 請求分布式鎖,並成功獲取該鎖。 當主 Redis 準備同步來自主 Redis 的鎖資訊時,主 Redis 突然關閉,鎖丟失。 觸發從 Redis 到新主 Redis 的公升級; 執行緒 B 從後繼 Redis 的 Slave Redis 申請分布式鎖,可以成功獲取該鎖。 這樣一來,兩個客戶端同時獲取相同的分布式鎖,沒有獨佔使用功能; 為了解決這個問題,Redis 引入了紅鎖的概念。
您需要準備多個Redis例項,這些例項彼此完全獨立,並且這些節點之間沒有主從關係。 當客戶端申請分布式鎖時,需要向所有Redis例項傳送乙個應用,只有當超過一半的Redis例項報告鎖已成功獲取時,才能認為該鎖已獲得。 與大多數保證一致性的演算法類似,這是多數原則。
public static void main(string args) finally }
當然,RedLock演算法是毋庸置疑的,兩位神仙在幾年前就吵過架,有興趣的話可以去Redis官網檢視一下Martin Kleppmann和Redis作者Antirez的爭論。
好吧,我想收集它,如果繼續談論它,我感覺我無法繞過分布式經典問題上限。
5. 分布式鎖選擇
如果想要強一致性,可以選擇 zk 的分布式鎖,但是 zk 的效能會在一定程度上下降,如果專案不使用 zk,那就選擇 redis 的分布式鎖,比較你的效能為那個非常小的概率,引入乙個元件是不划算的,如果不能容忍 redis 的紅鎖缺陷, 然後你可以自己在業務中保證。
以下是幾種常見的分布式鎖選擇的比較:
如果您喜歡這篇文章,請點選右上角與您的朋友分享文章。
想要了解學習的技術要點,請留言若飛安排分享。
由於***推送規則變更,請點選“觀看”並新增“星標”,即可第一時間獲得精彩技術分享
·end·
相關閱讀:
了解微服務架構路線的圖表:基於Spring Cloud的微服務架構分析:微服務等於Spring Cloud? 了解微服務架構和框架如何構建基於 DDD 的域驅動型微服務? 對於乙個小團隊來說,引入SpringCloud微服務真的很合適嗎? DDD興起的原因及其與微服務的關係呼叫微服務的最佳方式微服務架構設計總結基於Kubernetes的微服務專案設計與實現微服務架構-設計總結為什麼微服務必須有閘道器? 主流微服務全鏈路監控系統之戰,詳細講解了微服務架構的實現原理,微服務的介紹和技術棧,設計了微服務場景下的資料一致性解決方案,設計了容錯微服務架構作者: riemannchow*:老周談建築。
版權宣告:內容**網路,僅供學習和研究使用,版權歸原作者所有。 如有侵權,請告知我們,我們將立即刪除並道歉。 謝謝!