組建介紹--Zookeeper_第1頁
組建介紹--Zookeeper_第2頁
組建介紹--Zookeeper_第3頁
組建介紹--Zookeeper_第4頁
組建介紹--Zookeeper_第5頁
已閱讀5頁,還剩29頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

1、Zookeeper1. Zookeeper基本概念ZooKeeper是一個分布式的,開放源碼的分布式應(yīng)用程序協(xié)調(diào)服務(wù),是Google的Chubby一個開源的實現(xiàn),是Hadoop和Hbase的重要組件。它是一個為分布式應(yīng)用提供一致性服務(wù)的軟件,提供的功能包括:配置維護、域名服務(wù)、分布式同步、組服務(wù)等。ZooKeeper的目標(biāo)就是封裝好復(fù)雜易出錯的關(guān)鍵服務(wù),將簡單易用的接口和性能高效、功能穩(wěn)定的系統(tǒng)提供給用戶。它包含一個簡單的原語集,提供Java和C的接口。ZooKeeper代碼版本中,提供了分布式獨享鎖、選舉、隊列的接口,代碼在.srcrecipes。其中分布鎖和隊列有Java和C兩個版本,選舉

2、只有Java版本。1.1 角色Zookeeper中的角色主要有以下三類,如下表所示:1.2 系統(tǒng)模型如圖所示:1.3 設(shè)計目的1.最終一致性:client不論連接到哪個Server,展示給它都是同一個視圖,這是zookeeper最重要的性能。2 .可靠性:具有簡單、健壯、良好的性能,如果消息m被到一臺服務(wù)器接受,那么它將被所有的服務(wù)器接受。3 .實時性:Zookeeper保證客戶端將在一個時間間隔范圍內(nèi)獲得服務(wù)器的更新信息,或者服務(wù)器失效的信息。但由于網(wǎng)絡(luò)延時等原因,Zookeeper不能保證兩個客戶端能同時得到剛更新的數(shù)據(jù),如果需要最新數(shù)據(jù),應(yīng)該在讀數(shù)據(jù)之前調(diào)用sync()接口。4 .等待無

3、關(guān)(wait-free):慢的或者失效的client不得干預(yù)快速的client的請求,使得每個client都能有效的等待。5.原子性:更新只能成功或者失敗,沒有中間狀態(tài)。6 .順序性:包括全局有序和偏序兩種:全局有序是指如果在一臺服務(wù)器上消息a在消息b前發(fā)布,則在所有Server上消息a都將在消息b前被發(fā)布;偏序是指如果一個消息b在消息a后被同一個發(fā)送者發(fā)布,a必將排在b前面。1.4 重要概念ZNodeZNode根據(jù)其本身的特性,可以分為下面兩類:l Regular ZNode: 常規(guī)型ZNode, 用戶需要顯式的創(chuàng)建、刪除l Ephemeral ZNode: 臨時型ZNode, 用戶創(chuàng)建它之

4、后,可以顯式的刪除,也可以在創(chuàng)建它的Session結(jié)束后,由ZooKeeper Server自動刪除l ZNode還有一個Sequential的特性,如果創(chuàng)建的時候指定的話,該ZNode的名字后面會自動Append一個不斷增加的SequenceNo。SessionClient與ZooKeeper之間的通信,需要創(chuàng)建一個Session,這個Session會有一個超時時間。因為ZooKeeper集群會把Client的Session信息持久化,所以在Session沒超時之前,Client與ZooKeeper Server的連接可以在各個ZooKeeper Server之間透明地移動。在實際的應(yīng)用中,

5、如果Client與Server之間的通信足夠頻繁,Session的維護就不需要其它額外的消息了。否則,ZooKeeper Client會每t/3 ms發(fā)一次心跳給Server,如果Client 2t/3 ms沒收到來自Server的心跳回應(yīng),就會換到一個新的ZooKeeper Server上。這里t是用戶配置的Session的超時時間。WatcherZooKeeper支持一種Watch操作,Client可以在某個ZNode上設(shè)置一個Watcher,來Watch該ZNode上的變化。如果該ZNode上有相應(yīng)的變化,就會觸發(fā)這個Watcher,把相應(yīng)的事件通知給設(shè)置Watcher的Client。需

6、要注意的是,ZooKeeper中的Watcher是一次性的,即觸發(fā)一次就會被取消,如果想繼續(xù)Watch的話,需要客戶端重新設(shè)置Watcher。這個跟epoll里的oneshot模式有點類似。1.5 Zookeeper基本原理數(shù)據(jù)模型如上圖所示,ZooKeeper數(shù)據(jù)模型的結(jié)構(gòu)與Unix文件系統(tǒng)很類似,整體上可以看作是一棵樹,每個節(jié)點稱做一個ZNode。每個ZNode都可以通過其路徑唯一標(biāo)識,比如上圖中第三層的第一個ZNode, 它的路徑是/app1/c1。在每個ZNode上可存儲少量數(shù)據(jù)(默認是1M, 可以通過配置修改, 通常不建議在ZNode上存儲大量的數(shù)據(jù)),這個特性非常有用,在后面的典型

7、應(yīng)用場景中會介紹到。另外,每個ZNode上還存儲了其Acl信息,這里需要注意,雖說ZNode的樹形結(jié)構(gòu)跟Unix文件系統(tǒng)很類似,但是其Acl與Unix文件系統(tǒng)是完全不同的,每個ZNode的Acl的獨立的,子結(jié)點不會繼承父結(jié)點的,關(guān)于ZooKeeper中的Acl可以參考之前寫過的一篇文章說說Zookeeper中的ACL。Zookeeper這種數(shù)據(jù)結(jié)構(gòu)有如下這些特點:1)每個子目錄項如NameService都被稱作為znode,這個znode是被它所在的路徑唯一標(biāo)識,如Server1這個znode的標(biāo)識為/NameService/Server1。2)znode可以有子節(jié)點目錄,并且每個znode可

8、以存儲數(shù)據(jù),注意EPHEMERAL(臨時的)類型的目錄節(jié)點不能有子節(jié)點目錄。3)znode是有版本的(version),每個znode中存儲的數(shù)據(jù)可以有多個版本,也就是一個訪問路徑中可以存儲多份數(shù)據(jù),version號自動增加。4)znode可以是臨時節(jié)點(EPHEMERAL),可以是持久節(jié)點(PERSISTENT)。如果創(chuàng)建的是臨時節(jié)點,一旦創(chuàng)建這個EPHEMERALznode的客戶端與服務(wù)器失去聯(lián)系,這個znode也將自動刪除,Zookeeper的客戶端和服務(wù)器通信采用長連接方式,每個客戶端和服務(wù)器通過心跳來保持連接,這個連接狀態(tài)稱為session,如果znode是臨時節(jié)點,這個sessio

9、n失效,znode也就刪除了。5)znode的目錄名可以自動編號,如App1已經(jīng)存在,再創(chuàng)建的話,將會自動命名為App2。6)znode可以被監(jiān)控,包括這個目錄節(jié)點中存儲的數(shù)據(jù)的修改,子節(jié)點目錄的變化等,一旦變化可以通知設(shè)置監(jiān)控的客戶端,這個是Zookeeper的核心特性,Zookeeper的很多功能都是基于這個特性實現(xiàn)的。7)ZXID:每次對Zookeeper的狀態(tài)的改變都會產(chǎn)生一個zxid(ZooKeeper Transaction Id),zxid是全局有序的,如果zxid1小于zxid2,則zxid1在zxid2之前發(fā)生。1.6 Zookeeper特性 1.讀、寫(更新)模式

10、在ZooKeeper集群中,讀可以從任意一個ZooKeeper Server讀,這一點是保證ZooKeeper比較好的讀性能的關(guān)鍵;寫的請求會先Forwarder到Leader,然后由Leader來通過ZooKeeper中的原子廣播協(xié)議,將請求廣播給所有的Follower,Leader收到一半以上的寫成功的Ack后,就認為該寫成功了,就會將該寫進行持久化,并告訴客戶端寫成功了。2.WAL和Snapshot和大多數(shù)分布式系統(tǒng)一樣,ZooKeeper也有WAL(Write-Ahead-Log),對于每一個更新操作,ZooKeeper都會先寫WAL, 然后再對內(nèi)存中的數(shù)據(jù)做更新,然后向Client通

11、知更新結(jié)果。另外,ZooKeeper還會定期將內(nèi)存中的目錄樹進行Snapshot,落地到磁盤上,這個跟HDFS中的FSImage是比較類似的。這么做的主要目的,一當(dāng)然是數(shù)據(jù)的持久化,二是加快重啟之后的恢復(fù)速度,如果全部通過Replay WAL的形式恢復(fù)的話,會比較慢。3.FIFO對于每一個ZooKeeper客戶端而言,所有的操作都是遵循FIFO順序的,這一特性是由下面兩個基本特性來保證的:一是ZooKeeper Client與Server之間的網(wǎng)絡(luò)通信是基于TCP,TCP保證了Client/Server之間傳輸包的順序;二是ZooKeeper Server執(zhí)行客戶端請求也是嚴格按照FIFO順序

12、的。4.Linearizability在ZooKeeper中,所有的更新操作都有嚴格的偏序關(guān)系,更新操作都是串行執(zhí)行的,這一點是保證ZooKeeper功能正確性的關(guān)鍵。2. 工作原理Zookeeper的核心是原子廣播,這個機制保證了各個Server之間的同步。實現(xiàn)這個機制的協(xié)議叫做Zab協(xié)議。Zab協(xié)議有兩種模式,它們分別是恢復(fù)模式(選主)和廣播模式(同步)。當(dāng)服務(wù)啟動或者在領(lǐng)導(dǎo)者崩潰后,Zab就進入了恢復(fù)模式,當(dāng)領(lǐng)導(dǎo)者被選舉出來,且大多數(shù)Server完成了和leader的狀態(tài)同步以后,恢復(fù)模式就結(jié)束了。狀態(tài)同步保證了leader和Server具有相同的系統(tǒng)狀態(tài)。為了保證事務(wù)的順序一致性,zo

13、okeeper采用了遞增的事務(wù)id號(zxid)來標(biāo)識事務(wù)。所有的提議(proposal)都在被提出的時候加上了zxid。實現(xiàn)中zxid是一個64位的數(shù)字,它高32位是epoch用來標(biāo)識leader關(guān)系是否改變,每次一個leader被選出來,它都會有一個新的epoch,標(biāo)識當(dāng)前屬于那個leader的統(tǒng)治時期。低32位用于遞增計數(shù)。每個Server在工作過程中有三種狀態(tài):l LOOKING:當(dāng)前Server不知道leader是誰,正在搜尋l LEADING:當(dāng)前Server即為選舉出來的leaderl FOLLOWING:leader已經(jīng)選舉出來,當(dāng)前Server與之同步2.1 選主流程 當(dāng)le

14、ader崩潰或者leader失去大多數(shù)的follower,這時候zk進入恢復(fù)模式,恢復(fù)模式需要重新選舉出一個新的leader,讓所有的Server都恢復(fù)到一個正確的狀態(tài)。Zk的選舉算法有兩種:一種是基于basic paxos實現(xiàn)的,另外一種是基于fast paxos算法實現(xiàn)的。系統(tǒng)默認的選舉算法為fast paxos。先介紹basic paxos流程: 1.選舉線程由當(dāng)前Server發(fā)起選舉的線程擔(dān)任,其主要功能是對投票結(jié)果進行統(tǒng)計,并選出推薦的Server; 2.選舉線程首先向所有Server發(fā)起一次詢問(包括自己); 3選舉線程收到回復(fù)后,驗證是否是自己發(fā)起的詢問(驗證zxid是否一致),

15、然后獲取對方的id(myid),并存儲到當(dāng)前詢問對象列表中,最后獲取對方提議的leader相關(guān)信息(id,zxid),并將這些信息存儲到當(dāng)次選舉的投票記錄表中; 4.收到所有Server回復(fù)以后,就計算出zxid最大的那個Server,并將這個Server相關(guān)信息設(shè)置成下一次要投票的Server; 5.  線程將當(dāng)前zxid最大的Server設(shè)置為當(dāng)前Server要推薦的Leader,如果此時獲勝的Server獲得n/2 + 1的Server票數(shù), 設(shè)置當(dāng)前推薦的leader為獲勝的Server,將根據(jù)獲勝的Server相關(guān)信息設(shè)置自己的狀態(tài),否則,繼續(xù)這個過程,直到leader被選

16、舉出來。 通過流程分析我們可以得出:要使Leader獲得多數(shù)Server的支持,則Server總數(shù)必須是奇數(shù)2n+1,且存活的Server的數(shù)目不得少于n+1. 每個Server啟動后都會重復(fù)以上流程。在恢復(fù)模式下,如果是剛從崩潰狀態(tài)恢復(fù)的或者剛啟動的server還會從磁盤快照中恢復(fù)數(shù)據(jù)和會話信息,zk會記錄事務(wù)日志并定期進行快照,方便在恢復(fù)時進行狀態(tài)恢復(fù)。選主的具體流程圖如下所示:fast paxos流程是在選舉過程中,某Server首先向所有Server提議自己要成為leader,當(dāng)其它Server收到提議以后,解決epoch和zxid的沖突,并接受對方的提議,然后向?qū)Ψ桨l(fā)送接受提議完成的

17、消息,重復(fù)這個流程,最后一定能選舉出Leader。其流程圖如下所示:2.2 同步流程選完leader以后,zk就進入狀態(tài)同步過程。1. leader等待server連接;2 .Follower連接leader,將最大的zxid發(fā)送給leader;3 .Leader根據(jù)follower的zxid確定同步點;4 .完成同步后通知follower 已經(jīng)成為uptodate狀態(tài);5 .Follower收到uptodate消息后,又可以重新接受client的請求進行服務(wù)了。流程圖如下所示:2.3 工作流程2.3.1 Leader工作流程Leader主要有三個功能:1 .恢復(fù)數(shù)據(jù);2 .維持與Learne

18、r的心跳,接收Learner請求并判斷Learner的請求消息類型;3 .Learner的消息類型主要有PING消息、REQUEST消息、ACK消息、REVALIDATE消息,根據(jù)不同的消息類型,進行不同的處理。PING消息是指Learner的心跳信息;REQUEST消息是Follower發(fā)送的提議信息,包括寫請求及同步請求;ACK消息是Follower的對提議的回復(fù),超過半數(shù)的Follower通過,則commit該提議;REVALIDATE消息是用來延長SESSION有效時間。Leader的工作流程簡圖如下所示,在實際實現(xiàn)中,流程要比下圖復(fù)雜得多,啟動了三個線程來實現(xiàn)功能。2.3.2 Fol

19、lower工作流程Follower主要有四個功能:1. 向Leader發(fā)送請求(PING消息、REQUEST消息、ACK消息、REVALIDATE消息);2 .接收Leader消息并進行處理;3 .接收Client的請求,如果為寫請求,發(fā)送給Leader進行投票;4 .返回Client結(jié)果。Follower的消息循環(huán)處理如下幾種來自Leader的消息:1 .PING消息: 心跳消息;2 .PROPOSAL消息:Leader發(fā)起的提案,要求Follower投票;3 .COMMIT消息:服務(wù)器端最新一次提案的信息;4 .UPTODATE消息:表明同步完成;5 .REVALIDATE消息:根據(jù)Lea

20、der的REVALIDATE結(jié)果,關(guān)閉待revalidate的session還是允許其接受消息;6 .SYNC消息:返回SYNC結(jié)果到客戶端,這個消息最初由客戶端發(fā)起,用來強制得到最新的更新。Follower的工作流程簡圖如下所示,在實際實現(xiàn)中,F(xiàn)ollower是通過5個線程來實現(xiàn)功能的。對于observer的流程不再敘述,observer流程和Follower的唯一不同的地方就是observer不會參加leader發(fā)起的投票。3. Zookeeper的主流應(yīng)用場景實現(xiàn)思路 (1)配置管理集中式的配置管理在應(yīng)用集群中是非常常見的,一般商業(yè)公司內(nèi)部都會實現(xiàn)一套集中的配置管理中心,應(yīng)對不同的應(yīng)用集

21、群對于共享各自配置的需求,并且在配置變更時能夠通知到集群中的每一個機器。Zookeeper很容易實現(xiàn)這種集中式的配置管理,比如將APP1的所有配置配置到/APP1 znode下,APP1所有機器一啟動就對/APP1這個節(jié)點進行監(jiān)控(zk.exist("/APP1",true),并且實現(xiàn)回調(diào)方法Watcher,那么在zookeeper上/APP1 znode節(jié)點下數(shù)據(jù)發(fā)生變化的時候,每個機器都會收到通知,Watcher方法將會被執(zhí)行,那么應(yīng)用再取下數(shù)據(jù)即可(zk.getData("/APP1",false,null);以上這個例子只是簡單的粗顆粒度配置監(jiān)控

22、,細顆粒度的數(shù)據(jù)可以進行分層級監(jiān)控,這一切都是可以設(shè)計和控制的。(2)集群管理應(yīng)用集群中,我們常常需要讓每一個機器知道集群中(或依賴的其他某一個集群)哪些機器是活著的,并且在集群機器因為宕機,網(wǎng)絡(luò)斷鏈等原因能夠不在人工介入的情況下迅速通知到每一個機器。Zookeeper同樣很容易實現(xiàn)這個功能,比如我在zookeeper服務(wù)器端有一個znode叫/APP1SERVERS,那么集群中每一個機器啟動的時候都去這個節(jié)點下創(chuàng)建一個EPHEMERAL類型的節(jié)點,比如server1創(chuàng)建/APP1SERVERS/SERVER1(可以使用ip,保證不重復(fù)),server2創(chuàng)建/APP1SERVERS/SERVE

23、R2,然后SERVER1和SERVER2都watch /APP1SERVERS這個父節(jié)點,那么也就是這個父節(jié)點下數(shù)據(jù)或者子節(jié)點變化都會通知對該節(jié)點進行watch的客戶端。因為EPHEMERAL類型節(jié)點有一個很重要的特性,就是客戶端和服務(wù)器端連接斷掉或者session過期就會使節(jié)點消失,那么在某一個機器掛掉或者斷鏈的時候,其對應(yīng)的節(jié)點就會消失,然后集群中所有對/APP1SERVERS進行watch的客戶端都會收到通知,然后取得最新列表即可。另外有一個應(yīng)用場景就是集群選master,一旦master掛掉能夠馬上能從slave中選出一個master,實現(xiàn)步驟和前者一樣,只是機器在啟動的時候在APP1

24、SERVERS創(chuàng)建的節(jié)點類型變?yōu)镋PHEMERAL_SEQUENTIAL類型,這樣每個節(jié)點會自動被編號我們默認規(guī)定編號最小的為master,所以當(dāng)我們對/APP1SERVERS節(jié)點做監(jiān)控的時候,得到服務(wù)器列表,只要所有集群機器邏輯認為最小編號節(jié)點為master,那么master就被選出,而這個master宕機的時候,相應(yīng)的znode會消失,然后新的服務(wù)器列表就被推送到客戶端,然后每個節(jié)點邏輯認為最小編號節(jié)點為master,這樣就做到動態(tài)master選舉。1. 名字服務(wù)(NameService)分布式應(yīng)用中,通常需要一套完備的命令機制,既能產(chǎn)生唯一的標(biāo)識,又方便人識別和記憶。 我們知道,每個ZN

25、ode都可以由其路徑唯一標(biāo)識,路徑本身也比較簡潔直觀,另外ZNode上還可以存儲少量數(shù)據(jù),這些都是實現(xiàn)統(tǒng)一的NameService的基礎(chǔ)。下面以在HDFS中實現(xiàn)NameService為例,來說明實現(xiàn)NameService的基本布驟:l 目標(biāo):通過簡單的名字來訪問指定的HDFS機群l 定義命名規(guī)則:這里要做到簡潔易記憶。下面是一種可選的方案: serviceScheme:/zkCluster-clusterName,比如hdfs:/lgprc-example/表示基于lgprc ZooKeeper集群的用來做example的HDFS集群l 配置DNS映射: 將zkCluster的標(biāo)識lgprc通

26、過DNS解析到對應(yīng)的ZooKeeper集群的地址l 創(chuàng)建ZNode: 在對應(yīng)的ZooKeeper上創(chuàng)建/NameService/hdfs/lgprc-example結(jié)點,將HDFS的配置文件存儲于該結(jié)點下l 用戶程序要訪問hdfs:/lgprc-example/的HDFS集群,首先通過DNS找到lgprc的ZooKeeper機群的地址,然后在ZooKeeper的/NameService/hdfs/lgprc-example結(jié)點中讀取到HDFS的配置,進而根據(jù)得到的配置,得到HDFS的實際訪問入口2. 配置管理(Configuration Management) 在分布式系統(tǒng)中,常會遇

27、到這樣的場景: 某個Job的很多個實例在運行,它們在運行時大多數(shù)配置項是相同的,如果想要統(tǒng)一改某個配置,一個個實例去改,是比較低效,也是比較容易出錯的方式。通過ZooKeeper可以很好的解決這樣的問題,下面的基本的步驟:l 將公共的配置內(nèi)容放到ZooKeeper中某個ZNode上,比如/service/common-confl 所有的實例在啟動時都會傳入ZooKeeper集群的入口地址,并且在運行過程中Watch /service/common-conf這個ZNodel 如果集群管理員修改了了common-conf,所有的實例都會被通知到,根據(jù)收到的通知更新自己的配置,并繼續(xù)Watch /s

28、ervice/common-conf3. 組員管理(Group Membership) 在典型的Master-Slave結(jié)構(gòu)的分布式系統(tǒng)中,Master需要作為“總管”來管理所有的Slave, 當(dāng)有Slave加入,或者有Slave宕機,Master都需要感知到這個事情,然后作出對應(yīng)的調(diào)整,以便不影響整個集群對外提供服務(wù)。以Hbase為例,HMaster管理了所有的RegionServer,當(dāng)有新的RegionServer加入的時候,HMaster需要分配一些Region到該RegionServer上去,讓其提供服務(wù);當(dāng)有RegionServer宕機時,HMaster需要將該Regio

29、nServer之前服務(wù)的Region都重新分配到當(dāng)前正在提供服務(wù)的其它RegionServer上,以便不影響客戶端的正常訪問。下面是這種場景下使用ZooKeeper的基本步驟:l Master在ZooKeeper上創(chuàng)建/service/slaves結(jié)點,并設(shè)置對該結(jié)點的Watcherl 每個Slave在啟動成功后,創(chuàng)建唯一標(biāo)識自己的臨時性(Ephemeral)結(jié)點/service/slaves/$slave_id,并將自己地址(ip/port)等相關(guān)信息寫入該結(jié)點l Master收到有新子結(jié)點加入的通知后,做相應(yīng)的處理l 如果有Slave宕機,由于它所對應(yīng)的結(jié)點是臨時性結(jié)點,在它的Sessio

30、n超時后,ZooKeeper會自動刪除該結(jié)點l Master收到有子結(jié)點消失的通知,做相應(yīng)的處理4. 簡單互斥鎖(Simple Lock) 我們知識,在傳統(tǒng)的應(yīng)用程序中,線程、進程的同步,都可以通過操作系統(tǒng)提供的機制來完成。但是在分布式系統(tǒng)中,多個進程之間的同步,操作系統(tǒng)層面就無能為力了。這時候就需要像ZooKeeper這樣的分布式的協(xié)調(diào)(Coordination)服務(wù)來協(xié)助完成同步,下面是用ZooKeeper實現(xiàn)簡單的互斥鎖的步驟,這個可以和線程間同步的mutex做類比來理解:l 多個進程嘗試去在指定的目錄下去創(chuàng)建一個臨時性(Ephemeral)結(jié)點 /locks/my_lockl

31、 ZooKeeper能保證,只會有一個進程成功創(chuàng)建該結(jié)點,創(chuàng)建結(jié)點成功的進程就是搶到鎖的進程,假設(shè)該進程為Al 其它進程都對/locks/my_lock進行Watchl 當(dāng)A進程不再需要鎖,可以顯式刪除/locks/my_lock釋放鎖;或者是A進程宕機后Session超時,ZooKeeper系統(tǒng)自動刪除/locks/my_lock結(jié)點釋放鎖。此時,其它進程就會收到ZooKeeper的通知,并嘗試去創(chuàng)建/locks/my_lock搶鎖,如此循環(huán)反復(fù)l 5. 互斥鎖(Simple Lock without Herd Effect) 上一節(jié)的例子中有一個問題,每次搶鎖都會有大量的進程去競

32、爭,會造成羊群效應(yīng)(Herd Effect),為了解決這個問題,我們可以通過下面的步驟來改進上述過程:l 每個進程都在ZooKeeper上創(chuàng)建一個臨時的順序結(jié)點(Ephemeral Sequential) /locks/lock_$seql $seq最小的為當(dāng)前的持鎖者($seq是ZooKeeper生成的Sequenctial Number)l 其它進程都對只watch比它次小的進程對應(yīng)的結(jié)點,比如2 watch 1, 3 watch 2, 以此類推l 當(dāng)前持鎖者釋放鎖后,比它次大的進程就會收到ZooKeeper的通知,它成為新的持鎖者,如此循環(huán)反復(fù)這里需要補充一點,通常在分布式系統(tǒng)中用Zoo

33、Keeper來做Leader Election(選主)就是通過上面的機制來實現(xiàn)的,這里的持鎖者就是當(dāng)前的“主”。6. 讀寫鎖(Read/Write Lock) 我們知道,讀寫鎖跟互斥鎖相比不同的地方是,它分成了讀和寫兩種模式,多個讀可以并發(fā)執(zhí)行,但寫和讀、寫都互斥,不能同時執(zhí)行行。利用ZooKeeper,在上面的基礎(chǔ)上,稍做修改也可以實現(xiàn)傳統(tǒng)的讀寫鎖的語義,下面是基本的步驟:l 每個進程都在ZooKeeper上創(chuàng)建一個臨時的順序結(jié)點(Ephemeral Sequential) /locks/lock_$seql $seq最小的一個或多個結(jié)點為當(dāng)前的持鎖者,多個是因為多個讀可以并發(fā)l

34、需要寫鎖的進程,Watch比它次小的進程對應(yīng)的結(jié)點l 需要讀鎖的進程,Watch比它小的最后一個寫進程對應(yīng)的結(jié)點l 當(dāng)前結(jié)點釋放鎖后,所有Watch該結(jié)點的進程都會被通知到,他們成為新的持鎖者,如此循環(huán)反復(fù)7. 屏障(Barrier) 在分布式系統(tǒng)中,屏障是這樣一種語義: 客戶端需要等待多個進程完成各自的任務(wù),然后才能繼續(xù)往前進行下一步。下用是用ZooKeeper來實現(xiàn)屏障的基本步驟:l Client在ZooKeeper上創(chuàng)建屏障結(jié)點/barrier/my_barrier,并啟動執(zhí)行各個任務(wù)的進程l Client通過exist()來Watch /barrier/my_barrier結(jié)

35、點l 每個任務(wù)進程在完成任務(wù)后,去檢查是否達到指定的條件,如果沒達到就啥也不做,如果達到了就把/barrier/my_barrier結(jié)點刪除l Client收到/barrier/my_barrier被刪除的通知,屏障消失,繼續(xù)下一步任務(wù)8. 雙屏障(Double Barrier)雙屏障是這樣一種語義: 它可以用來同步一個任務(wù)的開始和結(jié)束,當(dāng)有足夠多的進程進入屏障后,才開始執(zhí)行任務(wù);當(dāng)所有的進程都執(zhí)行完各自的任務(wù)后,屏障才撤銷。下面是用ZooKeeper來實現(xiàn)雙屏障的基本步驟:進入屏障:l Client Watch /barrier/ready結(jié)點, 通過判斷該結(jié)點是否存在來決定是否啟動任務(wù)l

36、每個任務(wù)進程進入屏障時創(chuàng)建一個臨時結(jié)點/barrier/process/$process_id,然后檢查進入屏障的結(jié)點數(shù)是否達到指定的值,如果達到了指定的值,就創(chuàng)建一個/barrier/ready結(jié)點,否則繼續(xù)等待l Client收到/barrier/ready創(chuàng)建的通知,就啟動任務(wù)執(zhí)行過程l 離開屏障:l Client Watch /barrier/process,如果其沒有子結(jié)點,就可以認為任務(wù)執(zhí)行結(jié)束,可以離開屏障l 每個任務(wù)進程執(zhí)行任務(wù)結(jié)束后,都需要刪除自己對應(yīng)的結(jié)點/barrier/process/$process_id4. Zookeeper 監(jiān)視(Watches) 簡介Zooke

37、eper C API 的聲明和描述在 include/zookeeper.h 中可以找到,另外大部分的 Zookeeper C API 常量、結(jié)構(gòu)體聲明也在 zookeeper.h 中,如果如果你在使用 C API 是遇到不明白的地方,最好看看 zookeeper.h,或者自己使用 doxygen 生成 Zookeeper C API 的幫助文檔。Zookeeper 中最有特色且最不容易理解的是監(jiān)視(Watches)。Zookeeper 所有的讀操作getData(), getChildren(), 和 exists() 都 可以設(shè)置監(jiān)視(watch),監(jiān)視事件可

38、以理解為一次性的觸發(fā)器, 官方定義如下: a watch event is one-time trigger, sent to the client that set the watch, which occurs when the data for which the watch was set changes。對此需要作出如下理解:(1)(一次性觸發(fā))One-time trigger當(dāng)設(shè)置監(jiān)視的數(shù)據(jù)發(fā)生改變時,該監(jiān)視事件會被發(fā)送到客戶端,例如,如果客戶端調(diào)用了 getData("/znode1", true) 并且稍后 /znode1 節(jié)點上的數(shù)據(jù)發(fā)生了改變或者被刪除了

39、,客戶端將會獲取到 /znode1 發(fā)生變化的監(jiān)視事件,而如果 /znode1 再一次發(fā)生了變化,除非客戶端再次對 /znode1 設(shè)置監(jiān)視,否則客戶端不會收到事件通知。(2)(發(fā)送至客戶端)Sent to the clientZookeeper 客戶端和服務(wù)端是通過 socket 進行通信的,由于網(wǎng)絡(luò)存在故障,所以監(jiān)視事件很有可能不會成功地到達客戶端,監(jiān)視事件是異步發(fā)送至監(jiān)視者的,Zookeeper 本身提供了保序性(ordering guarantee):即客戶端只有首先看到了監(jiān)視事件后,才會感知到它所設(shè)置監(jiān)視的 znode 發(fā)生了變化(a client will never see a

40、change for which it has set a watch until it first sees the watch event). 網(wǎng)絡(luò)延遲或者其他因素可能導(dǎo)致不同的客戶端在不同的時刻感知某一監(jiān)視事件,但是不同的客戶端所看到的一切具有一致的順序。(3)(被設(shè)置 watch 的數(shù)據(jù))The data for which the watch was set這意味著 znode 節(jié)點本身具有不同的改變方式。你也可以想象 Zookeeper 維護了兩條監(jiān)視鏈表:數(shù)據(jù)監(jiān)視和子節(jié)點監(jiān)視(data watches and child watches) getData() and exists

41、() 設(shè)置數(shù)據(jù)監(jiān)視,getChildren() 設(shè)置子節(jié)點監(jiān)視。 或者,你也可以想象 Zookeeper 設(shè)置的不同監(jiān)視返回不同的數(shù)據(jù),getData() 和 exists() 返回 znode 節(jié)點的相關(guān)信息,而 getChildren() 返回子節(jié)點列表。因此, setData() 會觸發(fā)設(shè)置在某一節(jié)點上所設(shè)置的數(shù)據(jù)監(jiān)視(假定數(shù)據(jù)設(shè)置成功),而一次成功的 create() 操作則會出發(fā)當(dāng)前節(jié)點上所設(shè)置的數(shù)據(jù)監(jiān)視以及父節(jié)點的子節(jié)點監(jiān)視。一次成功的 delete() 操作將會觸發(fā)當(dāng)前節(jié)點的數(shù)據(jù)監(jiān)視和子節(jié)點監(jiān)視事件,同時也會觸發(fā)該節(jié)點父節(jié)點的child watch。Zookeeper 中的監(jiān)視是

42、輕量級的,因此容易設(shè)置、維護和分發(fā)。當(dāng)客戶端與 Zookeeper 服務(wù)器端失去聯(lián)系時,客戶端并不會收到監(jiān)視事件的通知,只有當(dāng)客戶端重新連接后,若在必要的情況下,以前注冊的監(jiān)視會重新被注冊并觸發(fā),對于開發(fā)人員來說 這通常是透明的。只有一種情況會導(dǎo)致監(jiān)視事件的丟失,即:通過 exists() 設(shè)置了某個 znode 節(jié)點的監(jiān)視,但是如果某個客戶端在此 znode 節(jié)點被創(chuàng)建和刪除的時間間隔內(nèi)與 zookeeper 服務(wù)器失去了聯(lián)系,該客戶端即使稍后重新連接 zookeeper服務(wù)器后也得不到事件通知。5. Zookeeper C API 常量與部分結(jié)構(gòu)(struct)介紹與 ACL 相關(guān)的結(jié)構(gòu)與

43、常量:struct Id 結(jié)構(gòu)為: struct Id     char * scheme;     char * id; struct ACL 結(jié)構(gòu)為: struct ACL    int32_t perms;     struct Id id; struct ACL_vector 結(jié)構(gòu)為: struct&

44、#160;ACL_vector   int32_t count;   struct ACL *data; 與 znode 訪問權(quán)限有關(guān)的常量:l const int ZOO_PERM_READ; /允許客戶端讀取 znode 節(jié)點的值以及子節(jié)點列表。l const int ZOO_PERM_WRITE;/ 允許客戶端設(shè)置 znode 節(jié)點的值。l const int ZOO_PERM_CREATE; /允許客戶端在該 znode 節(jié)點下創(chuàng)建子節(jié)點。l co

45、nst int ZOO_PERM_DELETE;/允許客戶端刪除子節(jié)點。l const int ZOO_PERM_ADMIN; /允許客戶端執(zhí)行 set_acl()。l const int ZOO_PERM_ALL;/允許客戶端執(zhí)行所有操作,等價與上述所有標(biāo)志的或(OR) 。與 ACL IDs 相關(guān)的常量:l struct Id ZOO_ANYONE_ID_UNSAFE; /(world,anyone)l struct Id ZOO_AUTH_IDS;/ (auth,)三種標(biāo)準(zhǔn)的 ACL:l struct 

46、;ACL_vector ZOO_OPEN_ACL_UNSAFE; /(ZOO_PERM_ALL,ZOO_ANYONE_ID_UNSAFE)l struct ACL_vector ZOO_READ_ACL_UNSAFE;/ (ZOO_PERM_READ, ZOO_ANYONE_ID_UNSAFE)l struct ACL_vector ZOO_CREATOR_ALL_ACL; /(ZOO_PERM_ALL,ZOO_AUTH_IDS)與 Interest 相關(guān)的常量:ZOOKEEPER_WRITE, ZOOKEEPER_READ這兩個常量用于標(biāo)識感興趣的事件并通知 z

47、ookeeper 發(fā)生了哪些事件。Interest 常量可以進行組合或(OR)來標(biāo)識多種興趣(multiple interests: write, read),這兩個常量一般用于 zookeeper_interest() 和 zookeeper_process()兩個函數(shù)中。與節(jié)點創(chuàng)建相關(guān)的常量:ZOO_EPHEMERAL, ZOO_SEQUENCEl zoo_create 函數(shù)標(biāo)志,ZOO_EPHEMERAL 用來標(biāo)識創(chuàng)建臨時節(jié)點l ZOO_SEQUENCE 用來標(biāo)識節(jié)點命名具有遞增的后綴序號(一般是節(jié)點名稱后填充 10 位字符的序號,如 /xyz0000000

48、000, /xyz0000000001, /xyz0000000002, .),同樣地,ZOO_EPHEMERAL, ZOO_SEQUENCE 可以組合。與連接狀態(tài) Stat 相關(guān)的常量以下常量均與 Zookeeper 連接狀態(tài)有關(guān),他們通常用作監(jiān)視器回調(diào)函數(shù)的參數(shù)。ZOOAPI const int ZOO_EXPIRED_SESSION_STATEZOOAPI const int ZOO_AUTH_FAILED_STATEZOOAPI const int ZOO_CONNECTING_STATEZOOAPI const int ZO

49、O_ASSOCIATING_STATEZOOAPI const int ZOO_CONNECTED_STATE與監(jiān)視類型(Watch Types)相關(guān)的常量以下常量標(biāo)識監(jiān)視事件的類型,他們通常用作監(jiān)視器回調(diào)函數(shù)的第一個參數(shù)。l ZOO_CREATED_EVENT; / 節(jié)點被創(chuàng)建(此前該節(jié)點不存在),通過 zoo_exists() 設(shè)置監(jiān)視。l ZOO_DELETED_EVENT; / 節(jié)點被刪除,通過 zoo_exists() 和 zoo_get() 設(shè)置監(jiān)視。l ZOO_CHANGED_EVENT; / 節(jié)點發(fā)生變化,通過 zoo_exists() 和 zoo_get() 設(shè)置監(jiān)

50、視。l ZOO_CHILD_EVENT; / 子節(jié)點事件,通過zoo_get_children() 和 zoo_get_children2()設(shè)置監(jiān)視。l ZOO_SESSION_EVENT; / 會話丟失l ZOO_NOTWATCHING_EVENT; / 監(jiān)視被移除。Zookeeper C API 錯誤碼介紹 ZOO_ERRORSZOK 正常返回ZSYSTEMERROR 系統(tǒng)或服務(wù)器端錯誤(System and server-side errors),服務(wù)器不會拋出該錯誤,該錯誤也只是用來標(biāo)識錯誤范圍的,即大于該錯誤值,且小于 ZAPIERROR 都是系統(tǒng)錯誤

51、。ZRUNTIMEINCONSISTENCY 運行時非一致性錯誤。ZDATAINCONSISTENCY 數(shù)據(jù)非一致性錯誤。ZCONNECTIONLOSS Zookeeper 客戶端與服務(wù)器端失去連接ZMARSHALLINGERROR 在 marshalling 和 unmarshalling 數(shù)據(jù)時出現(xiàn)錯誤(Error while marshalling or unmarshalling data)ZUNIMPLEMENTED 該操作未實現(xiàn)(Operation is unimplemented)ZOPER

52、ATIONTIMEOUT 該操作超時(Operation timeout)ZBADARGUMENTS 非法參數(shù)錯誤(Invalid arguments)ZINVALIDSTATE 非法句柄狀態(tài)(Invliad zhandle state)ZAPIERROR API 錯誤(API errors),服務(wù)器不會拋出該錯誤,該錯誤也只是用來標(biāo)識錯誤范圍的,錯誤值大于該值的標(biāo)識 API 錯誤,而小于該值的標(biāo)識 ZSYSTEMERROR。ZNONODE 節(jié)點不存在(Node does not exist)ZNOAUTH 沒有經(jīng)過授權(quán)(Not au

53、thenticated)ZBADVERSION 版本沖突(Version conflict)ZNOCHILDRENFOREPHEMERALS 臨時節(jié)點不能擁有子節(jié)點(Ephemeral nodes may not have children)ZNODEEXISTS 節(jié)點已經(jīng)存在(The node already exists)ZNOTEMPTY 該節(jié)點具有自身的子節(jié)點(The node has children)ZSESSIONEXPIRED 會話過期(The session has been expired by the server)ZIN

54、VALIDCALLBACK 非法的回調(diào)函數(shù)(Invalid callback specified)ZINVALIDACL 非法的ACL(Invalid ACL specified)ZAUTHFAILED 客戶端授權(quán)失敗(Client authentication failed)ZCLOSING Zookeeper 連接關(guān)閉(ZooKeeper is closing)ZNOTHING 并非錯誤,客戶端不需要處理服務(wù)器的響應(yīng)(not error, no server responses to process)ZSESSIONMOVED 會

55、話轉(zhuǎn)移至其他服務(wù)器,所以操作被忽略(session moved to another server, so operation is ignored)Watch事件類型:l ZOO_CREATED_EVENT:節(jié)點創(chuàng)建事件,需要watch一個不存在的節(jié)點,當(dāng)節(jié)點被創(chuàng)建時觸發(fā),此watch通過zoo_exists()設(shè)置l ZOO_DELETED_EVENT:節(jié)點刪除事件,此watch通過zoo_exists()或zoo_get()設(shè)置l ZOO_CHANGED_EVENT:節(jié)點數(shù)據(jù)改變事件,此watch通過zoo_exists()或zoo_get()設(shè)置ZOO_CHILD_EVENT:子節(jié)點列

56、表改變事件,此watch通過zoo_get_children()或zoo_get_children2()設(shè)置l ZOO_SESSION_EVENT:會話失效事件,客戶端與服務(wù)端斷開或重連時觸發(fā)l ZOO_NOTWATCHING_EVENT:watch移除事件,服務(wù)端出于某些原因不再為客戶端watch節(jié)點時觸發(fā)其他 HBase和ZooKeeper HBase內(nèi)置有ZooKeeper,也可以使用外部ZooKeeper。 讓HBase使用一個已有的不被HBase托管的Zookeep集群,需要設(shè)置 conf/hbase env sh文件中的HBASE_MANAGES_ZK 屬性為 false . #

57、Tell HBase whether it should manage it's own instance of Zookeeper or not. export HBASE_MANAGES_ZK=false 接下來,指明Zookeeper的host和端口??梢栽?hbase-site.xml中設(shè)置, 也可以在HBase的CLASSPATH下面加一個zoo.cfg配置文件。 HBase 會優(yōu)先加載 zoo.cfg 里面的配置,把hbase-site.xml里面的覆蓋掉. 當(dāng)HBase托管ZooKeeper的時候,Zookeeper集群的啟動是HBase啟動腳本的一部分。但你需要自己去運行。你可以這樣做 $HBASE_HOME/bin/hbase-daemons sh start,stop zookeeper 你可以用這條命令啟動ZooKeeper而不啟動HBase. HBASE_MANAGES_ZK 的值是 false, 如果你想在HBase重啟的時候不重啟ZooKee

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論