分布式鎖02 zookeeper

2021-08-28 08:00:25 字數 2517 閱讀 9881

一.簡介

zookeeper 是google 的 chubby乙個開源的實現,是 hadoop 的分布式協調服務。

它包含乙個簡單的原語集,分布式應用程式可以基於它實現同步服務,配置維護和命名服務等。

為什麼使用zookeeper:

大部分分布式應用需要乙個主控、協調器或控制器來管理物理分布的子程序(如資源、任務分配等)

目前,大部分應用需要開發私有的協調程式,缺乏乙個通用的機制

協調程式的反覆編寫浪費,且難以形成通用、伸縮性好的協調器

zookeeper:提供通用的分布式鎖服務,用以協調分布式應用

zookeeper能幫我們做什麼?

hadoop2.0,使用zookeeper的事件處理確保整個集群只有乙個活躍的namenode,儲存配置資訊等。

hbase,使用zookeeper的事件處理確保整個集群只有乙個hmaster,察覺hregionserver聯機和宕機,儲存訪問控制列表等。

二.分布式鎖

分布式鎖,這個主要得益於zookeeper為我們保證了資料的強一致性。鎖服務可以分為兩類,乙個是保持獨佔,另乙個是控制時序。

所謂保持獨佔,就是所有試圖來獲取這個鎖的客戶端,最終只有乙個可以成功獲得這把鎖。通常的做法是把zk上的乙個znode看作是一把鎖,通過 create znode的方式來實現。所有客戶端都去建立 /distribute_lock 節點,最終成功建立的那個客戶端也即擁有了這把鎖。

控制時序,就是所有檢視來獲取這個鎖的客戶端,最終都是會被安排執行,只是有個全域性時序了。做法和上面基本類似,只是這裡 /distribute_lock 已經預先存在,客戶端在它下面建立臨時有序節點(這個可以通過節點的屬性控制:createmode.ephemeral_sequential來指定)。zk的父節點(/distribute_lock)維持乙份sequence,保證子節點建立的時序性,從而也形成了每個客戶端的全域性時序。

三.zookeeper的幾個性質

1.有序節點:假如當前有乙個父節點為/lock,我們可以在這個父節點下面建立子節點;zookeeper提供了乙個可選的有序特性,例如我們可以建立子節點「/lock/node-」並且指明有序,那麼zookeeper在生成子節點時會根據當前的子節點數量自動新增整數序號,也就是說如果是第乙個建立的子節點,那麼生成的子節點為/lock/node-0000000000,下乙個節點則為/lock/node-0000000001,依次類推。

2.臨時節點:客戶端可以建立乙個臨時節點,在會話結束或者會話超時後,zookeeper會自動刪除該節點。

3.事件監聽:在讀取資料時,我們可以同時對節點設定事件監聽,當節點資料或結構變化時,zookeeper會通知客戶端。當前zookeeper有如下四種事件:1)節點建立;2)節點刪除;3)節點資料修改;4)子節點變更。

四.zookeeper實現分布式鎖

假設鎖空間的根節點為/lock:

1.客戶端連線zookeeper,並在/lock下建立臨時的且有序的子節點,第乙個客戶端對應的子節點為/lock/lock-0000000000,第二個為/lock/lock-0000000001,以此類推。

2.客戶端獲取/lock下的子節點列表,判斷自己建立的子節點是否為當前子節點列表中序號最小的子節點,如果是則認為獲得鎖,否則監聽/lock的子節點變更訊息,獲得子節點變更通知後重複此步驟直至獲得鎖;

3.執行業務**;

4.完成業務流程後,刪除對應的子節點釋放鎖。

步驟1中建立的臨時節點能夠保證在故障的情況下鎖也能被釋放,考慮這麼個場景:假如客戶端a當前建立的子節點為序號最小的節點,獲得鎖之後客戶端所在機器宕機了,客戶端沒有主動刪除子節點;如果建立的是永久的節點,那麼這個鎖永遠不會釋放,導致死鎖;由於建立的是臨時節點,客戶端宕機後,過了一定時間zookeeper沒有收到客戶端的心跳包判斷會話失效,將臨時節點刪除從而釋放鎖。

另外細心的朋友可能會想到,在步驟2中獲取子節點列表與設定監聽這兩步操作的原子性問題,考慮這麼個場景:客戶端a對應子節點為/lock/lock-0000000000,客戶端b對應子節點為/lock/lock-0000000001,客戶端b獲取子節點列表時發現自己不是序號最小的,但是在設定***前客戶端a完成業務流程刪除了子節點/lock/lock-0000000000,客戶端b設定的***豈不是丟失了這個事件從而導致永遠等待了?這個問題不存在的。因為zookeeper提供的api中設定***的操作與讀操作是原子執行的,也就是說在讀子節點列表時同時設定***,保證不會丟失事件。

最後,對於這個演算法有個極大的優化點:假如當前有1000個節點在等待鎖,如果獲得鎖的客戶端釋放鎖時,這1000個客戶端都會被喚醒,這種情況稱為「羊群效應」;在這種羊群效應中,zookeeper需要通知1000個客戶端,這會阻塞其他的操作,最好的情況應該只喚醒新的最小節點對應的客戶端。應該怎麼做呢?在設定事件監聽時,每個客戶端應該對剛好在它之前的子節點設定事件監聽,例如子節點列表為/lock/lock-0000000000、/lock/lock-0000000001、/lock/lock-0000000002,序號為1的客戶端監聽序號為0的子節點刪除訊息,序號為2的監聽序號為1的子節點刪除訊息。

可以直接使用curator這個開源專案提供的zookeeper分布式鎖實現

參考:

zookeeper分布式鎖

方案1 演算法思路 利用名稱唯一性,加鎖操作時,只需要所有客戶端一起建立 test lock節點,只有乙個建立成功,成功者獲得鎖。解鎖時,只需刪除 test lock節點,其餘客戶端再次進入競爭建立節點,直到所有客戶端都獲得鎖。特點 這種方案的正確性和可靠性是zookeeper機制保證的,實現簡單。...

zookeeper分布式鎖

zookeeper節點有4個型別 1.持久型 2.瞬時型 3.持久自動排序型 4.瞬時自動排序型 分布式鎖利用的就是zookeeper中瞬時自動排序型節點特性。一 瞬時自動排序節點 瞬時特點為,當客戶端斷開連線的時候,該節點自動消除。自動排序則為,如果節點名字重複,則自動在該節點名字後新增數字,該數...

zookeeper 分布式鎖

分布式鎖肯定是用在分布式環境下。在分布式環境下,使用分布式鎖的目的也是保證同一時刻只有乙個執行緒來修改共享變數,修改共享快取 前景 jdk提供的鎖只能保證執行緒間的安全性,但分布式環境下,各節點之間的執行緒同步執行卻得不到保障,分布式鎖由此誕生。實現方式有以下幾種 基於資料庫實現分布式鎖 基於快取 ...