在閱讀ZooKeeper的recipe for lock時,我感到困惑。看起來,這個分佈式鎖的配方不能保證「任何時間的快照,沒有兩個客戶端認爲他們擁有相同的鎖」。但是由於ZooKeeper得到了廣泛的採用,如果參考文檔中有這樣的錯誤,應該早有人指出它,那麼我誤解了什麼?關注動物園管理員的鎖定配方
報價the recipe for distributed locks:
鎖
完全分佈式的鎖是全球同步的,在任何時間快照含義沒有兩個客戶認爲他們持有相同的鎖。這些可以使用ZooKeeeper來實現。與優先級隊列一樣,首先定義一個鎖定節點。
- 調用Create()與 「locknode/GUID的鎖相」 的路徑和順序和短暫的標誌設置。
- 在鎖定節點上調用getChildren()而不設置監視標誌(這對於避免羣效應很重要)。
- 如果在步驟1中創建的路徑名具有最低的序列號後綴,則客戶端具有該鎖並且客戶端退出該協議。
- 客戶端調用exists(),並在鎖目錄的路徑中設置具有次低序號的watch標誌。
- 如果存在()返回false,則轉到步驟2。否則,等待來自前面步驟的路徑通知之前執行步驟2
考慮以下情況:
- Client1通過ZooKeeper節點「locknode/guid-lock-0」成功獲取鎖定(步驟3);
- Client2創建節點「locknode/guid-lock-1」,未能獲取該鎖,現在正在觀看「locknode/guid-lock-0」;
- 之後,出於某種原因(比如網絡擁塞),Client1未能及時向ZooKeeper集羣發送心跳消息,但Client1仍在工作,錯誤地認爲它仍然保持鎖定狀態。
但是,動物園管理員可能會認爲客戶端1的會話超時,然後
- 刪除「locknode/GUID-鎖0」,
- 發送通知到客戶機2(或者先發的通知? ),
- 但不能及時向客戶端1發送「會話超時」通知(例如,由於網絡擁塞)。
- 客戶機2得到通知,進到步驟2,得到的唯一節點「」 locknode/GUID-鎖定-1" ,它創建本身;因此,客戶機2將假定它持有鎖
- 但在同時,Client1認爲它擁有該鎖。
這是一個有效的方案嗎?
關於_zookeeper-users_郵件列表的平行討論:http://thread.gmane.org/gmane.comp.java.hadoop.zookeeper.user/5065 – seh