ZooKeeper實現分散式鎖
目錄
ZooKeeper 的資料模型
ZooKeeper的資料模型類似於資料結構中的樹
,也很像檔案系統
。
ZooKeeper的資料模型基於節點,稱為Znode。不同於樹的節點的是,Znode的引用方式通過路徑
引用,類似於檔案系統。資料都儲存在記憶體中。
ZNode分為四種類型:
ZNode的四種類型
- PERSISTENT:持久節點,預設的節點型別。建立節點的客戶端與 Zookeeper 斷開連線後,該節點依舊存在。
- EPHEMERAL: 臨時節點。和持久節點相反,當建立節點的客戶端與 Zookeeper 斷開連線後,臨時節點會被刪除。
- PERSISTENT_SEQUENTIAL:持久順序節點。結合持久節點和順序節點特性。
- EPHEMERAL_SEQUENTIAL:臨時順序節點。結合臨時節點和順序節點特性。
所謂順序節點,就是在建立節點時,Zookeeper 根據建立的時間順序給該節點名稱進行編號。
Zookeeper實現分散式鎖
Zookeeper 分散式鎖是利用臨時順序節點
實現的。
獲取鎖
首先建立一個持久節點,作為鎖的父節點(LockParent)。當有客戶端需要獲取鎖時,在父節點下新增臨時順序節點
。
示意圖如下:
之後,客戶端查詢 LockParent 下面所有的臨時順序節點並排序,判斷自己所建立的節點 Lock1 是不是編號最小的一個。如果是,則成功獲得鎖。
這時,如果再有一個客戶端2 來獲取鎖,則在 LockParent下再建立一個臨時順序節點 Lock2。同樣對 LockParent 下面所有的臨時順序節點排序,發現 Lock2 不是編號最小的節點,於是客戶端2向排序在它前一個節點
Lock1 註冊 Watcher,用於監聽 Lock1 節點是否存在。這意味著客戶端2獲取鎖失敗,進入了等待狀態。
釋放鎖
釋放鎖分為兩種情況:
操作完成,顯示釋放
當客戶端完成資料的操作後,顯示刪除自己建立的臨時節點。
例如:客戶端完成資料操作,顯示刪除Lock1。此時,由於客戶端2對 Lock1 註冊了 Watcher ,那麼客戶端2就會收到 Lock1 節點刪除的事件通知,然後客戶端2查詢 LockParent 下面所有的臨時順序節點並排序,判斷自己所建立的節點 Lock2 是不是編號最小的一個。如果是,則成功獲得鎖。如果不是,則向排序在它前一個節點
宕機
當客戶端操作資料中途宕機了,那麼就會斷開與 ZooKeeper 伺服器的連線,那麼根據臨時順序節點的特性,節點會被自動刪除。之後的操作就同顯示刪除一樣了。
ZooKeeper 與Redis 分散式鎖對比
分散式鎖實現 | 優點 | 缺點 |
---|---|---|
ZooKeeper | 1. 有封裝好的框架,容易實現 2. 有等待鎖的佇列,提升獲取鎖效率 | 新增、刪除臨時節點效率低 |
Redis | Set和Del執行執行效率高 | 1. 實現複雜,需要考慮原子性、超時、誤刪等情況 2. 沒有等待鎖的佇列,需要客戶端自旋獲取鎖,效率低 |
注:等待鎖的佇列是指 LockParent 下的臨時節點按照編號排序形成的列表,總是編號小(先建立)的先刪除,類似佇列FIFO特性。
我的更多文章盡在:我的個人部落格