ZooKeeper典型應用場景

ZooKeeper是一個高可用的分布式數(shù)據(jù)管理與系統(tǒng)協(xié)調框架娩践。基于對Paxos算法的實現(xiàn),使該框架保證了分布式環(huán)境中數(shù)據(jù)的強一致性幌蚊,也正是基于這樣的特性谤碳,使得ZooKeeper解決很多分布式問題。網(wǎng)上對ZK的應用場景也有不少介紹溢豆,本文將結合作者身邊的項目例子蜒简,系統(tǒng)地對ZK的應用場景進行一個分門歸類的介紹。

值得注意的是漩仙,ZK并非天生就是為這些應用場景設計的搓茬,都是后來眾多開發(fā)者根據(jù)其框架的特性,利用其提供的一系列API接口(或者稱為原語集)队他,摸索出來的典型使用方法卷仑。因此,也非常歡迎讀者分享你在ZK使用上的奇技淫巧麸折。

數(shù)據(jù)發(fā)布與訂閱(配置中心)

發(fā)布與訂閱模型锡凝,即所謂的配置中心,顧名思義就是發(fā)布者將數(shù)據(jù)發(fā)布到ZK節(jié)點上垢啼,供訂閱者動態(tài)獲取數(shù)據(jù)私爷,實現(xiàn)配置信息的集中式管理和動態(tài)更新。例如全局的配置信息膊夹,服務式服務框架的服務地址列表等就非常適合使用衬浑。

  • 應用中用到的一些配置信息放到ZK上進行集中管理。這類場景通常是這樣:應用在啟動的時候會主動來獲取一次配置放刨,同時工秩,在節(jié)點上注冊一個Watcher,這樣一來进统,以后每次配置有更新的時候助币,都會實時通知到訂閱的客戶端,從來達到獲取最新配置信息的目的螟碎。
  • 分布式搜索服務中眉菱,索引的元信息和服務器集群機器的節(jié)點狀態(tài)存放在ZK的一些指定節(jié)點,供各個客戶端訂閱使用掉分。
  • 分布式日志收集系統(tǒng)俭缓。這個系統(tǒng)的核心工作是收集分布在不同機器的日志。收集器通常是按照應用來分配收集任務單元酥郭,因此需要在ZK上創(chuàng)建一個以應用名作為path的節(jié)點P华坦,并將這個應用的所有機器ip,以子節(jié)點的形式注冊到節(jié)點P上不从,這樣一來就能夠實現(xiàn)機器變動的時候惜姐,能夠實時通知到收集器調整任務分配。
  • 系統(tǒng)中有些信息需要動態(tài)獲取椿息,并且還會存在人工手動去修改這個信息的發(fā)問歹袁。通常是暴露出接口坷衍,例如JMX接口,來獲取一些運行時的信息条舔。引入ZK之后惫叛,就不用自己實現(xiàn)一套方案了,只要將這些信息存放到指定的ZK節(jié)點上即可逞刷。

注意:在上面提到的應用場景中,有個默認前提是:數(shù)據(jù)量很小妻熊,但是數(shù)據(jù)更新可能會比較快的場景夸浅。

負載均衡

這里說的負載均衡是指軟負載均衡。在分布式環(huán)境中扔役,為了保證高可用性帆喇,通常同一個應用或同一個服務的提供方都會部署多份,達到對等服務亿胸。而消費者就須要在這些對等的服務器中選擇一個來執(zhí)行相關的業(yè)務邏輯坯钦,其中比較典型的是消息中間件中的生產者,消費者負載均衡侈玄。
消息中間件中發(fā)布者和訂閱者的負載均衡婉刀,linkedin開源的KafkaMQ和阿里開源的metaq都是通過zookeeper來做到生產者、消費者的負載均衡序仙。這里以metaq為例如講下:
生產者負載均衡:metaq發(fā)送消息的時候突颊,生產者在發(fā)送消息的時候必須選擇一臺broker上的一個分區(qū)來發(fā)送消息,因此metaq在運行過程中潘悼,會把所有broker和對應的分區(qū)信息全部注冊到ZK指定節(jié)點上律秃,默認的策略是一個依次輪詢的過程,生產者在通過ZK獲取分區(qū)列表之后治唤,會按照brokerId和partition的順序排列組織成一個有序的分區(qū)列表棒动,發(fā)送的時候按照從頭到尾循環(huán)往復的方式選擇一個分區(qū)來發(fā)送消息。

消費負載均衡

在消費過程中宾添,一個消費者會消費一個或多個分區(qū)中的消息船惨,但是一個分區(qū)只會由一個消費者來消費。MetaQ的消費策略是:

  • 每個分區(qū)針對同一個group只掛載一個消費者缕陕。
  • 如果同一個group的消費者數(shù)目大于分區(qū)數(shù)目掷漱,則多出來的消費者將不參與消費。
  • 如果同一個group的消費者數(shù)目小于分區(qū)數(shù)目榄檬,則有部分消費者需要額外承擔消費任務卜范。

在某個消費者故障或者重啟等情況下,其他消費者會感知到這一變化(通過 zookeeper watch消費者列表)鹿榜,然后重新進行負載均衡海雪,保證所有的分區(qū)都有消費者進行消費锦爵。

命名服務(Naming Service)

命名服務也是分布式系統(tǒng)中比較常見的一類場景。在分布式系統(tǒng)中奥裸,通過使用命名服務险掀,客戶端應用能夠根據(jù)指定名字來獲取資源或服務的地址,提供者等信息湾宙。被命名的實體通痴燎猓可以是集群中的機器,提供的服務地址侠鳄,遠程對象等等——這些我們都可以統(tǒng)稱他們?yōu)槊郑∟ame)埠啃。其中較為常見的就是一些分布式服務框架中的服務地址列表。通過調用ZK提供的創(chuàng)建節(jié)點的API伟恶,能夠很容易創(chuàng)建一個全局唯一的path碴开,這個path就可以作為一個名稱。
阿里巴巴集團開源的分布式服務框架Dubbo中使用ZooKeeper來作為其命名服務博秫,維護全局的服務地址列表潦牛,點擊這里查看Dubbo開源項目。在Dubbo實現(xiàn)中:
服務提供者在啟動的時候挡育,向ZK上的指定節(jié)點/dubbo/${serviceName}/providers目錄下寫入自己的URL地址巴碗,這個操作就完成了服務的發(fā)布。
服務消費者啟動的時候即寒,訂閱/dubbo/${serviceName}/providers目錄下的提供者URL地址良价, 并向/dubbo/${serviceName} /consumers目錄下寫入自己的URL地址。
注意蒿叠,所有向ZK上注冊的地址都是臨時節(jié)點明垢,這樣就能夠保證服務提供者和消費者能夠自動感應資源的變化
另外市咽,Dubbo還有針對服務粒度的監(jiān)控痊银,方法是訂閱/dubbo/${serviceName}目錄下所有提供者和消費者的信息。

分布式通知/協(xié)調

ZooKeeper中特有watcher注冊與異步通知機制施绎,能夠很好的實現(xiàn)分布式環(huán)境下不同系統(tǒng)之間的通知與協(xié)調溯革,實現(xiàn)對數(shù)據(jù)變更的實時處理。使用方法通常是不同系統(tǒng)都對ZK上同一個znode進行注冊谷醉,監(jiān)聽znode的變化(包括znode本身內容及子節(jié)點的)致稀,其中一個系統(tǒng)update了znode,那么另一個系統(tǒng)能夠收到通知俱尼,并作出相應處理

  • 另一種心跳檢測機制:檢測系統(tǒng)和被檢測系統(tǒng)之間并不直接關聯(lián)起來抖单,而是通過zk上某個節(jié)點關聯(lián),大大減少系統(tǒng)耦合。
  • 另一種系統(tǒng)調度模式:某系統(tǒng)有控制臺和推送系統(tǒng)兩部分組成矛绘,控制臺的職責是控制推送系統(tǒng)進行相應的推送工作耍休。管理人員在控制臺作的一些操作,實際上是修改了ZK上某些節(jié)點的狀態(tài)货矮,而ZK就把這些變化通知給他們注冊Watcher的客戶端羊精,即推送系統(tǒng),于是囚玫,作出相應的推送任務喧锦。
  • 另一種工作匯報模式:一些類似于任務分發(fā)系統(tǒng),子任務啟動后抓督,到zk來注冊一個臨時節(jié)點燃少,并且定時將自己的進度進行匯報(將進度寫回這個臨時節(jié)點),這樣任務管理者就能夠實時知道任務進度本昏。

總之,使用zookeeper來進行分布式通知和協(xié)調能夠大大降低系統(tǒng)之間的耦合

集群管理與Master選舉

集群機器監(jiān)控:這通常用于那種對集群中機器狀態(tài)枪汪,機器在線率有較高要求的場景涌穆,能夠快速對集群中機器變化作出響應。這樣的場景中雀久,往往有一個監(jiān)控系統(tǒng)宿稀,實時檢測集群機器是否存活。過去的做法通常是:監(jiān)控系統(tǒng)通過某種手段(比如ping)定時檢測每個機器赖捌,或者每個機器自己定時向監(jiān)控系統(tǒng)匯報“我還活著”祝沸。 這種做法可行,但是存在兩個比較明顯的問題:

  • 集群中機器有變動的時候越庇,牽連修改的東西比較多罩锐。
  • 有一定的延時。

利用ZooKeeper有兩個特性卤唉,就可以實時另一種集群機器存活性監(jiān)控系統(tǒng)

  • 客戶端在節(jié)點 x 上注冊一個Watcher涩惑,那么如果 x?的子節(jié)點變化了,會通知該客戶端桑驱。
  • 創(chuàng)建EPHEMERAL類型的節(jié)點竭恬,一旦客戶端和服務器的會話結束或過期,那么該節(jié)點就會消失熬的。

例如痊硕,監(jiān)控系統(tǒng)在 /clusterServers 節(jié)點上注冊一個Watcher,以后每動態(tài)加機器押框,那么就往 /clusterServers 下創(chuàng)建一個 EPHEMERAL類型的節(jié)點:/clusterServers/{hostname}. 這樣岔绸,監(jiān)控系統(tǒng)就能夠實時知道機器的增減情況,至于后續(xù)處理就是監(jiān)控系統(tǒng)的業(yè)務了。

Master選舉則是zookeeper中最為經典的應用場景了亭螟。
在分布式環(huán)境中挡鞍,相同的業(yè)務應用分布在不同的機器上,有些業(yè)務邏輯(例如一些耗時的計算预烙,網(wǎng)絡I/O處理)墨微,往往只需要讓整個集群中的某一臺機器進行執(zhí)行,其余機器可以共享這個結果扁掸,這樣可以大大減少重復勞動翘县,提高性能,于是這個master選舉便是這種場景下的碰到的主要問題谴分。

利用ZooKeeper的強一致性锈麸,能夠保證在分布式高并發(fā)情況下節(jié)點創(chuàng)建的全局唯一性,即:同時有多個客戶端請求創(chuàng)建 /currentMaster 節(jié)點牺蹄,最終一定只有一個客戶端請求能夠創(chuàng)建成功忘伞。利用這個特性,就能很輕易的在分布式環(huán)境中進行集群選取了沙兰。

另外氓奈,這種場景演化一下,就是動態(tài)Master選舉鼎天。這就要用到?EPHEMERAL_SEQUENTIAL類型節(jié)點的特性了舀奶。

上文中提到,所有客戶端創(chuàng)建請求斋射,最終只有一個能夠創(chuàng)建成功育勺。在這里稍微變化下,就是允許所有請求都能夠創(chuàng)建成功罗岖,但是得有個創(chuàng)建順序涧至,于是所有的請求最終在ZK上創(chuàng)建結果的一種可能情況是這樣: /currentMaster/{sessionId}-1 ,?/currentMaster/{sessionId}-2 ,?/currentMaster/{sessionId}-3 ….. 每次選取序列號最小的那個機器作為Master,如果這個機器掛了桑包,由于他創(chuàng)建的節(jié)點會馬上消失化借,那么之后最小的那個機器就是Master了。

在搜索系統(tǒng)中捡多,如果集群中每個機器都生成一份全量索引蓖康,不僅耗時,而且不能保證彼此之間索引數(shù)據(jù)一致垒手。因此讓集群中的Master來進行全量索引的生成蒜焊,然后同步到集群中其它機器。另外科贬,Master選舉的容災措施是泳梆,可以隨時進行手動指定master鳖悠,就是說應用在zk在無法獲取master信息時,可以通過比如http方式优妙,向一個地方獲取master乘综。
在Hbase中,也是使用ZooKeeper來實現(xiàn)動態(tài)HMaster的選舉套硼。在Hbase實現(xiàn)中卡辰,會在ZK上存儲一些ROOT表的地址和HMaster的地址,HRegionServer也會把自己以臨時節(jié)點(Ephemeral)的方式注冊到Zookeeper中邪意,使得HMaster可以隨時感知到各個HRegionServer的存活狀態(tài)九妈,同時,一旦HMaster出現(xiàn)問題雾鬼,會重新選舉出一個HMaster來運行萌朱,從而避免了HMaster的單點問題

分布式鎖

在分布式系統(tǒng)中,如果不同的系統(tǒng)或是同一個系統(tǒng)的不同主機之間共享了一個或一組資源策菜,那么訪問這些資源的時候晶疼,往往需要互斥來防止彼此干擾,來保證一致性又憨,在這種情況下翠霍,便需要使用到分布式鎖。例如有N臺服務器同時要對某個文件進行修改竟块,如何才能保證文本不會被寫亂壶运,這就是一個簡單的分布式鎖應用場景耐齐。

ZooKeeper 里實現(xiàn)分布式鎖的基本邏輯:

  • zookeeper中創(chuàng)建一個根節(jié)點(Locks)浪秘,用于后續(xù)各個客戶端的鎖操作。
  • 想要獲取鎖的client都在Locks中創(chuàng)建一個自增序的子節(jié)點埠况,每個client得到一個序號耸携,如果自己的序號是最小的則獲得鎖。
  • 如果沒有得到鎖辕翰,就監(jiān)控排在自己前面的序號節(jié)點夺衍,并且設置默認時間,等待它的釋放喜命。
  • 業(yè)務操作后釋放鎖,然后監(jiān)控自己的節(jié)點的client就被喚醒得到鎖沟沙。(例如client A需要釋放鎖,只需要把對應的節(jié)點1刪除掉壁榕,因為client B已經關注了節(jié)點1矛紫,那么當節(jié)點1被刪除后,zookeeper就會通知client B:你是序號最小的了牌里,可以獲取鎖了)颊咬。釋放鎖的過程相對比較簡單,就是刪除自己創(chuàng)建的那個子節(jié)點即可。
518211-20170321142536752-1300040670.png
518211-20170321142629408-723040717.png
518211-20170321142710424-880814732.png
518211-20170321142813736-1253317928.png

分布式鎖喳篇,這個主要得益于ZooKeeper為我們保證了數(shù)據(jù)的強一致性敞临。鎖服務可以分為兩類,一個是保持獨占麸澜,另一個是控制時序挺尿。

  • 所謂保持獨占,就是所有試圖來獲取這個鎖的客戶端痰憎,最終只有一個可以成功獲得這把鎖票髓。通常的做法是把zk上的一個znode看作是一把鎖,通過create znode的方式來實現(xiàn)铣耘。所有客戶端都去創(chuàng)建 /distribute_lock 節(jié)點洽沟,最終成功創(chuàng)建的那個客戶端也即擁有了這把鎖。
  • 控制時序蜗细,就是所有視圖來獲取這個鎖的客戶端裆操,最終都是會被安排執(zhí)行,只是有個全局時序了炉媒。做法和上面基本類似踪区,只是這里 /distribute_lock 已經預先存在,客戶端在它下面創(chuàng)建臨時有序節(jié)點(這個可以通過節(jié)點的屬性控制:CreateMode.EPHEMERAL_SEQUENTIAL來指定)吊骤。Zk的父節(jié)點(/distribute_lock)維持一份sequence,保證子節(jié)點創(chuàng)建的時序性缎岗,從而也形成了每個客戶端的全局時序。

分布式隊列

隊列方面白粉,簡單地講有兩種传泊,一種是常規(guī)的先進先出隊列,另一種是要等到隊列成員聚齊之后的才統(tǒng)一按序執(zhí)行鸭巴。對于第一種先進先出隊列眷细,和分布式鎖服務中的控制時序場景基本原理一致,這里不再贅述鹃祖。

第二種隊列其實是在FIFO隊列的基礎上作了一個增強溪椎。通常可以在 /queue 這個znode下預先建立一個/queue/num 節(jié)點恬口,并且賦值為n(或者直接給/queue賦值n)校读,表示隊列大小,之后每次有隊列成員加入后祖能,就判斷下是否已經到達隊列大小歉秫,決定是否可以開始執(zhí)行了。這種用法的典型場景是芯杀,分布式環(huán)境中端考,一個大任務Task A雅潭,需要在很多子任務完成(或條件就緒)情況下才能進行。這個時候却特,凡是其中一個子任務完成(就緒)扶供,那么就去 /taskList 下建立自己的臨時時序節(jié)點(CreateMode.EPHEMERAL_SEQUENTIAL),當 /taskList 發(fā)現(xiàn)自己下面的子節(jié)點滿足指定個數(shù)裂明,就可以進行下一步按序進行處理了椿浓。

安裝Zookeeper

Kafka的運行依賴于Zookeeper,所以在運行Kafka之前我們需要安裝并運行Zookeeper

  • 下載安裝文件: http://zookeeper.apache.org/releases.html
  • 解壓文件(本文解壓到 E:\resources\zookeeper-3.4.8)
  • 打開E:\resources\zookeeper-3.4.8\conf闽晦,把zoo_sample.cfg重命名成zoo.cfg
  • 從文本編輯器里打開zoo.cfg
  • 把dataDir的值改成“:\zookeeper-3.4.8\data”
  • 添加如下系統(tǒng)變量:

ZOOKEEPER_HOME: E:\resources\zookeeper-3.4.8
Path: 在現(xiàn)有的值后面添加 ";%ZOOKEEPER_HOME%\bin;"

  • 運行Zookeeper: 打開cmd然后執(zhí)行扳碍,zkserver

參考資料

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市仙蛉,隨后出現(xiàn)的幾起案子笋敞,更是在濱河造成了極大的恐慌,老刑警劉巖荠瘪,帶你破解...
    沈念sama閱讀 222,681評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件夯巷,死亡現(xiàn)場離奇詭異,居然都是意外死亡哀墓,警方通過查閱死者的電腦和手機趁餐,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,205評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來篮绰,“玉大人后雷,你說我怎么就攤上這事》透鳎” “怎么了臀突?”我有些...
    開封第一講書人閱讀 169,421評論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長走孽。 經常有香客問我惧辈,道長琳状,這世上最難降的妖魔是什么磕瓷? 我笑而不...
    開封第一講書人閱讀 60,114評論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮念逞,結果婚禮上困食,老公的妹妹穿的比我還像新娘。我一直安慰自己翎承,他們只是感情好硕盹,可當我...
    茶點故事閱讀 69,116評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著叨咖,像睡著了一般瘩例。 火紅的嫁衣襯著肌膚如雪啊胶。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,713評論 1 312
  • 那天垛贤,我揣著相機與錄音焰坪,去河邊找鬼。 笑死聘惦,一個胖子當著我的面吹牛某饰,可吹牛的內容都是我干的。 我是一名探鬼主播善绎,決...
    沈念sama閱讀 41,170評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼黔漂,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了禀酱?” 一聲冷哼從身側響起炬守,我...
    開封第一講書人閱讀 40,116評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎剂跟,沒想到半個月后劳较,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 46,651評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡浩聋,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,714評論 3 342
  • 正文 我和宋清朗相戀三年观蜗,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片衣洁。...
    茶點故事閱讀 40,865評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡墓捻,死狀恐怖,靈堂內的尸體忽然破棺而出坊夫,到底是詐尸還是另有隱情砖第,我是刑警寧澤,帶...
    沈念sama閱讀 36,527評論 5 351
  • 正文 年R本政府宣布环凿,位于F島的核電站梧兼,受9級特大地震影響,放射性物質發(fā)生泄漏智听。R本人自食惡果不足惜羽杰,卻給世界環(huán)境...
    茶點故事閱讀 42,211評論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望到推。 院中可真熱鬧考赛,春花似錦、人聲如沸莉测。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,699評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽捣卤。三九已至忍抽,卻和暖如春八孝,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背鸠项。 一陣腳步聲響...
    開封第一講書人閱讀 33,814評論 1 274
  • 我被黑心中介騙來泰國打工唆阿, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人锈锤。 一個月前我還...
    沈念sama閱讀 49,299評論 3 379
  • 正文 我出身青樓驯鳖,卻偏偏與公主長得像,于是被迫代替她去往敵國和親久免。 傳聞我的和親對象是個殘疾皇子浅辙,可洞房花燭夜當晚...
    茶點故事閱讀 45,870評論 2 361

推薦閱讀更多精彩內容

  • ZooKeeper是一個高可用的分布式數(shù)據(jù)管理與系統(tǒng)協(xié)調框架⊙掷眩基于對Paxos算法的實現(xiàn)记舆,使該框架保證了分布式環(huán)境...
    會跳舞的機器人閱讀 755評論 0 0
  • ZooKeeper是一個高可用的分布式數(shù)據(jù)管理與系統(tǒng)協(xié)調框架『舭停基于對Paxos算法的實現(xiàn)泽腮,使該框架保證了分布式環(huán)境...
    1b5057877c64閱讀 2,369評論 4 59
  • ZooKeeper 是一個高可用的分布式數(shù)據(jù)管理與系統(tǒng)協(xié)調框架∫赂希基于對 Paxos 算法的實現(xiàn)诊赊,使該框架保證了分布...
    壹點零閱讀 230評論 0 0
  • 數(shù)據(jù)發(fā)布與訂閱(配置中心) 發(fā)布與訂閱模型,即所謂的配置中心府瞄,顧名思義就是發(fā)布者將數(shù)據(jù)發(fā)布到ZK節(jié)點上碧磅,供訂閱者動...
    九都散人閱讀 1,052評論 0 7
  • 此文知識來自于:《從Paxos到Zookeeper分布式一致性原理與實踐》第六章 集群管理(子節(jié)點) Master...
    李文文丶閱讀 543評論 0 1