- zookeeper為分布式應(yīng)用提供了高效且可靠的分布式協(xié)調(diào)服務(wù),提供了如統(tǒng)一命名服務(wù)、配置管理和分布式鎖等分布式的基礎(chǔ)服務(wù)。在分布式數(shù)據(jù)的一致性方面,zk并沒有直接采用paxos算法,而是采用zab的一致性協(xié)議。
一、初識(shí)zk
1、概述
- ZooKeeper是一個(gè)開源的分布式協(xié)調(diào)服務(wù)。ZooKeeper框架最初是在“Yahoo!"上構(gòu)建的,用于以簡(jiǎn)單而穩(wěn)健的方式訪問他們的應(yīng)用程序。 后來,Apache ZooKeeper成為Hadoop,HBase和其他分布式框架使用的有組織服務(wù)的標(biāo)準(zhǔn)。 例如,Apache HBase使用ZooKeeper跟蹤分布式數(shù)據(jù)的狀態(tài)。ZooKeeper 的設(shè)計(jì)目標(biāo)是將那些復(fù)雜且容易出錯(cuò)的分布式一致性服務(wù)封裝起來,構(gòu)成一個(gè)高效可靠的原語集,并以一系列簡(jiǎn)單易用的接口提供給用戶使用。
原語:操作系統(tǒng)或計(jì)算機(jī)網(wǎng)絡(luò)用語范疇。是由若干條指令組成的,用于完成一定功能的一個(gè)過程。具有不可分割性·即原語的執(zhí)行必須是連續(xù)的,在執(zhí)行過程中不允許被中斷。
- zk是一個(gè)典型的分布式數(shù)據(jù)一致性的解決方案。分布式應(yīng)用可以基于它實(shí)現(xiàn)數(shù)據(jù)的發(fā)布訂閱、負(fù)載均衡、命名服務(wù)、分布式協(xié)調(diào)和通知、集群管理、分布式鎖等。zk可以保證分布式的一致性特性。
-
Zookeeper 一個(gè)最常用的使用場(chǎng)景就是用于擔(dān)任服務(wù)生產(chǎn)者和服務(wù)消費(fèi)者的注冊(cè)中心。
zookeeper作為dubbo注冊(cè)中心
2、特點(diǎn)
順序一致性:從同一客戶端發(fā)起的事務(wù)請(qǐng)求,最終將會(huì)嚴(yán)格地按照順序被應(yīng)用到 ZooKeeper 中去。
原子性:更新只能成功或者失敗,沒有中間狀態(tài)。
單一視圖(無論客戶端連接的哪一個(gè)zk服務(wù)器,其看到的服務(wù)端數(shù)據(jù)模型是一樣的)
可靠性:一旦一次更改請(qǐng)求被應(yīng)用,更改的結(jié)果就會(huì)被持久化,直到被下一次更改覆蓋。
實(shí)時(shí)性(一定時(shí)間內(nèi)保證可以讀取到最新值)
3、zk設(shè)計(jì)目標(biāo)
- zk致力于提供一個(gè)高性能、高可用、且具有嚴(yán)格的順序訪問控制能力(主要是寫操作的嚴(yán)格順序性)的分布式協(xié)調(diào)服務(wù)。
(1)目標(biāo)一:簡(jiǎn)單的數(shù)據(jù)模型
zk使得分布式程序能夠通過一個(gè)共享的、樹形結(jié)構(gòu)的命名空間進(jìn)行相互協(xié)調(diào)。(這里的樹形結(jié)構(gòu),指zk服務(wù)器內(nèi)存中的一個(gè)數(shù)據(jù)模型,由一些列被稱為ZNode的數(shù)據(jù)節(jié)點(diǎn)組成)。zk將全量數(shù)據(jù)存儲(chǔ)在內(nèi)存中,以此來提高服務(wù)器吞吐、減少延時(shí)的目的。

(2)可以構(gòu)建集群
一個(gè)zk服務(wù)器集群通常由一組機(jī)器組成,一般3-5臺(tái)機(jī)器就可以組成一個(gè)可用的zk集群了。組成zk集群的每臺(tái)機(jī)器都會(huì)在內(nèi)存中維護(hù)當(dāng)前的服務(wù)器狀態(tài),并且每臺(tái)機(jī)器都互相保持著通信。只要集群中存在超過一般的機(jī)器能夠正常工作,那么整個(gè)集群就能正常保持服務(wù)。

- 上圖中每一個(gè)Server代表一個(gè)安裝Zookeeper服務(wù)的服務(wù)器。組成 ZooKeeper 服務(wù)的服務(wù)器都會(huì)在內(nèi)存中維護(hù)當(dāng)前的服務(wù)器狀態(tài),并且每臺(tái)服務(wù)器之間都互相保持著通信。集群間通過 Zab 協(xié)議(Zookeeper Atomic Broadcast)來保持?jǐn)?shù)據(jù)的一致性。
(3)順序訪問
來自客戶端的每一個(gè)版本請(qǐng)求,zk都會(huì)分配一個(gè)全局唯一的遞增編號(hào),這個(gè)編號(hào)表示了所有事物操作的先后順序
(4)高性能
zk將全量數(shù)據(jù)存儲(chǔ)在內(nèi)存中,并直接服務(wù)于客戶端的所有非事物請(qǐng)求,適用于讀操作為主的應(yīng)用場(chǎng)景。根據(jù)有關(guān)資料顯示壓測(cè)可達(dá)到12-13W的qps。
4、zk基本概念
(1)集群模式:zk引入leader、follower和observer三個(gè)角色。通過選舉產(chǎn)生leader機(jī)器,leader服務(wù)器為客戶端提供讀和寫服務(wù);follower和observer都能提供讀服務(wù),但是observer不參與選舉。
(2)會(huì)話session:在zk中,一個(gè)客戶端連接是指客戶端和服務(wù)端的一個(gè)TCP長(zhǎng)連接。對(duì)外默認(rèn)端口是2181,客戶端啟動(dòng)的時(shí)候,首先會(huì)和服務(wù)端建立一個(gè)TCP連接,從第一次建立開始,客戶端會(huì)話的生命周期也就開始了,通過這個(gè)連接,客戶端能夠通過心跳檢測(cè)與服務(wù)端保持有效的會(huì)話,也能夠向zk服務(wù)器發(fā)送請(qǐng)求并接受響應(yīng),同時(shí)還能夠通過該連接接收來自服務(wù)器的watch事件通知;session的sessionTimeout用來設(shè)置一個(gè)客戶端會(huì)話的超時(shí)時(shí)間,由于為止原因,導(dǎo)致客戶端連接斷開,只要sessionTimeout規(guī)定的時(shí)間內(nèi)能夠重新連上集群中任意一臺(tái)服務(wù)器,那么之前創(chuàng)建的會(huì)話仍然有效。
(3)數(shù)據(jù)節(jié)點(diǎn)ZNode:zk中數(shù)據(jù)節(jié)點(diǎn)指數(shù)據(jù)模型中的數(shù)據(jù)單元ZNode。數(shù)據(jù)模型是一顆樹,保存在內(nèi)存中,由\進(jìn)行分割的路徑,就是一個(gè)ZNode;在每一個(gè)ZNode上都會(huì)保存自己的數(shù)據(jù)內(nèi)容,同時(shí)會(huì)保存一些列的屬性信息。
1、持久性節(jié)點(diǎn):指一旦這個(gè)ZNode被創(chuàng)建,除非主動(dòng)進(jìn)行ZNode移除操作,否則這個(gè)ZNode將一直保存在zk中
2、臨時(shí)節(jié)點(diǎn):生命周期和客戶端會(huì)話綁定,一旦客戶端會(huì)話失效,這個(gè)客戶端創(chuàng)建的所有臨時(shí)節(jié)點(diǎn)都會(huì)被移除。
(4)版本:對(duì)應(yīng)于每一個(gè)ZNode,zk會(huì)為其維護(hù)一個(gè)叫做stat的數(shù)據(jù)結(jié)構(gòu),stat中記錄了這個(gè)ZNode的三個(gè)數(shù)據(jù)版本,分別是version(當(dāng)前ZNode版本)、cversion(當(dāng)前ZNode子節(jié)點(diǎn)版本)和aversion(當(dāng)前ZNode的ACL版本)
(5)Watcher:watche(事件監(jiān)聽器)是zk一個(gè)重要的特性,zk允許用戶在指定的節(jié)點(diǎn)上注冊(cè)一些東watcher,并且在一些特定的事件觸發(fā)的時(shí)候,zk服務(wù)端會(huì)將事件通知感興趣的客戶端上去,該機(jī)制是zk實(shí)現(xiàn)分布式協(xié)調(diào)的重要特性。
(6)ACL:zk采用ACL來進(jìn)行權(quán)限控制,zk定義了五種權(quán)限(create創(chuàng)建子節(jié)點(diǎn)、read獲取節(jié)點(diǎn)數(shù)據(jù)和子節(jié)點(diǎn)列表、write更新節(jié)點(diǎn)數(shù)據(jù)、delete刪除子節(jié)點(diǎn)、admin設(shè)置節(jié)點(diǎn)ACL)
5、小結(jié)
(1)ZooKeeper是一個(gè)開源的分布式協(xié)調(diào)服務(wù),提供了分布式數(shù)據(jù)一致性的解決方案。
(2)ZooKeeper 本身就是一個(gè)分布式程序(只要半數(shù)以上節(jié)點(diǎn)存活,ZooKeeper 就能正常服務(wù)),構(gòu)建zk集群時(shí)候節(jié)點(diǎn)個(gè)數(shù)必須大于1且是奇數(shù)。
(3)ZooKeeper 將數(shù)據(jù)保存在內(nèi)存中,這也就保證了 高吞吐量和低延遲(但是內(nèi)存限制了能夠存儲(chǔ)的容量不太大,此限制也是保持znode中存儲(chǔ)的數(shù)據(jù)量較小的進(jìn)一步原因)。
(4)ZooKeeper 是高性能的。 在“讀”多于“寫”的應(yīng)用程序中尤其地高性能,因?yàn)椤皩憽睍?huì)導(dǎo)致所有的服務(wù)器間同步狀態(tài)。(“讀”多于“寫”是協(xié)調(diào)服務(wù)的典型場(chǎng)景。)
(5)ZooKeeper有臨時(shí)節(jié)點(diǎn)的概念。
(6)ZooKeeper 底層其實(shí)只提供了兩個(gè)功能:①管理(存儲(chǔ)、讀取)用戶程序提交的數(shù)據(jù);②為用戶程序提交數(shù)據(jù)節(jié)點(diǎn)監(jiān)聽服務(wù)。
二、ZAB協(xié)議
1、ZAB協(xié)議與paxos協(xié)議關(guān)系
- Paxos 算法應(yīng)該可以說是 ZooKeeper 的靈魂了。但是,ZooKeeper 并沒有完全采用 Paxos算法 ,而是使用 ZAB 協(xié)議作為其保證數(shù)據(jù)一致性的核心算法。另外,在ZooKeeper的官方文檔中也指出,ZAB協(xié)議并不像 Paxos 算法那樣,是一種通用的分布式一致性算法,它是一種特別為Zookeeper設(shè)計(jì)的崩潰可恢復(fù)的原子消息廣播算法。
- ZAB(ZooKeeper Atomic Broadcast 原子廣播) 協(xié)議是為分布式協(xié)調(diào)服務(wù) ZooKeeper 專門設(shè)計(jì)的一種支持崩潰恢復(fù)的原子廣播協(xié)議。 在 ZooKeeper 中,主要依賴 ZAB 協(xié)議來實(shí)現(xiàn)分布式數(shù)據(jù)一致性,基于該協(xié)議,ZooKeeper 實(shí)現(xiàn)了一種主備模式的系統(tǒng)架構(gòu)來保持集群中各個(gè)副本之間的數(shù)據(jù)一致性。
ZAB協(xié)議的開發(fā)設(shè)計(jì)人員在協(xié)議設(shè)計(jì)之初并沒有要求其具有很好的擴(kuò)展性,最初只是雅虎公司內(nèi)部哪些高吞吐、低延遲、健壯、簡(jiǎn)單的分布式系統(tǒng)場(chǎng)景設(shè)計(jì)的,因此ZAB協(xié)議并不想paxos協(xié)議那樣,是一種通用的分布式一致性算法,是一種特別為zk設(shè)計(jì)的奔潰可恢復(fù)的原子消息廣播算法。
2、ZAB協(xié)議的核心
- zk的核心是定義了那些請(qǐng)求會(huì)改變zk服務(wù)器數(shù)據(jù)狀態(tài)的事物請(qǐng)求的處理方式。(其實(shí)核心就是原子廣播)
所有事物的請(qǐng)求必須由一個(gè)全局的唯一的服務(wù)器來協(xié)調(diào)處理,這樣的服務(wù)器稱為leader服務(wù)器,余下的服務(wù)器稱為follow服務(wù)器。leader服務(wù)器負(fù)責(zé)將一個(gè)客戶端請(qǐng)求轉(zhuǎn)換為一個(gè)(事物)proposal提議,并將該提議分發(fā)到集群中所有的follow服務(wù)器。之后leader服務(wù)器等待follow服務(wù)器的反饋,一旦超過半數(shù)的follow服務(wù)器進(jìn)行了正確的反饋后,leader服務(wù)器將再次向所有的follow服務(wù)器分發(fā)commit請(qǐng)求,要求將前一個(gè)proposal進(jìn)行提交。
3、ZAB協(xié)議基本模式(崩潰恢復(fù)和消息廣播)
(1)崩潰恢復(fù):當(dāng)整個(gè)服務(wù)框架在啟動(dòng)過程中,或是當(dāng) Leader 服務(wù)器出現(xiàn)網(wǎng)絡(luò)中斷、崩潰退出與重啟等異常情況時(shí),ZAB 協(xié)議就會(huì)進(jìn)人恢復(fù)模式并選舉產(chǎn)生新的Leader服務(wù)器。當(dāng)選舉產(chǎn)生了新的 Leader 服務(wù)器,同時(shí)集群中已經(jīng)有過半的機(jī)器與該Leader服務(wù)器完成了狀態(tài)同步之后,ZAB協(xié)議就會(huì)退出恢復(fù)模式。其中,所謂的狀態(tài)同步是指數(shù)據(jù)同步,用來保證集群中存在過半的機(jī)器能夠和Leader服務(wù)器的數(shù)據(jù)狀態(tài)保持一致。
(2)消息廣播:當(dāng)集群中已經(jīng)有過半的Follower服務(wù)器完成了和Leader服務(wù)器的狀態(tài)同步,那么整個(gè)服務(wù)框架就可以進(jìn)人消息廣播模式了。 當(dāng)一臺(tái)同樣遵守ZAB協(xié)議的服務(wù)器啟動(dòng)后加人到集群中時(shí),如果此時(shí)集群中已經(jīng)存在一個(gè)Leader服務(wù)器在負(fù)責(zé)進(jìn)行消息廣播,那么新加人的服務(wù)器就會(huì)自覺地進(jìn)人數(shù)據(jù)恢復(fù)模式:找到Leader所在的服務(wù)器,并與其進(jìn)行數(shù)據(jù)同步,然后一起參與到消息廣播流程中去。正如上文介紹中所說的,ZooKeeper設(shè)計(jì)成只允許唯一的一個(gè)Leader服務(wù)器來進(jìn)行事務(wù)請(qǐng)求的處理。Leader服務(wù)器在接收到客戶端的事務(wù)請(qǐng)求后,會(huì)生成對(duì)應(yīng)的事務(wù)提案并發(fā)起一輪廣播協(xié)議;而如果集群中的其他機(jī)器接收到客戶端的事務(wù)請(qǐng)求,那么這些非Leader服務(wù)器會(huì)首先將這個(gè)事務(wù)請(qǐng)求轉(zhuǎn)發(fā)給Leader服務(wù)器。
三、zk原理探究
1、zk角色概念

- 領(lǐng)導(dǎo)者(leader),負(fù)責(zé)進(jìn)行投票的發(fā)起和決議,更新系統(tǒng)狀態(tài)
- 學(xué)習(xí)者(learner),包括跟隨者(follower)和觀察者(observer),follower用于接受客戶端請(qǐng)求并想客戶端返回結(jié)果,在選主過程中參與投票。
- Observer可以接受客戶端連接,將寫請(qǐng)求轉(zhuǎn)發(fā)給leader,但observer不參加投票過程,只同步leader的狀態(tài),observer的目的是為了擴(kuò)展系統(tǒng),提高讀取速度
-
客戶端(client),請(qǐng)求發(fā)起方
zk各個(gè)角色總結(jié)歸納 - zk集群的服務(wù)節(jié)點(diǎn)在工作過程中有三種狀態(tài)。LOOKING:當(dāng)前Server不知道leader是誰,正在搜尋;LEADING:當(dāng)前Server即為選舉出來的leader;FOLLOWING:leader已經(jīng)選舉出來,當(dāng)前Server與之同步
2、zk的讀寫機(jī)制
- 首先zk是由多個(gè)server構(gòu)成的集群,集群中只有一個(gè)leader,多個(gè)leaner(多個(gè)follow和observer),leader負(fù)責(zé)總協(xié)調(diào)(比如實(shí)施更新請(qǐng)求轉(zhuǎn)發(fā)),每一個(gè)leaner保存一份數(shù)據(jù)的副本。zk通過zab協(xié)議的原子廣播模式實(shí)現(xiàn)了數(shù)據(jù)的全局一致性。
3、zk節(jié)點(diǎn)數(shù)據(jù)操作流程

1.在Client向Follwer發(fā)出一個(gè)寫的請(qǐng)求
2.Follwer把請(qǐng)求發(fā)送給Leader
3.Leader接收到以后開始發(fā)起投票并通知Follwer進(jìn)行投票
4.Follwer把投票結(jié)果發(fā)送給Leader
5.Leader將結(jié)果匯總后如果需要寫入,則開始寫入同時(shí)把寫入操作通知給follow,然后commit;
6.Follwer把請(qǐng)求結(jié)果返回給Client
4、zk選舉
- 當(dāng)leader崩潰或者leader失去大多數(shù)的follower,這時(shí)候zk進(jìn)入恢復(fù)模式,恢復(fù)模式需要重新選舉出一個(gè)新的leader,讓所有的Server都恢復(fù)到一個(gè)正確的狀態(tài)。Zk的選舉算法有兩種:一種是基于basic paxos實(shí)現(xiàn)的,另外一種是基于fast paxos算法實(shí)現(xiàn)的。系統(tǒng)默認(rèn)的選舉算法為fast paxos。
(1)集群?jiǎn)?dòng)時(shí)候選舉
以一個(gè)簡(jiǎn)單的例子來說明整個(gè)選舉的過程:假設(shè)有五臺(tái)服務(wù)器組成的 zookeeper 集群,它們 的 serverid 從 1-5,同時(shí)它們都是最新啟動(dòng)的,也就是沒有歷史數(shù)據(jù),在存放數(shù)據(jù)量這一點(diǎn) 上,都是一樣的。假設(shè)這些服務(wù)器依序啟動(dòng),來看看會(huì)發(fā)生什么
1、服務(wù)器 1 啟動(dòng),此時(shí)只有它一臺(tái)服務(wù)器啟動(dòng)了,它發(fā)出去的報(bào)沒有任何響應(yīng),所以它的 選舉狀態(tài)一直是 LOOKING 狀態(tài)
2、服務(wù)器 2 啟動(dòng),它與最開始啟動(dòng)的服務(wù)器 1 進(jìn)行通信,互相交換自己的選舉結(jié)果,由于 兩者都沒有歷史數(shù)據(jù),所以 id 值較大的服務(wù)器 2 勝出,但是由于沒有達(dá)到超過半數(shù)以上的服務(wù)器都同意選舉它(這個(gè)例子中的半數(shù)以上是 3),所以服務(wù)器 1、2 還是繼續(xù)保持 LOOKING 狀態(tài)
3、服務(wù)器 3 啟動(dòng),根據(jù)前面的理論分析,服務(wù)器 3 成為服務(wù)器 1,2,3 中的老大,而與上面不 同的是,此時(shí)有三臺(tái)服務(wù)器(超過半數(shù))選舉了它,所以它成為了這次選舉的 leader
4、服務(wù)器 4 啟動(dòng),根據(jù)前面的分析,理論上服務(wù)器 4 應(yīng)該是服務(wù)器 1,2,3,4 中最大的,但是 由于前面已經(jīng)有半數(shù)以上的服務(wù)器選舉了服務(wù)器 3,所以它只能接收當(dāng)小弟的命了
5、服務(wù)器 5 啟動(dòng),同 4 一樣,當(dāng)小弟
(2)奔潰恢復(fù)時(shí)候的選舉。
- 隨機(jī)讓一個(gè)服務(wù)器從新開始選舉,并配合version、serverid 和邏輯時(shí)鐘等概念。
5、zid概念
- znode節(jié)點(diǎn)的狀態(tài)信息中包含zxid,ZooKeeper狀態(tài)的每一次改變, 都對(duì)應(yīng)著一個(gè)遞增的Transaction id, 該id稱為zxid. 由于zxid的遞增性質(zhì), 如果zxid1小于zxid2, 那么zxid1肯定先于zxid2發(fā)生.創(chuàng)建任意節(jié)點(diǎn), 或者更新任意節(jié)點(diǎn)的數(shù)據(jù), 或者刪除任意節(jié)點(diǎn), 都會(huì)導(dǎo)致Zookeeper狀態(tài)發(fā)生改變, 從而導(dǎo)致zxid的值增加.
6、zk狀態(tài)同步流程

- 選完Leader以后,zk就進(jìn)入狀態(tài)同步過程。
- Leader等待server連接;
2 .Follower連接leader,將最大的zxid發(fā)送給leader;
3 .Leader根據(jù)follower的zxid確定同步點(diǎn);
4 .完成同步后通知follower 已經(jīng)成為uptodate狀態(tài);
5 .Follower收到uptodate消息后,又可以重新接受client的請(qǐng)求進(jìn)行服務(wù)了。
7、zk中l(wèi)eader工作機(jī)制

1 .恢復(fù)數(shù)據(jù);
2 .維持與Learner的心跳,接收Learner請(qǐng)求并判斷Learner的請(qǐng)求消息類型;
3 .Learner的消息類型主要有PING消息(Learner的心跳信息)、REQUEST消息(Follower發(fā)送的提議信息,包括寫請(qǐng)求及同步請(qǐng)求)、ACK消息( Follower的對(duì)提議的回復(fù),超過半數(shù)的Follower通過,則commit該提議)、REVALIDATE消息(用來延長(zhǎng)SESSION有效時(shí)間),根據(jù)不同的消息類型,進(jìn)行不同的處理。
8、 follow的工作機(jī)制

1.向Leader發(fā)送請(qǐng)求(PING消息、REQUEST消息、ACK消息、REVALIDATE消息);
2.接收Leader消息并進(jìn)行處理;
3.接收Client的請(qǐng)求,如果為寫請(qǐng)求,發(fā)送給Leader進(jìn)行投票;
4.返回Client結(jié)果。
9、Observer工作機(jī)制
- 為了支持更多的客戶端,需要增加更多Server,Server增多,投票階段延遲增大,影響性能.。權(quán)衡伸縮性和高吞吐率,引入Observer,Observer不參與投票(其他和follow職責(zé)一樣)
- 加入更多Observer節(jié)點(diǎn),提高伸縮性,同時(shí)不影響吞吐率
10、zk中保證事物的順序性
- 為了保證事務(wù)的順序一致性,zookeeper采用了遞增的事務(wù)id號(hào)(zxid)來標(biāo)識(shí)事務(wù)。所有的提議(proposal)都在被提出的時(shí)候加上了zxid。實(shí)現(xiàn)中zxid是一個(gè)64位的數(shù)字,它高32位是epoch用來標(biāo)識(shí)leader關(guān)系是否改變,每次一個(gè)leader被選出來,它都會(huì)有一個(gè)新的epoch,標(biāo)識(shí)當(dāng)前屬于那個(gè)leader的統(tǒng)治時(shí)期。低32位用于遞增計(jì)數(shù)。
參考:
《從Paxos到Zookeeper 》
https://segmentfault.com/a/1190000016349824
https://blog.csdn.net/xqb_756148978/article/details/52259381
https://www.cnblogs.com/qingyunzong/p/8632995.html#_label4_4
https://blog.csdn.net/qq_22094297/article/details/80692624

