Zookeeper實現分佈式鎖 & 分佈鎖的對比

一、四種節點

Zookeeper的數據存儲結構就像一棵樹,這棵樹由節點組成,這種節點叫做Znode。Znode分爲四種類型:
1.持久節點(PERSISTENT):默認的節點類型。創建節點的客戶端與zookeeper斷開連接後,該節點依舊存在。
2.持久節點順序節點(PERSISTENT_SEQUENTIAL):在創建節點時,Zookeeper根據創建的時間順序給該節點名稱進行編號。
3.臨時節點(EPHEMERAL):和持久節點相反,當創建節點的客戶端與zookeeper斷開連接後,臨時節點會被刪除。
4.臨時順序節點(EPHEMERAL_SEQUENTIAL):在創建節點時,Zookeeper根據創建的時間順序給該節點名稱進行編號;當創建節點的客戶端與zookeeper斷開連接後,臨時節點會被刪除。 

                     Zookeeper的數據結構

                               順序節點

                       臨時節點1

                    臨時節點2

                          臨時節點3

二、Zookeeper分佈式鎖的原理

Zookeeper分佈式鎖應用了臨時順序節點。具體實現步驟如下:1.獲取鎖;2.釋放鎖

1、獲取鎖

(1)在Zookeeper當中創建一個持久節點ParentLock。當第一個客戶端想要獲得鎖時,需要在ParentLock這個節點下面創建一個臨時順序節點Lock1。
(2)Client1查找ParentLock下面所有的臨時順序節點並排序,判斷自己所創建的節點Lock1是不是順序最靠前的一個。如果是第一個節點,則成功獲得鎖。
(3)Client2查找ParentLock下面所有的臨時順序節點並排序,判斷自己所創建的節點Lock2是不是順序最靠前的一個,結果發現節點Lock2並不是最小的。於是,Client2向排序僅比它靠前的節點Lock1註冊Watcher,用於監聽Lock1節點是否存在。這意味着Client2搶鎖失敗,進入了等待狀態。
(4)這時候,如果又有一個客戶端Client3前來獲取鎖,則在ParentLock下載再創建一個臨時順序節點Lock3。Client3查找ParentLock下面所有的臨時順序節點並排序,判斷自己所創建的節點Lock3是不是順序最靠前的一個,結果同樣發現節點Lock3並不是最小的。於是,Client3向排序僅比它靠前的節點Lock2註冊Watcher,用於監聽Lock2節點是否存在。這意味着Client3同樣搶鎖失敗,進入了等待狀態。
這樣一來,Client1得到了鎖,Client2監聽了Lock1,Client3監聽了Lock2。這恰恰形成了一個等待隊列,很像是Java當中ReentrantLock所依賴的AQS(AbstractQueuedSynchronizer)。


 2、釋放鎖

釋放鎖分爲兩種情況:1.任務完成,客戶端顯示釋放; 2.任務執行過程中,客戶端崩潰
(1)當任務完成時,Client1會顯示調用刪除節點Lock1的指令。

(2)獲得鎖的Client1在任務執行過程中,如果Duang的一聲崩潰,則會斷開與Zookeeper服務端的鏈接。根據臨時節點的特性,相關聯的節點Lock1會隨之自動刪除。
由於Client2一直監聽着Lock1的存在狀態,當Lock1節點被刪除,Client2會立刻收到通知。這時候Client2會再次查詢ParentLock下面的所有節點,確認自己創建的節點Lock2是不是目前最小的節點。如果是最小,則Client2順理成章獲得了鎖。同理,如果Client2也因爲任務完成或者節點崩潰而刪除了節點Lock2,那麼Client3就會接到通知。最終,Client3成功得到了鎖。

 

三、Zookeeper和Redis分佈式鎖的比較

從理解的難易程度角度(從低到高):數據庫 > 緩存(Redis) > Zookeeper
從實現的複雜性角度(從低到高):Zookeeper >= 緩存(Redis) > 數據庫
從性能角度(從高到低):緩存(Redis) > Zookeeper >= 數據庫
從可靠性角度(從高到低):Zookeeper > 緩存(Redis) > 數據庫

分佈式鎖 優點 缺點
Zookeeper

1.有封裝好的框架,容易實現;

2.有等待所得隊列,大大提升搶鎖的效率

添加和刪除節點性能較低
Redis set和del指令的性能較高

1.實現複雜,需要考慮超時,原子性,誤刪等情形;  

2.沒有等待鎖的隊列,只能在客戶端自旋來等鎖,效率低下

有人說Zookeeper實現的分佈式鎖支持可重入,Redis實現的分佈式鎖不支持可重入,這是錯誤的觀點兩者都可以在客戶端實現可重入邏輯。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章