分佈式鎖使用場景
- 解決業務層冪等性,防止雙次點擊(譬如更新接口)
- 解決 MQ 消費端多端接受同一消息時保證只有一端處理消息
- 使用 schedule 執行定時任務時,多實例部署時只有一臺實例執行任務
Redis
特色
- 單線程串行處理
- 獲取鎖性能特別好
- setnx 不存在則設置成功不然失敗
- 沒有心跳機制,須要設置失效時間
- CAP 中的 AP 模型,由於用的是 gossip 協議,因此不是強一致性
多個業務獲取鎖場景
鎖失效時間設置問題
鎖定了10s後過時,但業務執行了30s(可能碰到fullgc,死循環等場景)。redis
主從切換問題
業務1從主獲取鎖,此時主掛機了,從晉升爲主,剛好此時從未同步這個鎖的值 。網絡
Zookeeper
特色
- 有序節點,按排序命名節點
- 臨時節點,客戶端斷連後自動消失
- 事件監聽,節點下發生更新時會有事件通知
- ZAB 協議,強一致,屬於 CP 模型
- zk 集羣變大後,性能持續降低
多個業務獲取鎖場景
客戶端掛掉或假死
客戶端斷連會把臨時節點刪除,鎖也就隨着釋放。另外一個業務便可獲取鎖。
但其實客戶端沒掛,只是心跳維持間斷了。緣由有好多,譬如fullgc,網絡問題(redis碰到網絡問題最多獲取鎖失敗)等。分佈式
Etcd
特色
- 若是存在 Key 的話就不能寫入,也就意味着不能獲取到鎖,若是集羣中,能夠寫入 Key,就意味着獲取獲得鎖。
- Raft 保證了集羣的一致性,強一致性,而且數據是能夠進行持久化
- 沒有心跳機制,須要設置失效時間
多個業務獲取鎖場景
鎖失效時間設置問題
鎖定了10s後過時,但業務執行了30s(可能碰到fullgc,死循環等場景)。性能
使用失效時間的鎖時間續租問題
在獲取到鎖的業務線程,能夠開啓一個子線程去維護和輪訓這把鎖的有效時間,並定時的對這把鎖進行續租。
假設業務線程獲取到一把鎖,鎖的 Expire 時間爲 10s,業務線程會開啓一個子線程經過輪訓的方式每 2 秒鐘去把這把鎖進行續租,每次都將鎖的 Expire 還原到 10s。線程
存在的問題
這些問題都會致使續租線程沒法執行,從而致使鎖提早失效。排序