這里說的集群模式為 sentinel 和 cluster 模式 (PS : 本人對於 sentinel 和 cluster 兩種集群模式還處於學習階段)
相關redLock 官方介紹(PS : 里面包含了算法的思想以及相關代碼演示)
https://redis.io/topics/distlock
對於分布式服務和分布式redis情況下, 對於分布式鎖依然要求 安全性和可用性
- 關於安全性: 根據官方介紹,根據鎖互斥的特點,要求最多只能有一個服務端client 加鎖成功
- 關於可用性:
- 避免死鎖,即使說成功獲取鎖的客戶端崩潰也不會影響到其他客戶端后續加鎖操作;
- 容錯性,即使在發生redis客戶端宕機或重啟情況下,仍然能保證服務正常加鎖和解鎖操作;
單機版 分布式鎖的實際就是利用的 "set nx ex 時間"命令來實現加鎖的操作,而對於分布式服務的控制,則是會在value中存儲客戶端相關信息來標記當前鎖所屬的服務客戶端
鎖獲取
根據redlock 算法的思想 , 其並不是利用主備節點,會嘗試操作所有的主節點,對於其加鎖的流程為按照順序依次對所有的主節點進行加鎖操作; 對於加鎖成功的標記 實際 就是分布式系統理論中的多數選舉規則,只要滿足半數以上redis客戶端加鎖成功,就認為當前服務獲取鎖成功;每個節點加鎖和釋放鎖的操作和單機版一樣
因此為了滿足多數選舉的規則,避免"腦裂"情況的發生,因此一般集群主節點要求為單數
對於當前分布式情況下redis加鎖,特別需要控制每個節點嘗試加鎖時間,原因在於 對於服務端發起加鎖請求時實際存在一個總時間限制,因此要求在每個節點上嘗試加鎖總時間不能影響到整體鎖存活時間
對於分布式情況下也會存在加鎖失敗的情況,對於加鎖失敗時就需要執行釋放鎖操作,原因是可能在多個節點已經加鎖成功,只是沒有滿足分布式最終加鎖成功的條件,因此需要去釋放當前服務所有成功獲取到單個節點上的鎖
鎖釋放
對於釋放鎖的操作和分布式加鎖的流程也是一致的也是需要順序遍歷所有的主節點,對於遍歷過程中可能會出現以下情形
- 當前節點上不存在當前key, 直接跳過
- 當前節點上存在當前key, 則需要獲取當前key中存儲的value,根據value中的相關自定義標識來判斷當前鎖是否屬於當前請求的客戶端,
- 如果屬於當前請求的客戶端,則執行刪除操作
- 反之如果不屬於,則繼續遞歸下一個節點,依次重復之前的 1,2操作,直到遍歷完全部的節點
//TODO : 具體代碼演示