如何用Zookeeper實現分佈式鎖?

在上一篇漫畫中,小灰介紹瞭如何使用redis實現分佈式鎖。

那麼,如何用Zookeeper來實現分佈式鎖呢?

這一次我們會爲大家詳細講述。

在這裏插入圖片描述
在這裏插入圖片描述
什麼是臨時順序節點?

讓我們來回顧一下Zookeeper節點的概念:
在這裏插入圖片描述
Zookeeper的數據存儲結構就像一棵樹,這棵樹由節點組成,這種節點叫做Znode。

Znode分爲四種類型:

1.持久節點 (PERSISTENT)

默認的節點類型。創建節點的客戶端與zookeeper斷開連接後,該節點依舊存在 。

2.持久節點順序節點(PERSISTENT_SEQUENTIAL)

所謂順序節點,就是在創建節點時,Zookeeper根據創建的時間順序給該節點名稱進行編號:
在這裏插入圖片描述
3.臨時節點(EPHEMERAL)

和持久節點相反,當創建節點的客戶端與zookeeper斷開連接後,臨時節點會被刪除:
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
4.臨時順序節點(EPHEMERAL_SEQUENTIAL)

顧名思義,臨時順序節點結合和臨時節點和順序節點的特點:在創建節點時,Zookeeper根據創建的時間順序給該節點名稱進行編號;當創建節點的客戶端與zookeeper斷開連接後,臨時節點會被刪除。

在這裏插入圖片描述
在這裏插入圖片描述
Zookeeper分佈式鎖的原理

Zookeeper分佈式鎖恰恰應用了臨時順序節點。具體如何實現呢?讓我們來看一看詳細步驟:

獲取鎖

首先,在Zookeeper當中創建一個持久節點ParentLock。當第一個客戶端想要獲得鎖時,需要在ParentLock這個節點下面創建一個臨時順序節點 Lock1。
在這裏插入圖片描述
之後,Client1查找ParentLock下面所有的臨時順序節點並排序,判斷自己所創建的節點Lock1是不是順序最靠前的一個。如果是第一個節點,則成功獲得鎖。
在這裏插入圖片描述
這時候,如果再有一個客戶端 Client2 前來獲取鎖,則在ParentLock下載再創建一個臨時順序節點Lock2。
在這裏插入圖片描述
Client2查找ParentLock下面所有的臨時順序節點並排序,判斷自己所創建的節點Lock2是不是順序最靠前的一個,結果發現節點Lock2並不是最小的。

於是,Client2向排序僅比它靠前的節點Lock1註冊Watcher,用於監聽Lock1節點是否存在。這意味着Client2搶鎖失敗,進入了等待狀態。
在這裏插入圖片描述
這時候,如果又有一個客戶端Client3前來獲取鎖,則在ParentLock下載再創建一個臨時順序節點Lock3。
在這裏插入圖片描述
Client3查找ParentLock下面所有的臨時順序節點並排序,判斷自己所創建的節點Lock3是不是順序最靠前的一個,結果同樣發現節點Lock3並不是最小的。

於是,Client3向排序僅比它靠前的節點Lock2註冊Watcher,用於監聽Lock2節點是否存在。這意味着Client3同樣搶鎖失敗,進入了等待狀態。

在這裏插入圖片描述
這樣一來,Client1得到了鎖,Client2監聽了Lock1,Client3監聽了Lock2。這恰恰形成了一個等待隊列,很像是Java當中ReentrantLock所依賴的AQS(AbstractQueuedSynchronizer)。在這裏插入圖片描述
在這裏插入圖片描述
釋放鎖

釋放鎖分爲兩種情況:

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

當任務完成時,Client1會顯示調用刪除節點Lock1的指令。
在這裏插入圖片描述
2.任務執行過程中,客戶端崩潰

獲得鎖的Client1在任務執行過程中,如果Duang的一聲崩潰,則會斷開與Zookeeper服務端的鏈接。根據臨時節點的特性,相關聯的節點Lock1會隨之自動刪除。

在這裏插入圖片描述
由於Client2一直監聽着Lock1的存在狀態,當Lock1節點被刪除,Client2會立刻收到通知。這時候Client2會再次查詢ParentLock下面的所有節點,確認自己創建的節點Lock2是不是目前最小的節點。如果是最小,則Client2順理成章獲得了鎖。
在這裏插入圖片描述
同理,如果Client2也因爲任務完成或者節點崩潰而刪除了節點Lock2,那麼Client3就會接到通知。在這裏插入圖片描述
最終,Client3成功得到了鎖。
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
Zookeeper和Redis分佈式鎖的比較

下面的表格總結了Zookeeper和Redis分佈式鎖的優缺點:
在這裏插入圖片描述
有人說Zookeeper實現的分佈式鎖支持可重入,Redis實現的分佈式鎖不支持可重入,這是錯誤的觀點。兩者都可以在客戶端實現可重入邏輯。

在Apache的開源框架 Apache Curator 中,包含了對Zookeeper分佈式鎖的實現,有興趣的小夥伴可以看看源碼:
喜歡的點點關注,點點贊。

對Java技術,架構技術感興趣的朋友,歡迎加QQ羣728821520,一起學習,相互討論。
https://github.com/apache/curator/
在這裏插入圖片描述

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