日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

Zookeeper系列(一)

發(fā)布時(shí)間:2025/3/15 编程问答 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Zookeeper系列(一) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

一、ZooKeeper的背景

1.1 認(rèn)識(shí)ZooKeeper

ZooKeeper---譯名為“動(dòng)物園管理員”。動(dòng)物園里當(dāng)然有好多的動(dòng)物,游客可以根據(jù)動(dòng)物園提供的向?qū)D到不同的場(chǎng)館觀賞各種類(lèi)型的動(dòng)物,而不是像走在原始叢林里,心驚膽顫的被動(dòng) 物所觀賞。為了讓各種不同的動(dòng)物呆在它們應(yīng)該呆的地方,而不是相互串門(mén),或是相互廝殺,就需要?jiǎng)游飯@管理員按照動(dòng)物的各種習(xí)性加以分類(lèi)和管理,這樣我們才能更加放心安全的觀賞動(dòng)物。

回到企業(yè)級(jí)應(yīng)用系統(tǒng)中,隨著信息化水平的不斷提高,企業(yè)級(jí)系統(tǒng)變得越來(lái)越龐大臃腫,性能急劇下降,客戶抱怨頻頻。拆分系統(tǒng)是目前我們可選擇的解決系統(tǒng)可伸縮性和性能問(wèn)題的唯一行之有效的方法。但是拆分系統(tǒng)同時(shí)也帶來(lái)了系統(tǒng)的復(fù)雜性——各子系統(tǒng)不是孤立存在的,它們彼此之間需要協(xié)作和交互,這就是我們常說(shuō)的分布式系統(tǒng)0。各個(gè)子系統(tǒng)就好比動(dòng)物園里的動(dòng)物,為了使各個(gè)子系統(tǒng)能正常為用戶提供統(tǒng)一的服務(wù),必須需要一種機(jī)制來(lái)進(jìn)行協(xié)調(diào)——這就是ZooKeeper(動(dòng)物園管理員)。

1.2 為什么使用ZooKeeper

我們知道要寫(xiě)一個(gè)分布式應(yīng)用是非常困難的,主要原因就是局部故障。一個(gè)消息通過(guò)網(wǎng)絡(luò)在兩個(gè)節(jié)點(diǎn)之間傳遞時(shí),網(wǎng)絡(luò)如果發(fā)生故障,發(fā)送方并不知道接收方是否接收到了這個(gè)消息。他可能在網(wǎng)絡(luò)故障遷就收到了此消息,也坑沒(méi)有收到,又或者可能接收方的進(jìn)程死了。發(fā)送方了解情況的唯一方法就是再次連接發(fā)送方,并向他進(jìn)行詢問(wèn)。這就是局部故障:根本不知道操作是否失敗。因此,大部分分布式應(yīng)用需要一個(gè)主控、協(xié)調(diào)控制器來(lái)管理物理分布的子進(jìn)程。目前,大部分應(yīng)用需要開(kāi)發(fā)私有的協(xié)調(diào)程序,缺乏一個(gè)通用的機(jī)制。協(xié)調(diào)程序的反復(fù)編寫(xiě)浪費(fèi),且難以形成通用、伸縮性好的協(xié)調(diào)器。協(xié)調(diào)服務(wù)非常容易出錯(cuò),并很難從故障中恢復(fù)。例如:協(xié)調(diào)服務(wù)很容易處于競(jìng)態(tài)1甚至死鎖2。Zookeeper的設(shè)計(jì)目的,是為了減輕分布式應(yīng)用程序所承擔(dān)的協(xié)調(diào)任務(wù)。

Zookeeper并不能阻止局部故障的發(fā)生,因?yàn)樗鼈兊谋举|(zhì)是分布式系統(tǒng)。他當(dāng)然也不會(huì)隱藏局部故障。ZooKeeper的目的就是提供一些工具集,用來(lái)建立安全處理局部故障的分布式應(yīng)用。

ZooKeeper是一個(gè)分布式小文件系統(tǒng),并且被設(shè)計(jì)為高可用性。通過(guò)選舉算法和集群復(fù)制可以避免單點(diǎn)故障3,由于是文件系統(tǒng),所以即使所有的ZooKeeper節(jié)點(diǎn)全部掛掉,數(shù)據(jù)也不會(huì)丟失,重啟服務(wù)器之后,數(shù)據(jù)即可恢復(fù)。另外ZooKeeper的節(jié)點(diǎn)更新是原子的,也就是說(shuō)更新不是成功就是失敗。通過(guò)版本號(hào),ZooKeeper實(shí)現(xiàn)了更新的樂(lè)觀鎖4,當(dāng)版本號(hào)不相符時(shí),則表示待更新的節(jié)點(diǎn)已經(jīng)被其他客戶端提前更新了,而當(dāng)前的整個(gè)更新操作將全部失敗。當(dāng)然所有的一切ZooKeeper已經(jīng)為開(kāi)發(fā)者提供了保障,我們需要做的只是調(diào)用API。與此同時(shí),隨著分布式應(yīng)用的的不斷深入,需要對(duì)集群管理逐步透明化監(jiān)控集群和作業(yè)狀態(tài),可以充分利ZK的獨(dú)有特性。

1.3 ZooKeeper的應(yīng)用 

ZooKeeper本質(zhì)上是一個(gè)分布式的小文件存儲(chǔ)系統(tǒng)。原本是Apache Hadoop的一個(gè)組件,現(xiàn)在被拆分為一個(gè)Hadoop的獨(dú)立子項(xiàng)目,在HBase(Hadoop的另外一個(gè)被拆分出來(lái)的子項(xiàng)目,用于分布式環(huán)境下的超大數(shù)據(jù)量的DBMS)中也用到了ZooKeeper集群。 

Hadoop,使用Zookeeper的事件處理確保整個(gè)集群只有一個(gè)NameNode,存儲(chǔ)配置信息等.
  HBase,使用Zookeeper的事件處理確保整個(gè)集群只有一個(gè)HMaster,察覺(jué)HRegionServer聯(lián)機(jī)和宕(dàng)機(jī),存儲(chǔ)訪問(wèn)控制列表等。

有人會(huì)懷疑ZooKeeper的執(zhí)行能力,在ZooKeeper誕生的地方——Yahoo!他被用作雅虎消息代理的協(xié)調(diào)和故障恢復(fù)服務(wù)。雅虎消息代理是一個(gè)高度可擴(kuò)展的發(fā)布-訂閱系統(tǒng),他管理著成千上萬(wàn)臺(tái)聯(lián)及程序和信息控制系統(tǒng)。它的吞吐量標(biāo)準(zhǔn)已經(jīng)達(dá)到大約每秒10000基于寫(xiě)操作的工作量。對(duì)于讀操作的工作量來(lái)說(shuō),它的吞吐量標(biāo)準(zhǔn)還要高幾倍。

二、ZooKeeper的介紹

2.1 ZooKeeper的概述

Zookeeper 是為分布式應(yīng)用程序提供高性能協(xié)調(diào)服務(wù)的工具集合,也是Google的Chubby一個(gè)開(kāi)源的實(shí)現(xiàn),是Hadoop 的分布式協(xié)調(diào)服務(wù)。它包含一個(gè)簡(jiǎn)單的原語(yǔ)集5,分布式應(yīng)用程序可以基于它實(shí)現(xiàn)配置維護(hù)、命名服務(wù)、分布式同步、組服務(wù)等。Zookeeper可以用來(lái)保證數(shù)據(jù)在ZK集群之間的數(shù)據(jù)的事務(wù)性一致6。其中ZooKeeper提供通用的分布式鎖服務(wù)7,用以協(xié)調(diào)分布式應(yīng)用。

Zookeeper作為Hadoop項(xiàng)目中的一個(gè)子項(xiàng)目,是 Hadoop集群管理的一個(gè)必不可少的模塊,它主要用來(lái)解決分布式應(yīng)用中經(jīng)常遇到的數(shù)據(jù)管理問(wèn)題,如集群管理、統(tǒng)一命名服務(wù)、分布式配置管理、分布式消息隊(duì)列、分布式鎖、分布式協(xié)調(diào)等。在Hadoop中,它管理Hadoop集群中的NameNode,還有在Hbase中Master Election、Server 之間狀態(tài)同狀步等。
  Zoopkeeper 提供了一套很好的分布式集群管理的機(jī)制,就是它這種基于層次型的目錄樹(shù)的數(shù)據(jù)結(jié)構(gòu),并對(duì)樹(shù)中的節(jié)點(diǎn)進(jìn)行有效管理,從而可以設(shè)計(jì)出多種多樣的分布式的數(shù)據(jù)管理模型。

2.2 ZooKeeper的設(shè)計(jì)目標(biāo)

眾所周知,分布式環(huán)境下的程序和活動(dòng)為了達(dá)到協(xié)調(diào)一致目的,通常具有某些共同的特點(diǎn),例如,簡(jiǎn)單性、有序性等。ZooKeeper不但在這些目標(biāo)的實(shí)現(xiàn)上有自身特點(diǎn),并且具有獨(dú)特優(yōu)勢(shì)。下面我們將簡(jiǎn)述ZooKeeper的設(shè)計(jì)目標(biāo)。

(1)簡(jiǎn)單化

ZooKeeper允許各分布式進(jìn)程通過(guò)一個(gè)共享的命名空間相互聯(lián)系,該命名空間類(lèi)似于一個(gè)標(biāo)準(zhǔn)的層次型的文件系統(tǒng):由若干注冊(cè)了的數(shù)據(jù)節(jié)點(diǎn)構(gòu)成(用Zookeeper的術(shù)語(yǔ)叫znode),這些節(jié)點(diǎn)類(lèi)似于文件和目錄。典型的文件系統(tǒng)是基于存儲(chǔ)設(shè)備的,文傳統(tǒng)的文件系統(tǒng)主要用于存儲(chǔ)功能,然而ZooKepper的數(shù)據(jù)是保存在內(nèi)存中的。也就是說(shuō),可以獲得高吞吐和低延遲。ZooKeeper的實(shí)現(xiàn)非常重視高性能、高可靠,以及嚴(yán)格的有序訪問(wèn)。

高性能保證了ZooKeeper可以用于大型的分布式系統(tǒng),高可靠保證了ZooKeeper不會(huì)發(fā)生單點(diǎn)故障,嚴(yán)格的順序訪問(wèn)保證了客戶端可以獲得復(fù)雜的同步操作原語(yǔ)。

(2)健壯性

就像ZooKeeper需要協(xié)調(diào)的分布式系統(tǒng)一樣,它本身就是具有冗余結(jié)構(gòu),它構(gòu)建在一系列主機(jī)之上,叫做一個(gè)”ensemble”。
  構(gòu)成ZooKeeper服務(wù)的各服務(wù)器之間必須相互知道,它們維護(hù)著一個(gè)狀態(tài)信息的內(nèi)存映像8,以及在持久化存儲(chǔ)中維護(hù)著事務(wù)日志和快照9。只要大部分服務(wù)器正常工作,ZooKeeper服務(wù)就能正常工作。
  客戶端連接到一臺(tái)ZooKeeper服務(wù)器。客戶端維護(hù)這個(gè)TCP連接,通過(guò)這個(gè)連接,客戶端可以發(fā)送請(qǐng)求、得到應(yīng)答,得到監(jiān)視事件以及發(fā)送心跳。如果這個(gè)連接斷了,客戶端可以連接到另一個(gè)ZooKeeper服務(wù)器。

(3)有序性

ZooKeeper給每次更新附加一個(gè)數(shù)字標(biāo)簽,表明ZooKeeper中的事務(wù)順序,后續(xù)操作可以利用這個(gè)順序來(lái)完成更高層次的抽象功能,例如同步原語(yǔ)7。

(4)速度優(yōu)勢(shì)

ZooKeeper特別適合于以讀為主要負(fù)荷的場(chǎng)合。ZooKeeper可以運(yùn)行在數(shù)千臺(tái)機(jī)器上,如果大部分操作為讀,例如讀寫(xiě)比例為10:1,ZooKeeper的效率會(huì)很高。

2.3 ZooKeeper的集群

ZK集群如下圖2.1所示。這是實(shí)際應(yīng)用的一個(gè)場(chǎng)景,該ZooKeeper集群當(dāng)中一共有5臺(tái)服務(wù)器,有兩種角色Leader和Follwer,5臺(tái)服務(wù)器連通在一起,客戶端有分別連在不同的ZK服務(wù)器上。如果當(dāng)數(shù)據(jù)通過(guò)客戶端1,在左邊第一臺(tái)Follower服務(wù)器上做了一次數(shù)據(jù)變更,他會(huì)把這個(gè)數(shù)據(jù)的變化同步到其他所有的服務(wù)器,同步結(jié)束之后,那么其他的客戶端都會(huì)獲得這個(gè)數(shù)據(jù)的變化。

圖 2.1

注意:

通常Zookeeper由2n+1臺(tái)servers組成,每個(gè)server都知道彼此的存在。每個(gè)server都維護(hù)的內(nèi)存狀態(tài)鏡像以及持久化存儲(chǔ)的事務(wù)日志和快照。為了保證Leader選舉能過(guò)得到多數(shù)的支持,所以ZooKeeper集群的數(shù)量一般為奇數(shù)。對(duì)于2n+1臺(tái)server,只要有n+1臺(tái)(大多數(shù))server可用,整個(gè)系統(tǒng)保持可用。

2.3.1 集群中的角色

在ZooKeeper集群當(dāng)中,集群中的服務(wù)器角色有兩種Leader和Learner,Learner角色又分為Observer和Follower,具體功能如下:

1.領(lǐng)導(dǎo)者(leader),負(fù)責(zé)進(jìn)行投票的發(fā)起和決議,更新系統(tǒng)狀態(tài)

2.學(xué)習(xí)者(learner),包括跟隨者(follower)和觀察者(observer),

3.follower用于接受客戶端請(qǐng)求并向客戶端返回結(jié)果,在選主過(guò)程中參與投票

4.Observer可以接受客戶端請(qǐng)求,將寫(xiě)請(qǐng)求轉(zhuǎn)發(fā)給leader,但observer不參加投票過(guò)程,只同步leader的狀態(tài),observer的目的是為了擴(kuò)展系統(tǒng),提高讀取速度。

5. 客戶端(client),請(qǐng)求發(fā)起方

ZooKeeper的組件圖中給出了ZooKeeper服務(wù)的高層次的組件。除了請(qǐng)求處理器(requestprocessor)外,構(gòu)成ZooKeeper服務(wù)的每個(gè)服務(wù)器都有一個(gè)備份。復(fù)制的數(shù)據(jù)庫(kù)(replicateddatabase)是一個(gè)內(nèi)存數(shù)據(jù)庫(kù),包含整個(gè)數(shù)據(jù)樹(shù)。為了可恢復(fù),更新會(huì)被log到磁盤(pán),并且在更新這個(gè)內(nèi)存數(shù)據(jù)庫(kù)之前,先序列化到磁盤(pán)。

每個(gè)ZooKeeper都為客戶端提供服務(wù)。客戶端只連接到一個(gè)服務(wù)器,并提交請(qǐng)求。讀請(qǐng)求直接由本地的復(fù)制數(shù)據(jù)庫(kù)提供數(shù)據(jù)。對(duì)服務(wù)狀態(tài)進(jìn)行修改的請(qǐng)求、寫(xiě)請(qǐng)求通過(guò)一個(gè)約定的協(xié)議進(jìn)行通訊。

作為這個(gè)協(xié)議的一部分,所有的寫(xiě)請(qǐng)求都被傳送到一個(gè)叫“首領(lǐng)(leader)”的服務(wù)器,而其他的服務(wù)器,叫做“(隨從)followers”,follower從leader接收信息修改的提議,并同意進(jìn)行。當(dāng)leader發(fā)生故障時(shí),協(xié)議的信息層(messaginglayer)關(guān)注leader的替換,并同步到所有的follower。

ZooKeeper采用一個(gè)自定義的信息原子操作協(xié)議,由于信息層的操作是原子性的,ZooKeeper能保證本地的復(fù)制數(shù)據(jù)庫(kù)不會(huì)產(chǎn)生不一致。當(dāng)leader接收到一個(gè)寫(xiě)請(qǐng)求,它計(jì)算出寫(xiě)之后系統(tǒng)的狀態(tài),把它變成一個(gè)事務(wù)。

2.3.2 Zookeeper的讀寫(xiě)機(jī)制和保證及特點(diǎn)

(1)ZooKeeper的讀寫(xiě)機(jī)制

Zookeeper是一個(gè)由多個(gè)server組成的集群

一個(gè)leader,多個(gè)follower

每個(gè)server保存一份數(shù)據(jù)副本

全局?jǐn)?shù)據(jù)一致

分布式讀寫(xiě)

更新請(qǐng)求轉(zhuǎn)發(fā),由leader實(shí)施

(2)ZooKeeper的保證

ZooKeeper運(yùn)行非常快而且簡(jiǎn)單。雖然它的目標(biāo)是構(gòu)建更加復(fù)雜服務(wù)(例如同步)的基礎(chǔ),但它提供了一些保證,如下:

1.順序一致性:來(lái)自于客戶端的更新,根據(jù)發(fā)送的先后被順序?qū)嵤?/p>

2.唯一的系統(tǒng)映像:盡管客戶端連接到不同的服務(wù)器,但它們看到的一個(gè)唯一(一致性)的系統(tǒng)服務(wù),client無(wú)論連接到哪個(gè)server,數(shù)據(jù)視圖都是一致的。

3.可靠性:一旦實(shí)施了一個(gè)更新,就會(huì)一直保持那種狀態(tài),直到客戶端再次更新它,同時(shí)數(shù)據(jù)更新原子性,一次數(shù)據(jù)更新要么成功,要么失敗。

4.及時(shí)性:在一個(gè)確定的時(shí)間內(nèi),客戶端看到的系統(tǒng)狀態(tài)是最新的。

(3)ZooKeeper特點(diǎn)

最終一致性:client不論連接到哪個(gè)Server,展示給它都是同一個(gè)視圖,這是zookeeper最重要的性能。

可靠性:具有簡(jiǎn)單、健壯、良好的性能,如果消息m被一臺(tái)服務(wù)器接受,那么它將被所有的服務(wù)器接受。

實(shí)時(shí)性:Zookeeper保證客戶端將在一個(gè)時(shí)間間隔范圍內(nèi)獲得服務(wù)器的更新信息,或者服務(wù)器失效的信息。 但由于網(wǎng)絡(luò)延時(shí)等原因,Zookeeper不能保證兩個(gè)客戶端能同時(shí)得到剛更新的數(shù)據(jù),如果需要最新數(shù)據(jù),應(yīng)該在讀數(shù)據(jù)之前調(diào)用sync()接口。

等待無(wú)關(guān)(wait-free):慢的或者失效的client,不得干預(yù)快速的client的請(qǐng)求,使得每個(gè)client都能有效的等待。

原子性:更新只能成功或者失敗,沒(méi)有中間狀態(tài)。

順序性:包括全局有序和偏序兩種:

全局有序:是指如果在一臺(tái)服務(wù)器上消息a在消息b前發(fā)布,則在所有Server上消息a都將在消息b前被發(fā)布;

偏序:是指如果一個(gè)消息b在消息a后被同一個(gè)發(fā)送者發(fā)布,a必將排在b前面

三、ZooKeeper服務(wù)

3.1 ZooKeeper數(shù)據(jù)模型

ZooKeeper擁有一個(gè)層次的命名空間,這個(gè)和分布式的文件系統(tǒng)非常相似。不同的是ZooKeeper命名空間中的Znode,兼具文件和目錄兩種特點(diǎn)。既像文件一樣維護(hù)著數(shù)據(jù)、元信息、ACL、時(shí)間戳等數(shù)據(jù)結(jié)構(gòu),又像目錄一樣可以作為路徑標(biāo)識(shí)的一部分,并可以具有子znode。用戶對(duì)znode具有增、刪、改、查等操作(權(quán)限允許的情況下)。

znode具有原子性操作,每個(gè)znode的數(shù)據(jù)將被原子性地讀寫(xiě),讀操作會(huì)讀取與znode相關(guān)的所有數(shù)據(jù),寫(xiě)操作會(huì)一次性替換所有數(shù)據(jù)。zookeeper并沒(méi)有被設(shè)計(jì)為常規(guī)的數(shù)據(jù)庫(kù)或者大數(shù)據(jù)存儲(chǔ),相反的是,它用來(lái)管理調(diào)度數(shù)據(jù),比如分布式應(yīng)用中的配置文件信息、狀態(tài)信息、匯集位置等等。這些數(shù)據(jù)的共同特性就是它們都是很小的數(shù)據(jù),通常以KB為大小單位。zooKeeper的服務(wù)器和客戶端都被設(shè)計(jì)為嚴(yán)格檢查并限制每個(gè)znode的數(shù)據(jù)大小至多1M,當(dāng)時(shí)常規(guī)使用中應(yīng)該遠(yuǎn)小于此值。

Zonde由路徑標(biāo)注,ZooKeeper中被表示成有反斜杠分割的Unicode字符串,如同Unix中的文件路徑。路徑必須是絕對(duì)的,因此他們必須由反斜杠來(lái)字符開(kāi)頭。除此以外,他們必須是唯一的,也就是說(shuō)每一個(gè)路徑只有一個(gè)表示,因此這些路徑不能改變。ZooKeeper的數(shù)據(jù)結(jié)構(gòu), 與普通的文件系統(tǒng)極為類(lèi)似. 見(jiàn)下圖:

圖中的每個(gè)節(jié)點(diǎn)稱(chēng)為一個(gè)znode. 每個(gè)znode由3部分組成:

1.stat:此為狀態(tài)信息, 描述該znode的版本, 權(quán)限等信息.

2.data:與該znode關(guān)聯(lián)的數(shù)據(jù).

3.children:該znode下的子節(jié)點(diǎn).

3.1.1 ZooKeeper節(jié)點(diǎn)Znode

ZooKeeper目錄樹(shù)中每一個(gè)節(jié)點(diǎn)對(duì)應(yīng)一個(gè)Znode。每個(gè)Znode維護(hù)著一個(gè)屬性結(jié)構(gòu),它包含著版本號(hào)(dataVersion),時(shí)間戳(ctime,mtime)等狀態(tài)信息。ZooKeeper正是使用節(jié)點(diǎn)的這些特性來(lái)實(shí)現(xiàn)它的某些特定功能。每當(dāng)Znode的數(shù)據(jù)改變時(shí),他相應(yīng)的版本號(hào)將會(huì)增加。每當(dāng)客戶端檢索數(shù)據(jù)時(shí),它將同時(shí)檢索數(shù)據(jù)的版本號(hào)。并且如果一個(gè)客戶端執(zhí)行了某個(gè)節(jié)點(diǎn)的更新或刪除操作,他也必須提供要被操作的數(shù)據(jù)版本號(hào)。如果所提供的數(shù)據(jù)版本號(hào)與實(shí)際不匹配,那么這個(gè)操作將會(huì)失敗。

Znode是客戶端訪問(wèn)ZooKeeper的主要實(shí)體,它包含以下幾個(gè)特征:

(1)Watches

客戶端可以在節(jié)點(diǎn)上設(shè)置watch(我們稱(chēng)之為監(jiān)視器)。當(dāng)節(jié)點(diǎn)狀態(tài)發(fā)生改變時(shí)(數(shù)據(jù)的增、刪、改)將會(huì)觸發(fā)watch所對(duì)應(yīng)的操作。當(dāng)watch被觸發(fā)時(shí),ZooKeeper將會(huì)向客戶端發(fā)送且僅發(fā)送一條通知,因?yàn)閣atch只能被觸發(fā)一次。

(2)數(shù)據(jù)訪問(wèn)

ZooKeeper中的每個(gè)節(jié)點(diǎn)存儲(chǔ)的數(shù)據(jù)要被原子性的操作。也就是說(shuō)讀操作將獲取與節(jié)點(diǎn)相關(guān)的所有數(shù)據(jù),寫(xiě)操作也將替換掉節(jié)點(diǎn)的所有數(shù)據(jù)。另外,每一個(gè)節(jié)點(diǎn)都擁有自己的ACL(訪問(wèn)控制列表),這個(gè)列表規(guī)定了用戶的權(quán)限,即限定了特定用戶對(duì)目標(biāo)節(jié)點(diǎn)可以執(zhí)行的操作。

(3)節(jié)點(diǎn)類(lèi)型

ZooKeeper中的節(jié)點(diǎn)有兩種,分別為臨時(shí)節(jié)點(diǎn)和永久節(jié)點(diǎn)。節(jié)點(diǎn)的類(lèi)型在創(chuàng)建時(shí)即被確定,并且不能改變。
  ZooKeeper的臨時(shí)節(jié)點(diǎn):該節(jié)點(diǎn)的生命周期依賴(lài)于創(chuàng)建它們的會(huì)話。一旦會(huì)話結(jié)束,臨時(shí)節(jié)點(diǎn)將被自動(dòng)刪除,當(dāng)然可以也可以手動(dòng)刪除。另外,需要注意是,ZooKeeper的臨時(shí)節(jié)點(diǎn)不允許擁有子節(jié)點(diǎn)。
  ZooKeeper的永久節(jié)點(diǎn):該節(jié)點(diǎn)的生命周期不依賴(lài)于會(huì)話,并且只有在客戶端顯示執(zhí)行刪除操作的時(shí)候,他們才能被刪除。

(4)順序節(jié)點(diǎn)(唯一性的保證)

當(dāng)創(chuàng)建Znode的時(shí)候,用戶可以請(qǐng)求在ZooKeeper的路徑結(jié)尾添加一個(gè)遞增的計(jì)數(shù)。這個(gè)計(jì)數(shù)對(duì)于此節(jié)點(diǎn)的父節(jié)點(diǎn)來(lái)說(shuō)是唯一的,它的格式為“%10d”(10位數(shù)字,沒(méi)有數(shù)值的數(shù)位用0補(bǔ)充,例如“0000000001”)。當(dāng)計(jì)數(shù)值大于232-1時(shí),計(jì)數(shù)器將溢出。

org.apache.zookeeper.CreateMode中定義了四種節(jié)點(diǎn)類(lèi)型,分別對(duì)應(yīng):

PERSISTENT:永久節(jié)點(diǎn)

EPHEMERAL:臨時(shí)節(jié)點(diǎn)

PERSISTENT_SEQUENTIAL:永久節(jié)點(diǎn)、序列化

EPHEMERAL_SEQUENTIAL:臨時(shí)節(jié)點(diǎn)、序列化

3.1.2 ZooKeeper中的時(shí)間

ZooKeeper有多種記錄時(shí)間的形式,其中包含以下幾個(gè)主要屬性:

(1)Zxid

致使ZooKeeper節(jié)點(diǎn)狀態(tài)改變的每一個(gè)操作都將使節(jié)點(diǎn)接收到一個(gè)zxid格式的時(shí)間戳,并且這個(gè)時(shí)間戳全局有序。也就是說(shuō),也就是說(shuō),每個(gè)對(duì)節(jié)點(diǎn)的改變都將產(chǎn)生一個(gè)唯一的zxid。如果zxid1的值小于zxid2的值,那么zxid1所對(duì)應(yīng)的事件發(fā)生在zxid2所對(duì)應(yīng)的事件之前。實(shí)際上,ZooKeeper的每個(gè)節(jié)點(diǎn)維護(hù)者三個(gè)zxid值,為別為:cZxid、mZxid、pZxid。

cZxid: 是節(jié)點(diǎn)的創(chuàng)建時(shí)間所對(duì)應(yīng)的Zxid格式時(shí)間戳。

mZxid:是節(jié)點(diǎn)的修改時(shí)間所對(duì)應(yīng)的Zxid格式時(shí)間戳。

實(shí)現(xiàn)中zxid是一個(gè)64為的數(shù)字,它高32位是epoch用來(lái)標(biāo)識(shí)leader關(guān)系是否改變,每次一個(gè)leader被選出來(lái),它都會(huì)有一個(gè) 新的epoch。低32位是個(gè)遞增計(jì)數(shù)。

(2)版本號(hào)

對(duì)節(jié)點(diǎn)的每一個(gè)操作都將致使這個(gè)節(jié)點(diǎn)的版本號(hào)增加。每個(gè)節(jié)點(diǎn)維護(hù)著三個(gè)版本號(hào),他們分別為:

version 節(jié)點(diǎn)數(shù)據(jù)版本號(hào)

cversion 子節(jié)點(diǎn)版本號(hào)

aversion 節(jié)點(diǎn)所擁有的ACL版本號(hào)

3.1.3 節(jié)點(diǎn)的屬性結(jié)構(gòu)

通過(guò)前面的介紹,我們可以了解到,一個(gè)節(jié)點(diǎn)自身?yè)碛斜硎酒錉顟B(tài)的許多重要屬性,如下圖所示。

3.1.4 Zonde總結(jié)

(1)znode中的數(shù)據(jù)可以有多個(gè)版本,在查詢?cè)搝node數(shù)據(jù)時(shí)就需要帶上版本信息。如:set path version / delete path version

(2)znode可以是臨時(shí)znode,由create -e 生成的節(jié)點(diǎn),一旦創(chuàng)建這個(gè)znode的client與server斷開(kāi)連接,該znode將被自動(dòng)刪除。

client和server之間通過(guò)heartbeat來(lái)確認(rèn)連接正常,這種狀態(tài)稱(chēng)之為session,斷開(kāi)連接后session失效。

(3)臨時(shí)znode不能有子znode。

(4)znode可以自動(dòng)編號(hào),由create -s 生成的節(jié)點(diǎn),例如在 create -s /app/node 已存在時(shí),將會(huì)生成 /app/node00***001節(jié)點(diǎn)。

(5)znode可以被監(jiān)控,該目錄下某些信息的修改,例如節(jié)點(diǎn)數(shù)據(jù)、子節(jié)點(diǎn)變化等,可以主動(dòng)通知監(jiān)控注冊(cè)的client。事實(shí)上,通過(guò)這個(gè)特性,可以完成許多重要應(yīng)用,例如配置管理、信息同步、分布式鎖等等。

3.2 ZooKeeper服務(wù)中的操作

在ZooKeeper中有9個(gè)基本操作,如下圖所示:

更新ZooKeeper操作是有限制的。delete或setData必須明確要更新的Znode的版本號(hào),我們可以調(diào)用exists找到。如果版本號(hào)不匹配,更新將會(huì)失敗。

更新ZooKeeper操作是非阻塞式的。因此客戶端如果失去了一個(gè)更新(由于另一個(gè)進(jìn)程在同時(shí)更新這個(gè)Znode),他可以在不阻塞其他進(jìn)程執(zhí)行的情況下,選擇重新嘗試或進(jìn)行其他操作。

盡管ZooKeeper可以被看做是一個(gè)文件系統(tǒng),但是處于便利,摒棄了一些文件系統(tǒng)地操作原語(yǔ)。因?yàn)槲募浅5男〔⑶沂拐w讀寫(xiě)的,所以不需要打開(kāi)、關(guān)閉或是尋地的操作。

3.2.1 watch觸發(fā)器

讀操作exists、getChildren和getData都被設(shè)置了watch,并且這些watch都由寫(xiě)操作來(lái)觸發(fā):create、delete和setData。ACL操作并不參與到watch中。當(dāng)watch被觸發(fā)時(shí),watch事件被生成,他的類(lèi)型由watch和觸發(fā)他的操作共同決定。ZooKeeper所管理的watch可以分為兩類(lèi):

1.數(shù)據(jù)watch(data watches):getData和exists負(fù)責(zé)設(shè)置數(shù)據(jù)watch;

2.孩子watch(child watches):getChildren負(fù)責(zé)設(shè)置孩子watch;

我們可以通過(guò)操作返回的數(shù)據(jù)來(lái)設(shè)置不同的watch:

1.getData和exists:返回關(guān)于節(jié)點(diǎn)的數(shù)據(jù)信息

2.getChildren:返回孩子列表

因此,一個(gè)成功的setData操作將觸發(fā)Znode的數(shù)據(jù)watch。

一個(gè)成功的create操作將觸發(fā)Znode的數(shù)據(jù)watch以及孩子watch。

一個(gè)成功的delete操作將觸發(fā)Znode的數(shù)據(jù)watch以及孩子watch。

watch由客戶端所連接的ZooKeeper服務(wù)器在本地維護(hù),因此watch可以非常容易地設(shè)置、管理和分派。當(dāng)客戶端連接到一個(gè)新的服務(wù)器上時(shí),任何的會(huì)話事件都將可能觸發(fā)watch。另外,當(dāng)從服務(wù)器斷開(kāi)連接的時(shí)候,watch將不會(huì)被接收。但是,當(dāng)一個(gè)客戶端重新建立連接的時(shí)候,任何先前注冊(cè)過(guò)的watch都會(huì)被重新注冊(cè)。

exists操作上的watch,在被監(jiān)視的Znode創(chuàng)建、刪除或數(shù)據(jù)更新時(shí)被觸發(fā)。

getData操作上的watch,在被監(jiān)視的Znode刪除或數(shù)據(jù)更新時(shí)被觸發(fā)。在被創(chuàng)建時(shí)不能被觸發(fā),因?yàn)橹挥衂node一定存在,getData操作才會(huì)成功。

getChildren操作上的watch,在被監(jiān)視的Znode的子節(jié)點(diǎn)創(chuàng)建或刪除,或是這個(gè)Znode自身被刪除時(shí)被觸發(fā)。可以通過(guò)查看watch事件類(lèi)型來(lái)區(qū)分是Znode還是他的子節(jié)點(diǎn)被刪除:NodeDelete表示Znode被刪除,NodeDeletedChanged表示子節(jié)點(diǎn)被刪除。

watch設(shè)置操作及相應(yīng)的觸發(fā)器如圖下圖所示:

watch事件包括了事件所涉及的Znode的路徑,因此對(duì)于NodeCreated和NodeDeleted事件來(lái)說(shuō),根據(jù)路徑就可以簡(jiǎn)單區(qū)分出是哪個(gè)Znode被創(chuàng)建或是被刪除了。為了查詢?cè)贜odeChildrenChanged事件后哪個(gè)子節(jié)點(diǎn)被改變了,需要再次調(diào)用getChildren來(lái)獲得新的children列表。同樣的,為了查詢NodeDeletedChanged事件后產(chǎn)生的新數(shù)據(jù),需要調(diào)用getData。在兩種情況下,Znode可能在獲取watch事件或執(zhí)行讀操作這兩種狀態(tài)下切換,在寫(xiě)應(yīng)用程序時(shí),必須記住這一點(diǎn)。

(1)Zookeeper的watch實(shí)際上要處理兩類(lèi)事件:

1. 連接狀態(tài)事件(type=None, path=null)

這類(lèi)事件不需要注冊(cè),也不需要我們連續(xù)觸發(fā),我們只要處理就行了。

2. 節(jié)點(diǎn)事件

節(jié)點(diǎn)的建立,刪除,數(shù)據(jù)的修改。它是one time trigger,我們需要不停的注冊(cè)觸發(fā),還可能發(fā)生事件丟失的情況。

上面2類(lèi)事件都在Watch中處理,也就是重載的process(Event event)

(2)節(jié)點(diǎn)事件的觸發(fā),通過(guò)函數(shù)exists,getData或getChildren來(lái)處理

這類(lèi)函數(shù),有雙重作用:

1. 注冊(cè)觸發(fā)事件

2. 函數(shù)本身的功能

函數(shù)的本身的功能又可以用異步的回調(diào)函數(shù)來(lái)實(shí)現(xiàn),重載processResult()過(guò)程中處理函數(shù)本身的的功能。

函數(shù)還可以指定自己的watch,所以每個(gè)函數(shù)都有4個(gè)版本。根據(jù)自己的需要來(lái)選擇不同的函數(shù),不同的版本。

3.3 ZooKeeper訪問(wèn)控制列表ACL

ZooKeeper使用ACL來(lái)對(duì)Znode進(jìn)行訪問(wèn)控制。ACL的實(shí)現(xiàn)和Unix文件訪問(wèn)許可非常相似:它使用許可位來(lái)對(duì)一個(gè)節(jié)點(diǎn)的不同操作進(jìn)行允許或禁止的權(quán)限控制。但是,和標(biāo)準(zhǔn)的Unix許可不同的是,Zookeeper對(duì)于用戶類(lèi)別的區(qū)分,不止局限于所有者(owner)、組 (group)、所有人(world)三個(gè)級(jí)別。Zookeeper中,數(shù)據(jù)節(jié)點(diǎn)沒(méi)有“所有者”的概念。訪問(wèn)者利用id標(biāo)識(shí)自己的身份,并獲得與之相應(yīng)的 不同的訪問(wèn)權(quán)限。

注意:

傳統(tǒng)的文件系統(tǒng)中,ACL分為兩個(gè)維度,一個(gè)是屬組,一個(gè)是權(quán)限,子目錄/文件默認(rèn)繼承父目錄的ACL。而在Zookeeper中一個(gè)ACL和一個(gè)ZooKeeper節(jié)點(diǎn)相對(duì)應(yīng)。并且,父節(jié)點(diǎn)的ACL與子節(jié)點(diǎn)的ACL是相互獨(dú)立的。也就是說(shuō),ACL不能被子節(jié)點(diǎn)所繼承,父節(jié)點(diǎn)所擁有的權(quán)限與子節(jié)點(diǎn)所用的權(quán)限都沒(méi)有任何關(guān)系。

Zookeeper支持可配置的認(rèn)證機(jī)制。它利用一個(gè)三元組來(lái)定義客戶端的訪問(wèn)權(quán)限:(scheme:expression, perms) 。其中:

1.scheme:定義了expression的含義。

如:(host:host1.corp.com,READ),標(biāo)識(shí)了一個(gè)名為host1.corp.com的主機(jī),有該數(shù)據(jù)節(jié)點(diǎn)的讀權(quán)限。

2.Perms:標(biāo)識(shí)了操作權(quán)限。

如:(ip:19.22.0.0/16, READ),表示IP地址以19.22開(kāi)頭的主機(jī),有該數(shù)據(jù)節(jié)點(diǎn)的讀權(quán)限。

Zookeeper的ACL也可以從三個(gè)維度來(lái)理解:一是,scheme; 二是,user; 三是,permission,通常表示為scheme:id:permissions,如下圖所示。

1.world : id格式:anyone。

如:world:anyone代表任何人,zookeeper中對(duì)所有人有權(quán)限的結(jié)點(diǎn)就是屬于world:anyone的。

2.auth : 它不需要id。

注:只要是通過(guò)authentication的user都有權(quán)限,zookeeper支持通過(guò)kerberos來(lái)進(jìn)行認(rèn)證, 也支持username/password形式的認(rèn)證。

3.digest: id格式:username:BASE64(SHA1(password))。

它需要先通過(guò)username:password形式的authentication。

4.ip: id格式:客戶機(jī)的IP地址。

設(shè)置的時(shí)候可以設(shè)置一個(gè)ip段。如:ip:192.168.1.0/16, 表示匹配前16個(gè)bit的IP段

5.super: 超級(jí)用戶模式。

在這種scheme情況下,對(duì)應(yīng)的id擁有超級(jí)權(quán)限,可以做任何事情

ZooKeeper權(quán)限定義如下圖所示:

ZooKeeper內(nèi)置的ACL模式如下圖所示:

當(dāng)會(huì)話建立的時(shí)候,客戶端將會(huì)進(jìn)行自我驗(yàn)證。另外,ZooKeeper Java API支持三種標(biāo)準(zhǔn)的用戶權(quán)限,它們分別為:

1.ZOO_PEN_ACL_UNSAFE:對(duì)于所有的ACL來(lái)說(shuō)都是完全開(kāi)放的,任何應(yīng)用程序可以在節(jié)點(diǎn)上執(zhí)行任何操作,比如創(chuàng)建、列出并刪除子節(jié)點(diǎn)。

2.ZOO_READ_ACL_UNSAFE:對(duì)于任意的應(yīng)用程序來(lái)說(shuō),僅僅具有讀權(quán)限。

3.ZOO_CREATOR_ALL_ACL:授予節(jié)點(diǎn)創(chuàng)建者所有權(quán)限。需要注意的是,設(shè)置此權(quán)限之前,創(chuàng)建者必須已經(jīng)通了服務(wù)器的認(rèn)證。

下面演示一個(gè)通過(guò)digest(用戶名密碼的方式)為創(chuàng)建的節(jié)點(diǎn)設(shè)置ACL的例子,代碼如下:

import org.apache.zookeeper.*; import org.apache.zookeeper.server.auth.DigestAuthenticationProvider; import org.apache.zookeeper.data.*; import java.util.*;public class NewDigest {public static void main(String[] args) throws Exception {//new一個(gè)aclList acls = new ArrayList(); //添加第一個(gè)id,采用用戶名密碼形式Id id1 = new Id("digest",DigestAuthenticationProvider.generateDigest("admin:admin"));ACL acl1 = new ACL(ZooDefs.Perms.ALL, id1);acls.add(acl1);//添加第二個(gè)id,所有用戶可讀權(quán)限Id id2 = new Id("world", "anyone");ACL acl2 = new ACL(ZooDefs.Perms.READ, id2);acls.add(acl2);// zk用admin認(rèn)證,創(chuàng)建/test ZNode。ZooKeeper zk = new ZooKeeper("host1:2181,host2:2181,host3:2181",2000, null);zk.addAuthInfo("digest", "admin:admin".getBytes());zk.create("/test", "data".getBytes(), acls, CreateMode.PERSISTENT);} }

3.4 ZooKeeper的執(zhí)行

ZooKeeper服務(wù)可以以兩種模式運(yùn)行。在單機(jī)模式下,只有一個(gè)ZooKeeper服務(wù)器,便于用來(lái)測(cè)試。但是他沒(méi)有高可用性和恢復(fù)性的保障。在工業(yè)界,ZooKeeper以復(fù)合模式10運(yùn)行在一組叫ensemble的集群上。ZooKeeper通過(guò)復(fù)制來(lái)獲得高可用性,同時(shí),只要ensemble中大部分機(jī)器運(yùn)作,就可以提供服務(wù)。在2n+1個(gè)節(jié)點(diǎn)的ensemble中,可以承受n臺(tái)機(jī)器故障。

ZooKeeper的思想非常簡(jiǎn)單:他所需要做的就是保證對(duì)Znode樹(shù)的每一次修改都復(fù)制到ensemble中的大部分機(jī)器上去。如果機(jī)器中的小部分出故障了,那么至少有一臺(tái)機(jī)器將會(huì)恢復(fù)到最新?tīng)顟B(tài),其他的則保存這副本,直到最終達(dá)到最新?tīng)顟B(tài)。Zookeeper采用Zab協(xié)議,它分為兩個(gè)階段,并且可能被無(wú)限的重復(fù)。

(1)階段1:領(lǐng)導(dǎo)者選舉

在ensemble中的機(jī)器要參與一個(gè)選擇特殊成員的進(jìn)程,這個(gè)成員叫領(lǐng)導(dǎo)者,其他機(jī)器腳跟隨者。在大部分的跟隨者與他們的領(lǐng)導(dǎo)者同步了狀態(tài)以后,這個(gè)階段才算完成。

(2)階段2:原子廣播

所有的寫(xiě)操作請(qǐng)求被傳送給領(lǐng)導(dǎo)者,并通過(guò)廣播將更新信息告訴跟隨者。當(dāng)大部分跟隨者執(zhí)行了修改之后,領(lǐng)導(dǎo)者就提交更新操作,客戶端將得到更新成功的回應(yīng)。未獲得一致性的協(xié)議被設(shè)計(jì)為原子的,因此無(wú)論修改失敗與否,他都分兩階段提交。

如果領(lǐng)導(dǎo)者出故障了,城下的機(jī)器將會(huì)再次進(jìn)行領(lǐng)導(dǎo)者選舉,并在新領(lǐng)導(dǎo)被選出前繼續(xù)執(zhí)行任務(wù)。如果在不久后老的領(lǐng)導(dǎo)者恢復(fù)了,那么它將以跟隨者的身份繼續(xù)運(yùn)行。領(lǐng)導(dǎo)者選舉非常快,由發(fā)布的結(jié)果所知,大約是200毫秒,因此在選舉是性能不會(huì)明顯減慢。
所有在ensemble中的機(jī)器在更新它們內(nèi)存中的Znode樹(shù)之前會(huì)先將更新信息寫(xiě)入磁盤(pán)。讀操作請(qǐng)求可由任何機(jī)器服務(wù),同時(shí),由于他們只涉及內(nèi)存查找,因此非常快。

3.5 ZooKeeper一致性

在ensemble中的領(lǐng)導(dǎo)者和跟隨著非常靈活,跟隨者通過(guò)更新號(hào)來(lái)滯后領(lǐng)導(dǎo)者11,結(jié)果導(dǎo)致了只要大部分而不是所有的ensemble中的元素確認(rèn)更新,就能被提交了。對(duì)于ZooKeeper來(lái)說(shuō),一個(gè)較好的智能模式是將客戶端連接到跟著領(lǐng)導(dǎo)者的ZooKeeper服務(wù)器上。客戶端可能被連接到領(lǐng)導(dǎo)者上,但他不能控制它,而且在如下情況時(shí),甚至可能不知道。參見(jiàn)下圖:

每一個(gè)Znode樹(shù)的更新都會(huì)給定一個(gè)唯一的全局標(biāo)識(shí),叫zxid(表示ZooKeeper事務(wù)“ID”)。更新是被排序的,因此如果zxid的z1<z2,那么z1就比z2先執(zhí)行。對(duì)于ZooKeeper來(lái)說(shuō),這是分布式系統(tǒng)中排序的唯一標(biāo)準(zhǔn)。

ZooKeeper是一種高性能、可擴(kuò)展的服務(wù)。ZooKeeper的讀寫(xiě)速度非常快,并且讀的速度要比寫(xiě)快。另外,在進(jìn)行讀操作的時(shí)候,ZooKeeper依然能夠?yàn)榕f的數(shù)據(jù)提供服務(wù)。這些都是由ZooKeeper所提供的一致性保證的,它具有如下特點(diǎn):

(1)順序一致性

任何一個(gè)客戶端的更新都按他們發(fā)送的順序排序,也就意味著如果一個(gè)客戶端將Znode z的值更新為值a,那么在之后的操作中,他會(huì)將z更新為b,在客戶端發(fā)現(xiàn)z帶有值b之后,就不會(huì)再看見(jiàn)帶有值a的z。

(2)原子性

更新不成功就失敗,這意味著如果更新失敗了,沒(méi)有客戶端會(huì)知道。☆☆

(3)單系統(tǒng)映像☆

無(wú)論客戶端連接的是哪臺(tái)服務(wù)器,他與系統(tǒng)看見(jiàn)的視圖一樣。這就意味著,如果一個(gè)客戶端在相同的會(huì)話時(shí)連接了一臺(tái)新的服務(wù)器,他將不會(huì)再看見(jiàn)比在之前服務(wù)器上看見(jiàn)的更老的系統(tǒng)狀態(tài),當(dāng)服務(wù)器系統(tǒng)出故障,同時(shí)客戶端嘗試連接ensemble中的其他機(jī)器時(shí),故障服務(wù)器的后面那臺(tái)機(jī)器將不會(huì)接受連接,直到它連接到故障服務(wù)器。

(4)容錯(cuò)性☆☆☆

一旦更新成功后,那么在客戶端再次更新他之前,他就固定了,將不再被修改,這就會(huì)保證產(chǎn)生下面兩種結(jié)果:

如果客戶端成功的獲得了正確的返回代碼,那么說(shuō)明更新已經(jīng)成功。如果不能夠獲得返回代碼(由于通信錯(cuò)誤、超時(shí)等原因),那么客戶端將不知道更新是否生效。

當(dāng)故障恢復(fù)的時(shí)候,任何客戶端能夠看到的執(zhí)行成功的更新操作將不會(huì)回滾。

(5)實(shí)時(shí)性☆☆

在任何客戶端的系統(tǒng)視圖上的的時(shí)間間隔是有限的,因此他在超過(guò)幾十秒的時(shí)間內(nèi)部會(huì)過(guò)期。這就意味著,服務(wù)器不會(huì)讓客戶端看一些過(guò)時(shí)的數(shù)據(jù),而是關(guān)閉,強(qiáng)制客戶端轉(zhuǎn)到一個(gè)更新的服務(wù)器上。

解釋一下:

由于性能原因,讀操作由ZooKeeper服務(wù)器的內(nèi)存提供,而且不參與寫(xiě)操作的全局排序。這一特性可能會(huì)導(dǎo)致來(lái)自使用ZooKeeper外部機(jī)制交流的客戶端與ZooKeeper狀態(tài)的不一致。舉例來(lái)說(shuō),客戶端A將Znode z的值a更新為a',A讓B來(lái)讀z,B讀到z的值是a而不是a’。這與ZooKeeper的保證機(jī)制是相容的(不允許的情況較作“同步一致的交叉客戶端視 圖”)。為了避免這種情況的發(fā)生,B在讀取z的值之前,應(yīng)該先調(diào)用z上的sync。Sync操作強(qiáng)制B連接上的ZooKeeper服務(wù)器與leader保 持一致這樣,當(dāng)B讀到z的值時(shí),他將成為A設(shè)置的值(或是之后的值)

容易混淆的是:

sync操作只能被異步調(diào)用12。這樣操作的原因是你不需要等待他的返回,因?yàn)閆ooKeeper保證了任何接下去的操作將會(huì)發(fā)生在sync在服務(wù)器上執(zhí)行以后,即使操作是在sync完成前被調(diào)用的。

這些已執(zhí)行的保證后,ZooKeeper更高級(jí)功能的設(shè)計(jì)與實(shí)現(xiàn)將會(huì)變得非常容易,例如:leader選舉、隊(duì)列,以及可撤銷(xiāo)鎖等機(jī)制的實(shí)現(xiàn)。

3.6 ZooKeeper會(huì)話

ZooKeeper客戶端與ensemble中的服務(wù)器列表配置一致,在啟動(dòng)時(shí),他嘗試與表中的一個(gè)服務(wù)器相連接。如果連接失敗了,他就嘗試表中的其他服務(wù)器,以此類(lèi)推,知道他最終連接到其中一個(gè),或者ZooKeeper的所有服務(wù)器都無(wú)法獲得時(shí),連接失敗。

一旦與ZooKeeper服務(wù)器連接成功,服務(wù)器會(huì)創(chuàng)建與客戶端的一個(gè)新的對(duì)話。每個(gè)回話都有超時(shí)時(shí)段,這是應(yīng)用程序在創(chuàng)建它時(shí)設(shè)定的。如果服務(wù)器沒(méi)有在超時(shí)時(shí)段內(nèi)得到請(qǐng)求,他可能會(huì)中斷這個(gè)會(huì)話。一旦會(huì)話被中斷了,他可能不再被打開(kāi),而且任何與會(huì)話相連接的臨時(shí)節(jié)點(diǎn)都將丟失。

無(wú)論什么時(shí)候會(huì)話持續(xù)空閑長(zhǎng)達(dá)一定時(shí)間,都會(huì)由客戶端發(fā)送ping請(qǐng)求保持活躍(猶如心跳)。時(shí)間段要足夠小以監(jiān)測(cè)服務(wù)器故障(由讀操作超時(shí)反應(yīng)),并且能再回話超市時(shí)間段內(nèi)重新連接到另一個(gè)服務(wù)器。

在ZooKeeper中有幾個(gè)time參數(shù)。tick time是ZooKeeper中的基本時(shí)間長(zhǎng)度,為ensemble里的服務(wù)器所使用,用來(lái)定義對(duì)于交互運(yùn)行的調(diào)度。其他設(shè)置以tick time的名義定義,或者至少由它來(lái)約束。

創(chuàng)建更復(fù)雜的臨時(shí)性狀態(tài)的應(yīng)用程序應(yīng)該支持更長(zhǎng)的會(huì)話超時(shí),因?yàn)橹匦聵?gòu)建的代價(jià)會(huì)更昂貴。在一些情況下,我們可以讓?xiě)?yīng)用程序在一定會(huì)話時(shí)間內(nèi)能夠重啟,并且避免會(huì)話過(guò)期。(這可能更適合執(zhí)行維護(hù)或是升級(jí))每個(gè)會(huì)話都由服務(wù)器給定一個(gè)唯一的身份和密碼,而且如果是在建立連接時(shí)被傳遞給ZooKeeper的話,只要沒(méi)有過(guò)期它能夠恢復(fù)會(huì)話。

這些特性可以視為一種可以避免會(huì)話過(guò)期的優(yōu)化,但它并不能代替用來(lái)處理會(huì)話過(guò)期。會(huì)話過(guò)期可能出現(xiàn)在機(jī)器突然故障時(shí),或是由于任何原因?qū)е碌膽?yīng)用程序安全關(guān)閉了,但在會(huì)話中斷前沒(méi)有重啟。

3.7 ZooKeeper實(shí)例狀態(tài)

Zookeeper對(duì)象的轉(zhuǎn)變是通過(guò)其生命周期中的不同狀態(tài)來(lái)實(shí)現(xiàn)。可以使用getState()方法在任何時(shí)候去查詢他的狀態(tài):

public states getState()

Zookeeper狀態(tài)事務(wù),如圖3.5所示

圖 3.5 Zookeeper狀態(tài)事務(wù)

  getState()方法的返回類(lèi)型是states,states是枚舉類(lèi)型代表Zookeeper對(duì)象可能所處的不同狀態(tài),一個(gè)Zookeeper實(shí)例可能一次只處于一個(gè)狀態(tài)。一個(gè)新建的Zookeeper實(shí)例正在于Zookeeper服務(wù)器建立連接時(shí),是處于CONNECTING狀態(tài)的。一旦連接建立好以后,他就變成了Connected狀態(tài)。

使用Zookeeper的客戶端可以通過(guò)注冊(cè)Watcher的方法來(lái)獲取狀態(tài)轉(zhuǎn)變的消息。一旦進(jìn)入了CONNNECTED狀態(tài),Watcher將獲得一個(gè)KeepState值為SyncConnected的WatchedEvent。

注意Zookeeper的watcher有兩個(gè)職責(zé):

<1>了解Zookeeper的狀態(tài)改變。傳遞給ZooKeeper對(duì)象構(gòu)造函數(shù)的(默認(rèn))watcher,被用來(lái)監(jiān)測(cè)狀態(tài)的改變。

<2>了解Zonde的改變。監(jiān)測(cè)Zonde的改變既可以使用專(zhuān)門(mén)的實(shí)例設(shè)置到讀操作上,也可以使用讀操作的默認(rèn)watcher。

Zookeeper實(shí)例可能失去或重新連接Zookeeper服務(wù),在CONNECTED和CONNECTING狀態(tài)中切換。如果連接斷開(kāi),watcher得到一個(gè)Disconnected事件。學(xué)要注意的是,這些狀態(tài)的遷移是由Zookeeper實(shí)例自己發(fā)起的,如果連接斷開(kāi)他將自動(dòng)嘗試自動(dòng)連接。

如果任何一個(gè)close()方法被調(diào)用,或是會(huì)話由Expired類(lèi)型的KeepState提示過(guò)期時(shí),ZooKeeper可能會(huì)轉(zhuǎn)變成第三種狀態(tài)CLOSED。一旦處于CLOSED狀態(tài),Zookeeper對(duì)象將不再是活動(dòng)的了(可以使用states的isActive()方法進(jìn)行測(cè)試),而且不能被重用。客戶端必須建立一個(gè)新的Zookeeper實(shí)例才能重新連接到Zookeeper服務(wù)。

下期預(yù)告:ZooKeeper的集群安裝和配置,敬請(qǐng)關(guān)注。本期內(nèi)容及供大家參考,有什么不對(duì)的地方,希望大家給予指點(diǎn)更正。如果您覺(jué)得,文章寫(xiě)得還行,就抬起您的貴手,點(diǎn)一下推薦

總結(jié)

以上是生活随笔為你收集整理的Zookeeper系列(一)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。