Zookeeper是如何實現分佈式鎖的

Zookeeper是如何實現分佈式鎖的

標籤 : Zookeeper 分佈式redis


實現分佈式鎖要考慮的重要問題

1. 三個核心要素

加鎖, 解鎖, 鎖超時數據庫

2. 三個問題

  • 要保證原子性操做, 加鎖和鎖超時的操做要一次性執行完畢
  • 防止誤刪鎖
  • 在誤刪的基礎上, 加一個守護線程, 爲鎖續命.

什麼是臨時順序節點


Zookeeper的數據存儲結構就像是一棵樹, 這棵樹由節點組成, 這種節點叫作Znode. Znode分爲四種類型.服務器

1. 持久節點(Persistent)

默認的節點類型, 建立節點的客戶端和Zookeeper斷開鏈接以後, 該節點依舊存在.框架

2. 持久順序節點(Persistent Sequential)

所謂順序節點, 就是在建立節點的時候, Zookeeper根據節點的建立時間順序給節點的名稱進行編號.分佈式

順序持久節點

3. 臨時節點(Ephemeral)

和持久節點相反, 當建立節點的客戶端與Zookeeper斷開鏈接以後,臨時節點會被刪除.性能

建立臨時節點
斷開客戶端
刪除臨時節點

4. 臨時順序節點(Ephemeral Sequential)

在建立節點時, Zookeeper根據建立的時間順序給該節點名稱進行編號; 當建立節點的客戶端與Zookeeper斷開鏈接以後,臨時節點會被刪除.線程


Zookeeper實現分佈式鎖的原理

上面已經說了Znode的四種類型, 其中最後一種類型 臨時順序節點 是最有利於實現Zookeeper分佈式鎖的.3d


1. 獲取鎖

  • 首先, 在Zookeeper當中建立一個持久節點ParentLock. 當第一個客戶端想要得到操做某項數據的鎖的時候,須要在該持久節點之下簡歷一個臨時順序節點Lock1.

客戶端1嘗試得到所

  • 以後, 客戶端1 查找ParentLock下面全部的臨時順序節點並按照大小排序, 判斷本身所建立的節點Lock1是否是順序最靠前的一個. 若是是第一個節點,則成功得到鎖.

客戶端1成功得到所

  • 此時, 客戶端2 前來獲取該項數據的鎖, 則在ParentLock下再建立一個臨時順序節點Lock2.

客戶端2嘗試得到鎖

  • 客戶端2 查找ParentLock下面全部的臨時順序節點並排序,發現本身的Lock2節點並非最靠前的. 因而客戶端2向排序僅僅比它靠前的Lock1註冊Watcher, 用於監聽Lock1動態. 這意味着 Lock2搶鎖失敗, 進入等待狀態.

Lock2搶鎖失敗

  • 此時, 若是有一個客戶端3前來獲取鎖, 則在ParentLock下在建立一個臨時順序節點Lock3.

Lock3嘗試得到鎖

  • 客戶端3查找ParentLock下面全部的臨時順序節點並排序, 判斷本身所建立的節點Lock3是否是順序最靠前的一個, 結果發現Lock3不是最靠前的. 因而客戶端3一樣搶鎖失敗, 進入了等待狀態.

Lock搶鎖失敗

  • 這個時候客戶端1獲得了鎖, 客戶端2監聽了客戶端1, 客戶端3監聽了客戶端2. 這樣恰好造成一個等待的隊列.

2. 釋放鎖

釋放鎖有兩種狀況code

2.1 任務完成, 客戶端顯示釋放

  • 當任務完成時, 客戶端1會顯示的調用刪除節點Lock1的指令.

客戶端1釋放鎖

2.2 任務執行過程當中, 客戶端崩潰

  • 得到鎖的客戶端1在執行任務的過程當中, 若是崩潰, 則會斷開和Zookeeper服務器的連接, 根據臨時節點的特性, 相關聯的Lock1會隨之自動刪除.

客戶端1崩潰,自動釋放鎖

3. 得到鎖

  • 因爲客戶端2一直在監聽Lock1的狀態,這個時候發現Lock1註銷了, 客戶端2會當即接收到通知. 這個時候客戶端2會再次查詢ParentLock下的全部節點, 確認本身所建立的節點是否是最小的節點, 若是是最小的則成功得到鎖.

客戶端2成功得到鎖

同理可推至客戶端3


總結

Zookeeper和Redis分佈式鎖的比較

分佈式鎖 優勢 缺點
Zookeeper 1.有封裝好的框架,容易實現.
2.有等待鎖的機制(Watcher),能夠提升搶鎖的效率,好處多多
添加和刪除節點的性能比較低
Redis SetDel的性能比較高(畢竟鍵值數據庫,Hash) 1.實現複雜,須要考慮原子性,誤刪等狀況.2.沒有等待鎖的機制,只能經過客戶端的自旋來等鎖,效率低下.
相關文章
相關標籤/搜索