一、前言
在上一篇博客已經(jīng)介紹了Zookeeper開源客戶端的簡單實用,本篇講解Zookeeper的應用場景。
二、典型應用場景
Zookeeper是一個高可用的分布式數(shù)據(jù)管理和協(xié)調(diào)框架,并且能夠很好的保證分布式環(huán)境中數(shù)據(jù)的一致性。在越來越多的分布式系統(tǒng)(Hadoop、HBase、Kafka)中,Zookeeper都作為核心組件使用。
2.1 數(shù)據(jù)發(fā)布/訂閱
數(shù)據(jù)發(fā)布/訂閱系統(tǒng),即配置中心。需要發(fā)布者將數(shù)據(jù)發(fā)布到Zookeeper的節(jié)點上,供訂閱者進行數(shù)據(jù)訂閱,進而達到動態(tài)獲取數(shù)據(jù)的目的,實現(xiàn)配置信息的集中式管理和數(shù)據(jù)的動態(tài)更新。發(fā)布/訂閱一般有兩種設計模式:推模式和拉模式,服務端主動將數(shù)據(jù)更新發(fā)送給所有訂閱的客戶端稱為推模式;客戶端主動請求獲取最新數(shù)據(jù)稱為拉模式,Zookeeper采用了推拉相結合的模式,客戶端向服務端注冊自己需要關注的節(jié)點,一旦該節(jié)點數(shù)據(jù)發(fā)生變更,那么服務端就會向相應的客戶端推送Watcher事件通知,客戶端接收到此通知后,主動到服務端獲取最新的數(shù)據(jù)。
若將配置信息存放到Zookeeper上進行集中管理,在通常情況下,應用在啟動時會主動到Zookeeper服務端上進行一次配置信息的獲取,同時,在指定節(jié)點上注冊一個Watcher監(jiān)聽,這樣在配置信息發(fā)生變更,服務端都會實時通知所有訂閱的客戶端,從而達到實時獲取最新配置的目的。
2.2 負載均衡
負載均衡是一種相當常見的計算機網(wǎng)絡技術,用來對多個計算機、網(wǎng)絡連接、CPU、磁盤驅動或其他資源進行分配負載,以達到優(yōu)化資源使用、最大化吞吐率、最小化響應時間和避免過載的目的。
使用Zookeeper實現(xiàn)動態(tài)DNS服務
· 域名配置,首先在Zookeeper上創(chuàng)建一個節(jié)點來進行域名配置,如DDNS/app1/server.app1.company1.com。
· 域名解析,應用首先從域名節(jié)點中獲取IP地址和端口的配置,進行自行解析。同時,應用程序還會在域名節(jié)點上注冊一個數(shù)據(jù)變更Watcher監(jiān)聽,以便及時收到域名變更的通知。
· 域名變更,若發(fā)生IP或端口號變更,此時需要進行域名變更操作,此時,只需要對指定的域名節(jié)點進行更新操作,Zookeeper就會向訂閱的客戶端發(fā)送這個事件通知,客戶端之后就再次進行域名配置的獲取。
2.3 命名服務
命名服務是分步實現(xiàn)系統(tǒng)中較為常見的一類場景,分布式系統(tǒng)中,被命名的實體通常可以是集群中的機器、提供的服務地址或遠程對象等,通過命名服務,客戶端可以根據(jù)指定名字來獲取資源的實體、服務地址和提供者的信息。Zookeeper也可幫助應用系統(tǒng)通過資源引用的方式來實現(xiàn)對資源的定位和使用,廣義上的命名服務的資源定位都不是真正意義上的實體資源,在分布式環(huán)境中,上層應用僅僅需要一個全局唯一的名字。Zookeeper可以實現(xiàn)一套分布式全局唯一ID的分配機制。

通過調(diào)用Zookeeper節(jié)點創(chuàng)建的API接口就可以創(chuàng)建一個順序節(jié)點,并且在API返回值中會返回這個節(jié)點的完整名字,利用此特性,可以生成全局ID,其步驟如下
1. 客戶端根據(jù)任務類型,在指定類型的任務下通過調(diào)用接口創(chuàng)建一個順序節(jié)點,如"job-"。
2. 創(chuàng)建完成后,會返回一個完整的節(jié)點名,如"job-00000001"。
3. 客戶端拼接type類型和返回值后,就可以作為全局唯一ID了,如"type2-job-00000001"。
2.4 分布式協(xié)調(diào)/通知
Zookeeper中特有的Watcher注冊于異步通知機制,能夠很好地實現(xiàn)分布式環(huán)境下不同機器,甚至不同系統(tǒng)之間的協(xié)調(diào)與通知,從而實現(xiàn)對數(shù)據(jù)變更的實時處理。通常的做法是不同的客戶端都對Zookeeper上的同一個數(shù)據(jù)節(jié)點進行Watcher注冊,監(jiān)聽數(shù)據(jù)節(jié)點的變化(包括節(jié)點本身和子節(jié)點),若數(shù)據(jù)節(jié)點發(fā)生變化,那么所有訂閱的客戶端都能夠接收到相應的Watcher通知,并作出相應處理。
MySQL數(shù)據(jù)復制總線是一個實時的數(shù)據(jù)復制框架,用于在不同的MySQL數(shù)據(jù)庫實例之間進行異步數(shù)據(jù)復制和數(shù)據(jù)變化通知,整個系統(tǒng)由MySQL數(shù)據(jù)庫集群、消息隊列系統(tǒng)、任務管理監(jiān)控平臺、Zookeeper集群等組件共同構成的一個包含生產(chǎn)者、復制管道、數(shù)據(jù)消費等部分的數(shù)據(jù)總線系統(tǒng)。

Zookeeper主要負責進行分布式協(xié)調(diào)工作,在具體的實現(xiàn)上,根據(jù)功能將數(shù)據(jù)復制組件劃分為三個模塊:Core(實現(xiàn)數(shù)據(jù)復制核心邏輯,將數(shù)據(jù)復制封裝成管道,并抽象出生產(chǎn)者和消費者概念)、Server(啟動和停止復制任務)、Monitor(監(jiān)控任務的運行狀態(tài),若數(shù)據(jù)復制期間發(fā)生異常或出現(xiàn)故障則進行告警)

每個模塊作為獨立的進程運行在服務端,運行時的數(shù)據(jù)和配置信息均保存在Zookeeper上。
① 任務創(chuàng)建,Core進程啟動時,首先向/mysql_replicator/tasks節(jié)點注冊任務,如創(chuàng)建一個子節(jié)點/mysql_replicator/tasks/copy_hot/item,若注冊過程中發(fā)現(xiàn)該子節(jié)點已經(jīng)存在,說明已經(jīng)有其他Task機器注冊了該任務,因此其自身不需要再創(chuàng)建該節(jié)點。
② 任務熱備份,為了應對任務故障或者復制任務所在主機故障,復制組件采用"熱備份"的容災方式,即將同一個復制任務部署在不同的主機上,主備任務機通過Zookeeper互相檢測運行監(jiān)控狀況。無論在第一步是否創(chuàng)建了任務節(jié)點,每臺機器都需要在/mysql_replicator/tasks/copy_hot_item/instrances節(jié)點上將自己的主機名注冊上去,節(jié)點類型為臨時順序節(jié)點,在完成子節(jié)點創(chuàng)建后,每天任務機器都可以獲取到自己創(chuàng)建的節(jié)點名及所有子節(jié)點列表,然后通過對比判斷自己是否是所有子節(jié)點中序號最小的,若是,則將自己運行狀態(tài)設置為RUNNING,其他機器設置為STANDBY,這種策略稱為小序號優(yōu)先策略。
③ 熱備切換,完成運行狀態(tài)的標示后,其中標記為RUNNING的客戶端機器進行正常的數(shù)據(jù)復制,而標記為STANDBY的機器則進入待命狀態(tài),一旦RUNNING機器出現(xiàn)故障,那么所有標記為STANDBY的機器再次按照小序號優(yōu)先策略來選出RUNNIG機器運行(STANDY機器需要在/mysql_replicator/tasks/copy_hot_item/instances節(jié)點上注冊一個子節(jié)點列表變更監(jiān)聽,RUNNING機器宕機與Zookeeper斷開連接后,對應的節(jié)點也會消失,于是所有客戶端收到通知,進行新一輪選舉)。
④ 記錄執(zhí)行狀態(tài),RUNNING機器需要將運行時的上下文狀態(tài)保留給STANDBY機器。
⑤ 控制臺協(xié)調(diào),Server的主要工作就是進行任務控制,通過Zookeeper來對不同任務進行控制和協(xié)調(diào),Server會將每個復制任務對應生產(chǎn)者的元數(shù)據(jù)及消費者的相關信息以配置的形式寫入任務節(jié)點/mysql_replicator/tasks/copy_hot_item中去,以便該任務的所有任務機器都能夠共享復制任務的配置。
在上述熱備份方案中,針對一個任務,都會至少分配兩臺任務機器來進行熱備份(RUNNING和STANDBY、即主備機器),若需要MySQL實例需要進行數(shù)據(jù)復制,那么需要消耗太多機器。此時,需要使用冷備份方案,其對所有任務進行分組。

Core進程被配置了所屬組(Group),即若一個Core進程被標記了group1,那么在Core進程啟動后,會到對應的Zookeeper group1節(jié)點下面獲取所有的Task列表,假如找到任務"copy_hot_item"之后,就會遍歷這個Task列表的instances節(jié)點,但凡還沒有子節(jié)點,則創(chuàng)建一個臨時的順序節(jié)點如/mysql_replicator/task-groups/group1/copy_hot_item/instances/[Hostname]-1,當然,在這個過程中,其他Core進程也會在這個instances節(jié)點下創(chuàng)建類似的子節(jié)點,按照"小序號優(yōu)先"策略確定RUNNING,不同的是,其他Core進程會自動刪除自己創(chuàng)建的子節(jié)點,然后遍歷下一個Task節(jié)點,這樣的過程稱為冷備份掃描,這樣,所有的Core進程在掃描周期內(nèi)不斷地對相應的Group下來的Task進行冷備份。
在絕大多數(shù)分布式系統(tǒng)中,系統(tǒng)機器間的通信無外乎心跳檢測、工作進度匯報和系統(tǒng)調(diào)度。
① 心跳檢測,不同機器間需要檢測到彼此是否在正常運行,可以使用Zookeeper實現(xiàn)機器間的心跳檢測,基于其臨時節(jié)點特性(臨時節(jié)點的生存周期是客戶端會話,客戶端若當即后,其臨時節(jié)點自然不再存在),可以讓不同機器都在Zookeeper的一個指定節(jié)點下創(chuàng)建臨時子節(jié)點,不同的機器之間可以根據(jù)這個臨時子節(jié)點來判斷對應的客戶端機器是否存活。通過Zookeeper可以大大減少系統(tǒng)耦合。
② 工作進度匯報,通常任務被分發(fā)到不同機器后,需要實時地將自己的任務執(zhí)行進度匯報給分發(fā)系統(tǒng),可以在Zookeeper上選擇一個節(jié)點,每個任務客戶端都在這個節(jié)點下面創(chuàng)建臨時子節(jié)點,這樣不僅可以判斷機器是否存活,同時各個機器可以將自己的任務執(zhí)行進度寫到該臨時節(jié)點中去,以便中心系統(tǒng)能夠實時獲取任務的執(zhí)行進度。
③ 系統(tǒng)調(diào)度,Zookeeper能夠實現(xiàn)如下系統(tǒng)調(diào)度模式:分布式系統(tǒng)由控制臺和一些客戶端系統(tǒng)兩部分構成,控制臺的職責就是需要將一些指令信息發(fā)送給所有的客戶端,以控制他們進行相應的業(yè)務邏輯,后臺管理人員在控制臺上做一些操作,實際上就是修改Zookeeper上某些節(jié)點的數(shù)據(jù),Zookeeper可以把數(shù)據(jù)變更以時間通知的形式發(fā)送給訂閱客戶端。
2.5 集群管理
Zookeeper的兩大特性:
· 客戶端如果對Zookeeper的數(shù)據(jù)節(jié)點注冊Watcher監(jiān)聽,那么當該數(shù)據(jù)及誒單內(nèi)容或是其子節(jié)點列表發(fā)生變更時,Zookeeper服務器就會向訂閱的客戶端發(fā)送變更通知。
· 對在Zookeeper上創(chuàng)建的臨時節(jié)點,一旦客戶端與服務器之間的會話失效,那么臨時節(jié)點也會被自動刪除。
利用其兩大特性,可以實現(xiàn)集群機器存活監(jiān)控系統(tǒng),若監(jiān)控系統(tǒng)在/clusterServers節(jié)點上注冊一個Watcher監(jiān)聽,那么但凡進行動態(tài)添加機器的操作,就會在/clusterServers節(jié)點下創(chuàng)建一個臨時節(jié)點:/clusterServers/[Hostname],這樣,監(jiān)控系統(tǒng)就能夠實時監(jiān)測機器的變動情況。下面通過分布式日志收集系統(tǒng)的典型應用來學習Zookeeper如何實現(xiàn)集群管理。
分布式日志收集系統(tǒng)的核心工作就是收集分布在不同機器上的系統(tǒng)日志,在典型的日志系統(tǒng)架構設計中,整個日志系統(tǒng)會把所有需要收集的日志機器分為多個組別,每個組別對應一個收集器,這個收集器其實就是一個后臺機器,用于收集日志,對于大規(guī)模的分布式日志收集系統(tǒng)場景,通常需要解決兩個問題:
· 變化的日志源機器
· 變化的收集器機器
無論是日志源機器還是收集器機器的變更,最終都可以歸結為如何快速、合理、動態(tài)地為每個收集器分配對應的日志源機器。使用Zookeeper的場景步驟如下
① 注冊收集器機器,在Zookeeper上創(chuàng)建一個節(jié)點作為收集器的根節(jié)點,例如/logs/collector的收集器節(jié)點,每個收集器機器啟動時都會在收集器節(jié)點下創(chuàng)建自己的節(jié)點,如/logs/collector/[Hostname]

② 任務分發(fā),所有收集器機器都創(chuàng)建完對應節(jié)點后,系統(tǒng)根據(jù)收集器節(jié)點下子節(jié)點的個數(shù),將所有日志源機器分成對應的若干組,然后將分組后的機器列表分別寫到這些收集器機器創(chuàng)建的子節(jié)點,如/logs/collector/host1上去。這樣,收集器機器就能夠根據(jù)自己對應的收集器節(jié)點上獲取日志源機器列表,進而開始進行日志收集工作。
③ 狀態(tài)匯報,完成任務分發(fā)后,機器隨時會宕機,所以需要有一個收集器的狀態(tài)匯報機制,每個收集器機器上創(chuàng)建完節(jié)點后,還需要再對應子節(jié)點上創(chuàng)建一個狀態(tài)子節(jié)點,如/logs/collector/host/status,每個收集器機器都需要定期向該結點寫入自己的狀態(tài)信息,這可看做是心跳檢測機制,通常收集器機器都會寫入日志收集狀態(tài)信息,日志系統(tǒng)通過判斷狀態(tài)子節(jié)點最后的更新時間來確定收集器機器是否存活。
④ 動態(tài)分配,若收集器機器宕機,則需要動態(tài)進行收集任務的分配,收集系統(tǒng)運行過程中關注/logs/collector節(jié)點下所有子節(jié)點的變更,一旦有機器停止匯報或有新機器加入,就開始進行任務的重新分配,此時通常由兩種做法:
· 全局動態(tài)分配,當收集器機器宕機或有新的機器加入,系統(tǒng)根據(jù)新的收集器機器列表,立即對所有的日志源機器重新進行一次分組,然后將其分配給剩下的收集器機器。
· 局部動態(tài)分配,每個收集器機器在匯報自己日志收集狀態(tài)的同時,也會把自己的負載匯報上去,如果一個機器宕機了,那么日志系統(tǒng)就會把之前分配給這個機器的任務重新分配到那些負載較低的機器,同樣,如果有新機器加入,會從那些負載高的機器上轉移一部分任務給新機器。
上述步驟已經(jīng)完整的說明了整個日志收集系統(tǒng)的工作流程,其中有兩點注意事項。
①節(jié)點類型,在/logs/collector節(jié)點下創(chuàng)建臨時節(jié)點可以很好的判斷機器是否存活,但是,若機器掛了,其節(jié)點會被刪除,記錄在節(jié)點上的日志源機器列表也被清除,所以需要選擇持久節(jié)點來標識每一臺機器,同時在節(jié)點下分別創(chuàng)建/logs/collector/[Hostname]/status節(jié)點來表征每一個收集器機器的狀態(tài),這樣,既能實現(xiàn)對所有機器的監(jiān)控,同時機器掛掉后,依然能夠將分配任務還原。
② 日志系統(tǒng)節(jié)點監(jiān)聽,若采用Watcher機制,那么通知的消息量的網(wǎng)絡開銷非常大,需要采用日志系統(tǒng)主動輪詢收集器節(jié)點的策略,這樣可以節(jié)省網(wǎng)絡流量,但是存在一定的延時。
2.6 Master選舉
在分布式系統(tǒng)中,Master往往用來協(xié)調(diào)集群中其他系統(tǒng)單元,具有對分布式系統(tǒng)狀態(tài)變更的決定權,如在讀寫分離的應用場景中,客戶端的寫請求往往是由Master來處理,或者其常常處理一些復雜的邏輯并將處理結果同步給其他系統(tǒng)單元。利用Zookeeper的強一致性,能夠很好地保證在分布式高并發(fā)情況下節(jié)點的創(chuàng)建一定能夠保證全局唯一性,即Zookeeper將會保證客戶端無法重復創(chuàng)建一個已經(jīng)存在的數(shù)據(jù)節(jié)點。
首先創(chuàng)建/master_election/2016-11-12節(jié)點,客戶端集群每天會定時往該節(jié)點下創(chuàng)建臨時節(jié)點,如/master_election/2016-11-12/binding,這個過程中,只有一個客戶端能夠成功創(chuàng)建,此時其變成master,其他節(jié)點都會在節(jié)點/master_election/2016-11-12上注冊一個子節(jié)點變更的Watcher,用于監(jiān)控當前的Master機器是否存活,一旦發(fā)現(xiàn)當前Master掛了,其余客戶端將會重新進行Master選舉。
2.7 分布式鎖
分布式鎖用于控制分布式系統(tǒng)之間同步訪問共享資源的一種方式,可以保證不同系統(tǒng)訪問一個或一組資源時的一致性,主要分為排它鎖和共享鎖。
排它鎖又稱為寫鎖或獨占鎖,若事務T1對數(shù)據(jù)對象O1加上了排它鎖,那么在整個加鎖期間,只允許事務T1對O1進行讀取和更新操作,其他任何事務都不能再對這個數(shù)據(jù)對象進行任何類型的操作,直到T1釋放了排它鎖。
① 獲取鎖,在需要獲取排它鎖時,所有客戶端通過調(diào)用接口,在/exclusive_lock節(jié)點下創(chuàng)建臨時子節(jié)點/exclusive_lock/lock。Zookeeper可以保證只有一個客戶端能夠創(chuàng)建成功,沒有成功的客戶端需要注冊/exclusive_lock節(jié)點監(jiān)聽。
② 釋放鎖,當獲取鎖的客戶端宕機或者正常完成業(yè)務邏輯都會導致臨時節(jié)點的刪除,此時,所有在/exclusive_lock節(jié)點上注冊監(jiān)聽的客戶端都會收到通知,可以重新發(fā)起分布式鎖獲取。
共享鎖又稱為讀鎖,若事務T1對數(shù)據(jù)對象O1加上共享鎖,那么當前事務只能對O1進行讀取操作,其他事務也只能對這個數(shù)據(jù)對象加共享鎖,直到該數(shù)據(jù)對象上的所有共享鎖都被釋放。
① 獲取鎖,在需要獲取共享鎖時,所有客戶端都會到/shared_lock下面創(chuàng)建一個臨時順序節(jié)點,如果是讀請求,那么就創(chuàng)建例如/shared_lock/host1-R-00000001的節(jié)點,如果是寫請求,那么就創(chuàng)建例如/shared_lock/host2-W-00000002的節(jié)點。
② 判斷讀寫順序,不同事務可以同時對一個數(shù)據(jù)對象進行讀寫操作,而更新操作必須在當前沒有任何事務進行讀寫情況下進行,通過Zookeeper來確定分布式讀寫順序,大致分為四步。
1. 創(chuàng)建完節(jié)點后,獲取/shared_lock節(jié)點下所有子節(jié)點,并對該節(jié)點變更注冊監(jiān)聽。
2. 確定自己的節(jié)點序號在所有子節(jié)點中的順序。
3. 對于讀請求:若沒有比自己序號小的子節(jié)點或所有比自己序號小的子節(jié)點都是讀請求,那么表明自己已經(jīng)成功獲取到共享鎖,同時開始執(zhí)行讀取邏輯,若有寫請求,則需要等待。對于寫請求:若自己不是序號最小的子節(jié)點,那么需要等待。
4. 接收到Watcher通知后,重復步驟1。
③ 釋放鎖,其釋放鎖的流程與獨占鎖一致。
上述共享鎖的實現(xiàn)方案,可以滿足一般分布式集群競爭鎖的需求,但是如果機器規(guī)模擴大會出現(xiàn)一些問題,下面著重分析判斷讀寫順序的步驟3。

針對如上圖所示的情況進行分析
1. host1首先進行讀操作,完成后將節(jié)點/shared_lock/host1-R-00000001刪除。
2. 余下4臺機器均收到這個節(jié)點移除的通知,然后重新從/shared_lock節(jié)點上獲取一份新的子節(jié)點列表。
3. 每臺機器判斷自己的讀寫順序,其中host2檢測到自己序號最小,于是進行寫操作,余下的機器則繼續(xù)等待。
4. 繼續(xù)...
可以看到,host1客戶端在移除自己的共享鎖后,Zookeeper發(fā)送了子節(jié)點更變Watcher通知給所有機器,然而除了給host2產(chǎn)生影響外,對其他機器沒有任何作用。大量的Watcher通知和子節(jié)點列表獲取兩個操作會重復運行,這樣會造成系能鞥影響和網(wǎng)絡開銷,更為嚴重的是,如果同一時間有多個節(jié)點對應的客戶端完成事務或事務中斷引起節(jié)點小時,Zookeeper服務器就會在短時間內(nèi)向其他所有客戶端發(fā)送大量的事件通知,這就是所謂的羊群效應。
可以有如下改動來避免羊群效應。
1. 客戶端調(diào)用create接口常見類似于/shared_lock/[Hostname]-請求類型-序號的臨時順序節(jié)點。
2. 客戶端調(diào)用getChildren接口獲取所有已經(jīng)創(chuàng)建的子節(jié)點列表(不注冊任何Watcher)。
3. 如果無法獲取共享鎖,就調(diào)用exist接口來對比自己小的節(jié)點注冊Watcher。對于讀請求:向比自己序號小的最后一個寫請求節(jié)點注冊Watcher監(jiān)聽。對于寫請求:向比自己序號小的最后一個節(jié)點注冊Watcher監(jiān)聽。
4. 等待Watcher通知,繼續(xù)進入步驟2。
此方案改動主要在于:每個鎖競爭者,只需要關注/shared_lock節(jié)點下序號比自己小的那個節(jié)點是否存在即可。
2.8 分布式隊列
分布式隊列可以簡單分為先入先出隊列模型和等待隊列元素聚集后統(tǒng)一安排處理執(zhí)行的Barrier模型。
① FIFO先入先出,先進入隊列的請求操作先完成后,才會開始處理后面的請求。FIFO隊列就類似于全寫的共享模型,所有客戶端都會到/queue_fifo這個節(jié)點下創(chuàng)建一個臨時節(jié)點,如/queue_fifo/host1-00000001。
創(chuàng)建完節(jié)點后,按照如下步驟執(zhí)行。
1. 通過調(diào)用getChildren接口來獲取/queue_fifo節(jié)點的所有子節(jié)點,即獲取隊列中所有的元素。
2. 確定自己的節(jié)點序號在所有子節(jié)點中的順序。
3. 如果自己的序號不是最小,那么需要等待,同時向比自己序號小的最后一個節(jié)點注冊Watcher監(jiān)聽。
4. 接收到Watcher通知后,重復步驟1。
② Barrier分布式屏障,最終的合并計算需要基于很多并行計算的子結果來進行,開始時,/queue_barrier節(jié)點已經(jīng)默認存在,并且將結點數(shù)據(jù)內(nèi)容賦值為數(shù)字n來代表Barrier值,之后,所有客戶端都會到/queue_barrier節(jié)點下創(chuàng)建一個臨時節(jié)點,例如/queue_barrier/host1。

創(chuàng)建完節(jié)點后,按照如下步驟執(zhí)行。
1. 通過調(diào)用getData接口獲取/queue_barrier節(jié)點的數(shù)據(jù)內(nèi)容,如10。
2. 通過調(diào)用getChildren接口獲取/queue_barrier節(jié)點下的所有子節(jié)點,同時注冊對子節(jié)點變更的Watcher監(jiān)聽。
3. 統(tǒng)計子節(jié)點的個數(shù)。
4. 如果子節(jié)點個數(shù)還不足10個,那么需要等待。
5. 接受到Wacher通知后,重復步驟3。
三、總結
本篇博客講解了如何利用Zookeeper的特性來完成典型應用,展示了Zookeeper在解決分布式問題上的強大作用,基于Zookeeper對分布式數(shù)據(jù)一致性的保證及其特性,開發(fā)人員能夠構建出自己的分布式系統(tǒng)。也謝謝各位園友的觀看~