[b]資料發布與訂閱(配置中心)[/b]
發布與訂閱模型,即所謂的配置中心,顧名思義就是發布者將資料發布到zk節點上,供訂閱者動態獲取資料,實現配置資訊的集中式管理和動態更新。例如全域性的配置資訊,服務式服務框架的服務位址列表等就非常適合使用。
應用中用到的一些配置資訊放到zk上進行集中管理。這類場景通常是這樣:應用在啟動的時候會主動來獲取一次配置,同時,在節點上註冊乙個watcher,這樣一來,以後每次配置有更新的時候,都會實時通知到訂閱的客戶端,從來達到獲取最新配置資訊的目的。
分布式搜尋服務中,索引的元資訊和伺服器集群機器的節點狀態存放在zk的一些指定節點,供各個客戶端訂閱使用。
分布式日誌收集系統。這個系統的核心工作是收集分布在不同機器的日誌。收集器通常是按照應用來分配收集任務單元,因此需要在zk上建立乙個以應用名作為path的節點p,並將這個應用的所有機器ip,以子節點的形式註冊到節點p上,這樣一來就能夠實現機器變動的時候,能夠實時通知到收集器調整任務分配。
系統中有些資訊需要動態獲取,並且還會存在人工手動去修改這個資訊的發問。通常是暴露出介面,例如jmx介面,來獲取一些執行時的資訊。引入zk之後,就不用自己實現一套方案了,只要將這些資訊存放到指定的zk節點上即可。
注意:在上面提到的應用場景中,有個預設前提是:資料量很小,但是資料更新可能會比較快的場景。
[b]負載均衡[/b]
這裡說的負載均衡是指軟負載均衡。在分布式環境中,為了保證高可用性,通常同乙個應用或同乙個服務的提供方都會部署多份,達到對等服務。而消費者就須要在這些對等的伺服器中選擇乙個來執行相關的業務邏輯,其中比較典型的是訊息中介軟體中的生產者,消費者負載均衡。
訊息中介軟體中發布者和訂閱者的負載均衡,linkedin開源的kafkamq和阿里開源的metaq都是通過zookeeper來做到生產者、消費者的負載均衡。這裡以metaq為例如講下:
生產者負載均衡:metaq傳送訊息的時候,生產者在傳送訊息的時候必須選擇一台broker上的乙個分割槽來傳送訊息,因此metaq在執行過程中,會把所有broker和對應的分割槽資訊全部註冊到zk指定節點上,預設的策略是乙個依次輪詢的過程,生產者在通過zk獲取分割槽列表之後,會按照brokerid和partition的順序排列組織成乙個有序的分割槽列表,傳送的時候按照從頭到尾迴圈往復的方式選擇乙個分割槽來傳送訊息。
消費負載均衡:
在消費過程中,乙個消費者會消費乙個或多個分割槽中的訊息,但是乙個分割槽只會由乙個消費者來消費。metaq的消費策略是:
每個分割槽針對同乙個group只掛載乙個消費者。
如果同乙個group的消費者數目大於分割槽數目,則多出來的消費者將不參與消費。
如果同乙個group的消費者數目小於分割槽數目,則有部分消費者需要額外承擔消費任務。
在某個消費者故障或者重啟等情況下,其他消費者會感知到這一變化(通過 zookeeper watch消費者列表),然後重新進行負載均衡,保證所有的分割槽都有消費者進行消費。
[b]命名服務(naming service)[/b]
命名服務也是分布式系統中比較常見的一類場景。在分布式系統中,通過使用命名服務,客戶端應用能夠根據指定名字來獲取資源或服務的位址,提供者等資訊。被命名的實體通常可以是集群中的機器,提供的服務位址,遠端物件等等——這些我們都可以統稱他們為名字(name)。其中較為常見的就是一些分布式服務框架中的服務位址列表。通過呼叫zk提供的建立節點的api,能夠很容易建立乙個全域性唯一的path,這個path就可以作為乙個名稱。
服務提供者在啟動的時候,向zk上的指定節點/dubbo/$/providers目錄下寫入自己的url位址,這個操作就完成了服務的發布。
服務消費者啟動的時候,訂閱/dubbo/$/providers目錄下的提供者url位址, 並向/dubbo/$ /consumers目錄下寫入自己的url位址。
注意,所有向zk上註冊的位址都是臨時節點,這樣就能夠保證服務提供者和消費者能夠自動感應資源的變化。
另外,dubbo還有針對服務粒度的監控,方法是訂閱/dubbo/$目錄下所有提供者和消費者的資訊。
[b]分布式通知/協調[/b]
zookeeper中特有watcher註冊與非同步通知機制,能夠很好的實現分布式環境下不同系統之間的通知與協調,實現對資料變更的實時處理。使用方法通常是不同系統都對zk上同乙個znode進行註冊,監聽znode的變化(包括znode本身內容及子節點的),其中乙個系統update了znode,那麼另乙個系統能夠收到通知,並作出相應處理
另一種心跳檢測機制:檢測系統和被檢測系統之間並不直接關聯起來,而是通過zk上某個節點關聯,大大減少系統耦合。
另一種系統排程模式:某系統有控制台和推送系統兩部分組成,控制台的職責是控制推送系統進行相應的推送工作。管理人員在控制台作的一些操作,實際上是修改了zk上某些節點的狀態,而zk就把這些變化通知給他們註冊watcher的客戶端,即推送系統,於是,作出相應的推送任務。
另一種工作匯報模式:一些類似於任務分發系統,子任務啟動後,到zk來註冊乙個臨時節點,並且定時將自己的進度進行匯報(將進度寫回這個臨時節點),這樣任務管理者就能夠實時知道任務進度。
總之,使用zookeeper來進行分布式通知和協調能夠大大降低系統之間的耦合
[b]集群管理與master選舉[/b]
集群中機器有變動的時候,牽連修改的東西比較多。
有一定的延時。
利用zookeeper有兩個特性,就可以實時另一種集群機器存活性監控系統:
客戶端在節點 x 上註冊乙個watcher,那麼如果 x?的子節點變化了,會通知該客戶端。
建立ephemeral型別的節點,一旦客戶端和伺服器的會話結束或過期,那麼該節點就會消失。
例如,監控系統在 /clusterservers 節點上註冊乙個watcher,以後每動態加機器,那麼就往 /clusterservers 下建立乙個 ephemeral型別的節點:/clusterservers/. 這樣,監控系統就能夠實時知道機器的增減情況,至於後續處理就是監控系統的業務了。
master選舉則是zookeeper中最為經典的應用場景了。
在分布式環境中,相同的業務應用分布在不同的機器上,有些業務邏輯(例如一些耗時的計算,網路i/o處理),往往只需要讓整個集群中的某一台機器進行執行,其餘機器可以共享這個結果,這樣可以大大減少重複勞動,提高效能,於是這個master選舉便是這種場景下的碰到的主要問題。
利用zookeeper的強一致性,能夠保證在分布式高併發情況下節點建立的全域性唯一性,即:同時有多個客戶端請求建立 /currentmaster 節點,最終一定只有乙個客戶端請求能夠建立成功。利用這個特性,就能很輕易的在分布式環境中進行集群選取了。
另外,這種場景演化一下,就是動態master選舉。這就要用到?ephemeral_sequential型別節點的特性了。
上文中提到,所有客戶端建立請求,最終只有乙個能夠建立成功。在這裡稍微變化下,就是允許所有請求都能夠建立成功,但是得有個建立順序,於是所有的請求最終在zk上建立結果的一種可能情況是這樣: /currentmaster/-1 ,?/currentmaster/-2 ,?/currentmaster/-3 ….. 每次選取序列號最小的那個機器作為master,如果這個機器掛了,由於他建立的節點會馬上小時,那麼之後最小的那個機器就是master了。
在hbase中,也是使用zookeeper來實現動態hmaster的選舉。在hbase實現中,會在zk上儲存一些root表的位址和hmaster的位址,hregionserver也會把自己以臨時節點(ephemeral)的方式註冊到zookeeper中,使得hmaster可以隨時感知到各個hregionserver的存活狀態,同時,一旦hmaster出現問題,會重新選舉出乙個hmaster來執行,從而避免了hmaster的單點問題
[b]分布式鎖[/b]
分布式鎖,這個主要得益於zookeeper為我們保證了資料的強一致性。鎖服務可以分為兩類,乙個是保持獨佔,另乙個是控制時序。
所謂保持獨佔,就是所有試圖來獲取這個鎖的客戶端,最終只有乙個可以成功獲得這把鎖。通常的做法是把zk上的乙個znode看作是一把鎖,通過create znode的方式來實現。所有客戶端都去建立 /distribute_lock 節點,最終成功建立的那個客戶端也即擁有了這把鎖。
控制時序,就是所有檢視來獲取這個鎖的客戶端,最終都是會被安排執行,只是有個全域性時序了。做法和上面基本類似,只是這裡 /distribute_lock 已經預先存在,客戶端在它下面建立臨時有序節點(這個可以通過節點的屬性控制:createmode.ephemeral_sequential來指定)。zk的父節點(/distribute_lock)維持乙份sequence,保證子節點建立的時序性,從而也形成了每個客戶端的全域性時序。
[b]分布式佇列[/b]
佇列方面,簡單地講有兩種,一種是常規的先進先出佇列,另一種是要等到佇列成員聚齊之後的才統一按序執行。對於第一種先進先出佇列,和分布式鎖服務中的控制時序場景基本原理一致,這裡不再贅述。
第二種佇列其實是在fifo佇列的基礎上作了乙個增強。通常可以在 /queue 這個znode下預先建立乙個/queue/num 節點,並且賦值為n(或者直接給/queue賦值n),表示佇列大小,之後每次有佇列成員加入後,就判斷下是否已經到達佇列大小,決定是否可以開始執行了。這種用法的典型場景是,分布式環境中,乙個大任務task a,需要在很多子任務完成(或條件就緒)情況下才能進行。這個時候,凡是其中乙個子任務完成(就緒),那麼就去 /tasklist 下建立自己的臨時時序節點(createmode.ephemeral_sequential),當 /tasklist 發現自己下面的子節點滿足指定個數,就可以進行下一步按序進行處理了。
ZooKeeper典型應用場景
zookeeper 是乙個開源的高可用的分布式資料管理與系統協調框架,基於對 paxos 演算法的實現,保證了分布式環境中資料的強一致性。發布與訂閱模型 發布者發布資料到 zk 節點上,供訂閱者動態獲取資料。在資料量很少,但是資料更新快的場景下 訊息中介軟體中的發布者和訂閱者的負載均衡,linked...
ZooKeeper典型使用場景
zookeeper是乙個高可用的分布式資料管理與系統協調框架。基於對paxos演算法的實現,使該框架保證了分布式環境中資料的強一致性,也正是 基於這樣的特性,使得zookeeper能夠應用於很多場景。網上對zk的使用場景也有不少介紹,本文將結合作者身邊的專案例子,系統的對zk的使用場景 進行歸類介紹...
ZooKeeper的典型應用場景 資料發布 訂閱
資料發布 訂閱系統,即所謂的配置中心 發布者將資料發布到zookeeper的乙個或一系列節點上,供訂閱者進行資料訂閱,進而達到動態獲取資料的目的,實現配置資訊的集中式管理和資料的動態更新。zookeeper採用的是推拉相結合的方式 客戶端向伺服器端註冊自己需要關注的節點,一旦該服務端節點的資料發生變...