1. 程式人生 > 實用技巧 >ZooKeeper實現分散式鎖

ZooKeeper實現分散式鎖

目錄

ZooKeeper 的資料模型

ZooKeeper的資料模型類似於資料結構中的,也很像檔案系統

ZooKeeper的資料模型基於節點,稱為Znode。不同於樹的節點的是,Znode的引用方式通過路徑引用,類似於檔案系統。資料都儲存在記憶體中。

znode示意圖

ZNode分為四種類型:

ZNode的四種類型

  • PERSISTENT:持久節點,預設的節點型別。建立節點的客戶端與 Zookeeper 斷開連線後,該節點依舊存在。
  • EPHEMERAL: 臨時節點。和持久節點相反,當建立節點的客戶端與 Zookeeper 斷開連線後,臨時節點會被刪除。
  • PERSISTENT_SEQUENTIAL:持久順序節點。結合持久節點和順序節點特性。
  • EPHEMERAL_SEQUENTIAL:臨時順序節點。結合臨時節點和順序節點特性。

所謂順序節點,就是在建立節點時,Zookeeper 根據建立的時間順序給該節點名稱進行編號。

Zookeeper實現分散式鎖

Zookeeper 分散式鎖是利用臨時順序節點實現的。

獲取鎖

首先建立一個持久節點,作為鎖的父節點(LockParent)。當有客戶端需要獲取鎖時,在父節點下新增臨時順序節點

示意圖如下:

ZooKeeper獲取鎖

之後,客戶端查詢 LockParent 下面所有的臨時順序節點並排序,判斷自己所建立的節點 Lock1 是不是編號最小的一個。如果是,則成功獲得鎖。

這時,如果再有一個客戶端2 來獲取鎖,則在 LockParent下再建立一個臨時順序節點 Lock2。同樣對 LockParent 下面所有的臨時順序節點排序,發現 Lock2 不是編號最小的節點,於是客戶端2向排序在它前一個節點 Lock1 註冊 Watcher,用於監聽 Lock1 節點是否存在。這意味著客戶端2獲取鎖失敗,進入了等待狀態。

ZooKeeper獲取鎖失敗

釋放鎖

釋放鎖分為兩種情況:

操作完成,顯示釋放

當客戶端完成資料的操作後,顯示刪除自己建立的臨時節點。

例如:客戶端完成資料操作,顯示刪除Lock1。此時,由於客戶端2對 Lock1 註冊了 Watcher ,那麼客戶端2就會收到 Lock1 節點刪除的事件通知,然後客戶端2查詢 LockParent 下面所有的臨時順序節點並排序,判斷自己所建立的節點 Lock2 是不是編號最小的一個。如果是,則成功獲得鎖。如果不是,則向排序在它前一個節點

註冊 Watcher 。

宕機

當客戶端操作資料中途宕機了,那麼就會斷開與 ZooKeeper 伺服器的連線,那麼根據臨時順序節點的特性,節點會被自動刪除。之後的操作就同顯示刪除一樣了。

ZooKeeper 與Redis 分散式鎖對比

分散式鎖實現優點缺點
ZooKeeper1. 有封裝好的框架,容易實現
2. 有等待鎖的佇列,提升獲取鎖效率
新增、刪除臨時節點效率低
RedisSet和Del執行執行效率高1. 實現複雜,需要考慮原子性、超時、誤刪等情況
2. 沒有等待鎖的佇列,需要客戶端自旋獲取鎖,效率低

注:等待鎖的佇列是指 LockParent 下的臨時節點按照編號排序形成的列表,總是編號小(先建立)的先刪除,類似佇列FIFO特性。

我的更多文章盡在我的個人部落格