ZooKeeper原理及使用(轉(zhuǎn))

ZooKeeper是Hadoop Ecosystem中非常重要的組件怔昨,它的主要功能是為分布式系統(tǒng)提供一致性協(xié)調(diào)(Coordination)服務(wù)铐伴,與之對應(yīng)的Google的類似服務(wù)叫 Chubby英染。今天這篇文章分為三個部分來介紹ZooKeeper轨功,第一部分介紹ZooKeeper的基本原理只嚣,第二部分介紹ZooKeeper提供的 Client API的使用乌询,第三部分介紹一些ZooKeeper典型的應(yīng)用場景魄梯。
ZooKeeper基本原理
1. 數(shù)據(jù)模型

如上圖所示猫缭,ZooKeeper數(shù)據(jù)模型的結(jié)構(gòu)與Unix文件系統(tǒng)很類似,整體上可以看作是一棵樹闪金,每個節(jié)點稱做一個ZNode羡滑。每個ZNode都可以通過其路徑唯一標(biāo)識丝格,比如上圖中第三層的第一個ZNode, 它的路徑是/app1/c1聪姿。在每個ZNode上可存儲少量數(shù)據(jù)(默認(rèn)是1M, 可以通過配置修改, 通常不建議在ZNode上存儲大量的數(shù)據(jù))碴萧,這個特性非常有用,在后面的典型應(yīng)用場景中會介紹到末购。另外破喻,每個ZNode上還存儲了其Acl信息,這里需要注意盟榴,雖說ZNode的樹形結(jié)構(gòu)跟Unix文件系統(tǒng)很類似曹质,但是其Acl與Unix文件系統(tǒng)是完全不同的,每個ZNode的Acl的獨立的,子結(jié)點不會繼承父結(jié)點的咆繁。
**2.重要概念 **
2.1 ZNode
前文已介紹了ZNode, ZNode根據(jù)其本身的特性,可以分為下面兩類:
Regular ZNode: 常規(guī)型ZNode, 用戶需要顯式的創(chuàng)建顶籽、刪除
Ephemeral ZNode: 臨時型ZNode, 用戶創(chuàng)建它之后玩般,可以顯式的刪除,也可以在創(chuàng)建它的Session結(jié)束后礼饱,由ZooKeeper Server自動刪除

ZNode還有一個Sequential的特性坏为,如果創(chuàng)建的時候指定的話,該ZNode的名字后面會自動Append一個不斷增加的SequenceNo镊绪。

2.2 Session
Client與ZooKeeper之間的通信匀伏,需要創(chuàng)建一個Session,這個Session會有一個超時時間蝴韭。因為ZooKeeper集群會把 Client的Session信息持久化够颠,所以在Session沒超時之前,Client與ZooKeeper Server的連接可以在各個ZooKeeper Server之間透明地移動榄鉴。
在實際的應(yīng)用中履磨,如果Client與Server之間的通信足夠頻繁,Session的維護(hù)就不需要其它額外的消息了庆尘。否則剃诅,ZooKeeper Client會每t/3 ms發(fā)一次心跳給Server,如果Client 2t/3 ms沒收到來自Server的心跳回應(yīng)驶忌,就會換到一個新的ZooKeeper Server上矛辕。這里t是用戶配置的Session的超時時間。
2.3 Watcher
ZooKeeper支持一種Watch操作付魔,Client可以在某個ZNode上設(shè)置一個Watcher聊品,來Watch該ZNode上的變化。如果該 ZNode上有相應(yīng)的變化几苍,就會觸發(fā)這個Watcher杨刨,把相應(yīng)的事件通知給設(shè)置Watcher的Client。需要注意的是擦剑,ZooKeeper中的 Watcher是一次性的妖胀,即觸發(fā)一次就會被取消,如果想繼續(xù)Watch的話惠勒,需要客戶端重新設(shè)置Watcher赚抡。這個跟epoll里的oneshot模式有點類似。

**3. ZooKeeper特性 **
3.1 讀纠屋、寫(更新)模式
在ZooKeeper集群中涂臣,讀可以從任意一個ZooKeeper Server讀,這一點是保證ZooKeeper比較好的讀性能的關(guān)鍵;寫的請求會先Forwarder到Leader赁遗,然后由Leader來通過 ZooKeeper中的原子廣播協(xié)議署辉,將請求廣播給所有的Follower,Leader收到一半以上的寫成功的Ack后岩四,就認(rèn)為該寫成功了哭尝,就會將該寫進(jìn)行持久化,并告訴客戶端寫成功了剖煌。

3.2 WAL和Snapshot
和大多數(shù)分布式系統(tǒng)一樣材鹦,ZooKeeper也有WAL(Write-Ahead-Log),對于每一個更新操作耕姊,ZooKeeper都會先寫WAL, 然后再對內(nèi)存中的數(shù)據(jù)做更新桶唐,然后向Client通知更新結(jié)果。另外茉兰,ZooKeeper還會定期將內(nèi)存中的目錄樹進(jìn)行Snapshot尤泽,落地到磁盤上,這個跟HDFS中的FSImage是比較類似的规脸。這么做的主要目的安吁,一當(dāng)然是數(shù)據(jù)的持久化,二是加快重啟之后的恢復(fù)速度燃辖,如果全部通過Replay WAL的形式恢復(fù)的話鬼店,會比較慢。

3.3 FIFO
對于每一個ZooKeeper客戶端而言黔龟,所有的操作都是遵循FIFO順序的妇智,這一特性是由下面兩個基本特性來保證的:一是ZooKeeper Client與Server之間的網(wǎng)絡(luò)通信是基于TCP,TCP保證了Client/Server之間傳輸包的順序氏身;二是ZooKeeper Server執(zhí)行客戶端請求也是嚴(yán)格按照FIFO順序的巍棱。

3.4 Linearizability
在ZooKeeper中,所有的更新操作都有嚴(yán)格的偏序關(guān)系蛋欣,更新操作都是串行執(zhí)行的航徙,這一點是保證ZooKeeper功能正確性的關(guān)鍵。

3.5 ZooKeeper Client API
ZooKeeper Client Library提供了豐富直觀的API供用戶程序使用陷虎,下面是一些常用的API:
create(path, data, flags): 創(chuàng)建一個ZNode, path是其路徑到踏,data是要存儲在該ZNode上的數(shù)據(jù),flags常用的有: PERSISTEN, PERSISTENT_SEQUENTAIL, EPHEMERAL, EPHEMERAL_SEQUENTAIL
delete(path, version): 刪除一個ZNode尚猿,可以通過version刪除指定的版本, 如果version是-1的話窝稿,表示刪除所有的版本.exists(path, watch): 判斷指定ZNode是否存在,并設(shè)置是否Watch這個ZNode凿掂。這里如果要設(shè)置Watcher的話伴榔,Watcher是在創(chuàng)建ZooKeeper實例時指定的,如果要設(shè)置特定的Watcher的話,可以調(diào)用另一個重載版本的exists(path, watcher)踪少。以下幾個帶watch參數(shù)的API也都類似
getData(path, watch): 讀取指定ZNode上的數(shù)據(jù)塘安,并設(shè)置是否watch這個ZNode
setData(path, watch): 更新指定ZNode的數(shù)據(jù),并設(shè)置是否Watch這個ZNode
getChildren(path, watch): 獲取指定ZNode的所有子ZNode的名字援奢,并設(shè)置是否Watch這個ZNode兼犯。sync(path): 把所有在sync之前的更新操作都進(jìn)行同步,達(dá)到每個請求都在半數(shù)以上的ZooKeeper Server上生效萝究。path參數(shù)目前沒有用
setAcl(path, acl): 設(shè)置指定ZNode的Acl信息
getAcl(path): 獲取指定ZNode的Acl信息

ZooKeeper典型應(yīng)用場景
**1. 名字服務(wù)(NameService) ** 分布式應(yīng)用中,通常需要一套完備的命令機(jī)制锉罐,既能產(chǎn)生唯一的標(biāo)識帆竹,又方便人識別和記憶。 我們知道脓规,每個ZNode都可以由其路徑唯一標(biāo)識栽连,路徑本身也比較簡潔直觀,另外ZNode上還可以存儲少量數(shù)據(jù)侨舆,這些都是實現(xiàn)統(tǒng)一的 NameService的基礎(chǔ)秒紧。下面以在HDFS中實現(xiàn)NameService為例,來說明實現(xiàn)NameService的基本布驟:
目標(biāo):通過簡單的名字來訪問指定的HDFS機(jī)群
定義命名規(guī)則:這里要做到簡潔易記憶挨下。下面是一種可選的方案: [serviceScheme://][zkCluster]-[clusterName]熔恢,比如hdfs://lgprc-example/表示基于 lgprc ZooKeeper集群的用來做example的HDFS集群
配置DNS映射: 將zkCluster的標(biāo)識lgprc通過DNS解析到對應(yīng)的ZooKeeper集群的地址
創(chuàng)建ZNode: 在對應(yīng)的ZooKeeper上創(chuàng)建/NameService/hdfs/lgprc-example結(jié)點,將HDFS的配置文件存儲于該結(jié)點下
用戶程序要訪問hdfs://lgprc-example/的HDFS集群臭笆,首先通過DNS找到lgprc的ZooKeeper機(jī)群的地址叙淌,然后在 ZooKeeper的/NameService/hdfs/lgprc-example結(jié)點中讀取到HDFS的配置,進(jìn)而根據(jù)得到的配置愁铺,得到HDFS的實際訪問入口

**2. 配置管理(Configuration Management) ** 在分布式系統(tǒng)中鹰霍,常會遇到這樣的場景: 某個Job的很多個實例在運(yùn)行,它們在運(yùn)行時大多數(shù)配置項是相同的茵乱,如果想要統(tǒng)一改某個配置茂洒,一個個實例去改,是比較低效瓶竭,也是比較容易出錯的方式督勺。通過ZooKeeper可以很好的解決這樣的問題,下面的基本的步驟:
將公共的配置內(nèi)容放到ZooKeeper中某個ZNode上斤贰,比如/service/common-conf
所有的實例在啟動時都會傳入ZooKeeper集群的入口地址玷氏,并且在運(yùn)行過程中Watch /service/common-conf這個ZNode
如果集群管理員修改了了common-conf,所有的實例都會被通知到腋舌,根據(jù)收到的通知更新自己的配置盏触,并繼續(xù)Watch /service/common-conf

**3. 組員管理(Group Membership) ** 在典型的Master-Slave結(jié)構(gòu)的分布式系統(tǒng)中,Master需要作為“總管”來管理所有的Slave, 當(dāng)有Slave加入,或者有Slave宕機(jī)赞辩,Master都需要感知到這個事情雌芽,然后作出對應(yīng)的調(diào)整,以便不影響整個集群對外提供服務(wù)辨嗽。以HBase為例世落,HMaster管理了所有的RegionServer,當(dāng)有新的RegionServer加入的時候糟需,HMaster需要分配一些Region到該 RegionServer上去屉佳,讓其提供服務(wù);當(dāng)有RegionServer宕機(jī)時洲押,HMaster需要將該RegionServer之前服務(wù)的 Region都重新分配到當(dāng)前正在提供服務(wù)的其它RegionServer上武花,以便不影響客戶端的正常訪問。下面是這種場景下使用ZooKeeper的基本步驟:
Master在ZooKeeper上創(chuàng)建/service/slaves結(jié)點杈帐,并設(shè)置對該結(jié)點的Watcher
每個Slave在啟動成功后体箕,創(chuàng)建唯一標(biāo)識自己的臨時性(Ephemeral)結(jié)點/service/slaves/${slave_id},并將自己地址(ip/port)等相關(guān)信息寫入該結(jié)點
Master收到有新子結(jié)點加入的通知后挑童,做相應(yīng)的處理
如果有Slave宕機(jī)累铅,由于它所對應(yīng)的結(jié)點是臨時性結(jié)點,在它的Session超時后站叼,ZooKeeper會自動刪除該結(jié)點
Master收到有子結(jié)點消失的通知娃兽,做相應(yīng)的處理

**4. 簡單互斥鎖(Simple Lock) ** 我們知識,在傳統(tǒng)的應(yīng)用程序中尽楔,線程换薄、進(jìn)程的同步,都可以通過操作系統(tǒng)提供的機(jī)制來完成翔试。但是在分布式系統(tǒng)中轻要,多個進(jìn)程之間的同步,操作系統(tǒng)層面就無能為力了垦缅。這時候就需要像ZooKeeper這樣的分布式的協(xié)調(diào)(Coordination)服務(wù)來協(xié)助完成同步冲泥,下面是用ZooKeeper實現(xiàn)簡單的互斥鎖的步驟,這個可以和線程間同步的mutex做類比來理解:
多個進(jìn)程嘗試去在指定的目錄下去創(chuàng)建一個臨時性(Ephemeral)結(jié)點 /locks/my_lock
ZooKeeper能保證壁涎,只會有一個進(jìn)程成功創(chuàng)建該結(jié)點凡恍,創(chuàng)建結(jié)點成功的進(jìn)程就是搶到鎖的進(jìn)程,假設(shè)該進(jìn)程為A
其它進(jìn)程都對/locks/my_lock進(jìn)行Watch
當(dāng) A進(jìn)程不再需要鎖怔球,可以顯式刪除/locks/my_lock釋放鎖嚼酝;或者是A進(jìn)程宕機(jī)后Session超時,ZooKeeper系統(tǒng)自動刪除 /locks/my_lock結(jié)點釋放鎖竟坛。此時闽巩,其它進(jìn)程就會收到ZooKeeper的通知钧舌,并嘗試去創(chuàng)建/locks/my_lock搶鎖,如此循環(huán)反復(fù)

**5. 互斥鎖(Simple Lock without Herd Effect) ** 上一節(jié)的例子中有一個問題涎跨,每次搶鎖都會有大量的進(jìn)程去競爭洼冻,會造成羊群效應(yīng)(Herd Effect),為了解決這個問題隅很,我們可以通過下面的步驟來改進(jìn)上述過程:
每個進(jìn)程都在ZooKeeper上創(chuàng)建一個臨時的順序結(jié)點(Ephemeral Sequential) /locks/lock_${seq}
${seq}最小的為當(dāng)前的持鎖者(${seq}是ZooKeeper生成的Sequenctial Number)
其它進(jìn)程都對只watch比它次小的進(jìn)程對應(yīng)的結(jié)點撞牢,比如2 watch 1, 3 watch 2, 以此類推
當(dāng)前持鎖者釋放鎖后,比它次大的進(jìn)程就會收到ZooKeeper的通知叔营,它成為新的持鎖者屋彪,如此循環(huán)反復(fù)

這里需要補(bǔ)充一點,通常在分布式系統(tǒng)中用ZooKeeper來做Leader Election(選主)就是通過上面的機(jī)制來實現(xiàn)的绒尊,這里的持鎖者就是當(dāng)前的“主”畜挥。

**6. 讀寫鎖(Read/Write Lock) ** 我們知道,讀寫鎖跟互斥鎖相比不同的地方是垒酬,它分成了讀和寫兩種模式砰嘁,多個讀可以并發(fā)執(zhí)行件炉,但寫和讀勘究、寫都互斥,不能同時執(zhí)行行斟冕。利用ZooKeeper口糕,在上面的基礎(chǔ)上,稍做修改也可以實現(xiàn)傳統(tǒng)的讀寫鎖的語義磕蛇,下面是基本的步驟:
每個進(jìn)程都在ZooKeeper上創(chuàng)建一個臨時的順序結(jié)點(Ephemeral Sequential) /locks/lock_${seq}
${seq}最小的一個或多個結(jié)點為當(dāng)前的持鎖者景描,多個是因為多個讀可以并發(fā)
需要寫鎖的進(jìn)程,Watch比它次小的進(jìn)程對應(yīng)的結(jié)點
需要讀鎖的進(jìn)程秀撇,Watch比它小的最后一個寫進(jìn)程對應(yīng)的結(jié)點
當(dāng)前結(jié)點釋放鎖后超棺,所有Watch該結(jié)點的進(jìn)程都會被通知到,他們成為新的持鎖者呵燕,如此循環(huán)反復(fù)

**7. 屏障(Barrier) ** 在分布式系統(tǒng)中棠绘,屏障是這樣一種語義: 客戶端需要等待多個進(jìn)程完成各自的任務(wù),然后才能繼續(xù)往前進(jìn)行下一步再扭。下用是用ZooKeeper來實現(xiàn)屏障的基本步驟:
Client在ZooKeeper上創(chuàng)建屏障結(jié)點/barrier/my_barrier氧苍,并啟動執(zhí)行各個任務(wù)的進(jìn)程
Client通過exist()來Watch /barrier/my_barrier結(jié)點
每個任務(wù)進(jìn)程在完成任務(wù)后,去檢查是否達(dá)到指定的條件泛范,如果沒達(dá)到就啥也不做让虐,如果達(dá)到了就把/barrier/my_barrier結(jié)點刪除
Client收到/barrier/my_barrier被刪除的通知,屏障消失罢荡,繼續(xù)下一步任務(wù)

8. 雙屏障(Double Barrier) 雙屏障是這樣一種語義: 它可以用來同步一個任務(wù)的開始和結(jié)束赡突,當(dāng)有足夠多的進(jìn)程進(jìn)入屏障后对扶,才開始執(zhí)行任務(wù);當(dāng)所有的進(jìn)程都執(zhí)行完各自的任務(wù)后麸俘,屏障才撤銷辩稽。下面是用ZooKeeper來實現(xiàn)雙屏障的基本步驟:
進(jìn)入屏障:Client Watch /barrier/ready結(jié)點, 通過判斷該結(jié)點是否存在來決定是否啟動任務(wù)
每個任務(wù)進(jìn)程進(jìn)入屏障時創(chuàng)建一個臨時結(jié)點/barrier/process/${process_id},然后檢查進(jìn)入屏障的結(jié)點數(shù)是否達(dá)到指定的值从媚,如果達(dá)到了指定的值逞泄,就創(chuàng)建一個/barrier/ready結(jié)點,否則繼續(xù)等待
Client收到/barrier/ready創(chuàng)建的通知拜效,就啟動任務(wù)執(zhí)行過程

離開屏障:Client Watch /barrier/process喷众,如果其沒有子結(jié)點,就可以認(rèn)為任務(wù)執(zhí)行結(jié)束紧憾,可以離開屏障

每個任務(wù)進(jìn)程執(zhí)行任務(wù)結(jié)束后到千,都需要刪除自己對應(yīng)的結(jié)點/barrier/process/${process_id}

原文鏈接:http://www.wuzesheng.com/?p=2609
比較好的一篇文章 :zookeeper

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市赴穗,隨后出現(xiàn)的幾起案子憔四,更是在濱河造成了極大的恐慌,老刑警劉巖般眉,帶你破解...
    沈念sama閱讀 219,039評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件了赵,死亡現(xiàn)場離奇詭異,居然都是意外死亡甸赃,警方通過查閱死者的電腦和手機(jī)柿汛,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,426評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來埠对,“玉大人络断,你說我怎么就攤上這事∠盥辏” “怎么了貌笨?”我有些...
    開封第一講書人閱讀 165,417評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長襟沮。 經(jīng)常有香客問我锥惋,道長,這世上最難降的妖魔是什么臣嚣? 我笑而不...
    開封第一講書人閱讀 58,868評論 1 295
  • 正文 為了忘掉前任净刮,我火速辦了婚禮,結(jié)果婚禮上硅则,老公的妹妹穿的比我還像新娘淹父。我一直安慰自己,他們只是感情好怎虫,可當(dāng)我...
    茶點故事閱讀 67,892評論 6 392
  • 文/花漫 我一把揭開白布暑认。 她就那樣靜靜地躺著困介,像睡著了一般。 火紅的嫁衣襯著肌膚如雪蘸际。 梳的紋絲不亂的頭發(fā)上座哩,一...
    開封第一講書人閱讀 51,692評論 1 305
  • 那天,我揣著相機(jī)與錄音粮彤,去河邊找鬼根穷。 笑死,一個胖子當(dāng)著我的面吹牛导坟,可吹牛的內(nèi)容都是我干的屿良。 我是一名探鬼主播,決...
    沈念sama閱讀 40,416評論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼惫周,長吁一口氣:“原來是場噩夢啊……” “哼尘惧!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起递递,我...
    開封第一講書人閱讀 39,326評論 0 276
  • 序言:老撾萬榮一對情侶失蹤喷橙,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后登舞,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體贰逾,經(jīng)...
    沈念sama閱讀 45,782評論 1 316
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,957評論 3 337
  • 正文 我和宋清朗相戀三年逊躁,在試婚紗的時候發(fā)現(xiàn)自己被綠了似踱。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片隅熙。...
    茶點故事閱讀 40,102評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡稽煤,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出囚戚,到底是詐尸還是另有隱情酵熙,我是刑警寧澤,帶...
    沈念sama閱讀 35,790評論 5 346
  • 正文 年R本政府宣布驰坊,位于F島的核電站匾二,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏拳芙。R本人自食惡果不足惜察藐,卻給世界環(huán)境...
    茶點故事閱讀 41,442評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望舟扎。 院中可真熱鬧分飞,春花似錦、人聲如沸睹限。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,996評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至染服,卻和暖如春别洪,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背柳刮。 一陣腳步聲響...
    開封第一講書人閱讀 33,113評論 1 272
  • 我被黑心中介騙來泰國打工挖垛, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人秉颗。 一個月前我還...
    沈念sama閱讀 48,332評論 3 373
  • 正文 我出身青樓晕换,卻偏偏與公主長得像,于是被迫代替她去往敵國和親站宗。 傳聞我的和親對象是個殘疾皇子闸准,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,044評論 2 355

推薦閱讀更多精彩內(nèi)容