分佈式鎖,是單機鎖的一種擴展,主要是爲了鎖住分佈式系統中不一樣機器代碼的物理塊或邏輯塊。以此保證不一樣機器之間的邏輯一致性。
僞代碼以下算法
if (能夠插入一條數據) { lock { if (能夠插入一條數據) { // 插入一條數據 } } }
正常代碼流程圖(markdown畫的,有點醜)設計模式
st=>start: 項目啓動 watcher=>operation: 監聽etcd ed=>end: 等待請求 st->watcher->ed
st=>start: 開始執行lock ed=>end: 結束 watcher=>operation: 監聽etcd hasEvent=>condition: 事件隊列爲空 pushEvent=>operation: 爭奪鎖事件 入等待隊列 watcherEvent=>operation: etcd節點超時事件和釋放事件 popEvent=>operation: 爭奪鎖事件 出事件隊列 execute=>operation: 執行被鎖住的代碼塊 fight=>condition: 爭奪鎖失敗 unlock=>operation: 釋放鎖 st->fight fight(no)->execute->unlock->ed fight(yes)->pushEvent->watcherEvent->popEvent->fight
事件細節僞代碼緩存
準備一個清空全部相關事件的萬能方法服務器
假設eventQueue是這種業務對應的事件隊列 假設fightEvent是該次執行的爭奪鎖事件 假設clear爲清除超時事件的方法 假設holdEvent爲持有鎖超時事件 假設waitEvent爲等待鎖超時事件 假設unLockEvent爲釋放鎖事件 // 清空全部事件 - clearAll eventQueue.remove(fightEvent) clear(waitEvent) clear(holdEvent)
監聽etcd的兩個事件markdown
// 當etcd鎖超時事件或etcd主動釋放事件發生時 // 爭奪鎖事件 出事件隊列 fightEvent = eventQueue.pop // 執行爭奪鎖事件 執行 fightEvent
爭奪鎖事件多線程
// 爭奪鎖事件 執行 etcd爭奪鎖方法 if (搶到鎖了) { // 清空全部事件 執行 clearAll // 設置持有鎖超時事件 設置 holdEvent } else { // 爭奪鎖事件若是是二次入隊列,建議到隊列頭,而不是到隊列尾 eventQueue.push(fightEvent) }
等待鎖超時事件(用時間輪延時執行)分佈式
// 清空全部事件 執行 clearAll // 拋出異常 throw new Exception
持有鎖超時事件(用時間輪延時執行)spa
// 執行釋放鎖事件 執行 unLockEvent
釋放鎖事件線程
// 釋放鎖事件 執行 etcd釋放鎖方法 // 清空全部事件 執行 clearAll
備註設計
以上代碼能夠用有限狀態機設計模式來設計業務
圖解分佈式服務器與etcd集羣交互
補充說明