Zookeeper是什么
Zookeeper是一個(gè)分布式協(xié)調(diào)服務(wù)的開(kāi)源框架。主要用來(lái)解決分布式集群中應(yīng)用系統(tǒng)的數(shù)據(jù)一致性問(wèn)題。
- 本質(zhì)上是一個(gè)分布式的小文件存儲(chǔ)系統(tǒng)。
- 提供給客戶端監(jiān)控存儲(chǔ)在zookeeper內(nèi)部數(shù)據(jù)的功能,從?可以達(dá)到基于數(shù)據(jù)的集群管理目的。諸如: 統(tǒng)?命名服務(wù)(dubbo)、分布式配置管理(solr的配置集中管理)、分布式消息隊(duì)列(sub/pub)、分布式鎖、分布式協(xié)調(diào)等功能。
Zookeeper角色架構(gòu)

-
Leader
- Zookeeper集群工作的核心角色;
- 集群內(nèi)部各個(gè)服務(wù)器的調(diào)度者;
- 事務(wù)請(qǐng)求(寫操作)的唯一調(diào)度和處理者,保證集群事務(wù)處理的順序性;對(duì)于 create,setData,delete 等有寫操作的請(qǐng)求,則需要統(tǒng)?轉(zhuǎn)發(fā)給leader 處理, leader 需要決定編號(hào)、執(zhí)?操作,這個(gè)過(guò)程稱為?個(gè)事務(wù)。
-
Follower
- 處理客戶端非事務(wù)(讀操作)請(qǐng)求。
- 轉(zhuǎn)發(fā)事務(wù)給Leader。
- 參與Leader的選舉投票。
-
Observer
- 觀察者角色,觀察 Zookeeper 集群的最新?tīng)顟B(tài)變化并將這些狀態(tài)同步過(guò)來(lái),其對(duì)于非事務(wù)請(qǐng)求可以進(jìn)?獨(dú)?處理,對(duì)于事務(wù)請(qǐng)求,則會(huì)轉(zhuǎn)發(fā)給 Leader服務(wù)器進(jìn)?處理。
- 不會(huì)參與任何形式的投票只提供非事務(wù)服務(wù),通常?于在不影響集群事務(wù)處理能力的前提下提升集群的非事務(wù)處理能?。增加了集群增加并發(fā)的讀請(qǐng)求。
Zookeeper的節(jié)點(diǎn)
Zookeeper的節(jié)點(diǎn)類型可以分為三大類:
- 持久性節(jié)點(diǎn)(Persistent)
- 臨時(shí)性節(jié)點(diǎn)(Ephemeral)
- 順序性節(jié)點(diǎn)(Sequential)
在實(shí)際創(chuàng)建節(jié)點(diǎn)的時(shí)候,會(huì)組合出四種節(jié)點(diǎn)類型: - 持久節(jié)點(diǎn)
- 持久順序節(jié)點(diǎn)
- 臨時(shí)節(jié)點(diǎn)
- 臨時(shí)順序節(jié)點(diǎn)
節(jié)點(diǎn)具體描述:
持久節(jié)點(diǎn):是Zookeeper中最常?的?種節(jié)點(diǎn)類型,所謂持久節(jié)點(diǎn),就是指節(jié)點(diǎn)被創(chuàng)建后會(huì)?直存在服務(wù)器,直到刪除操作主動(dòng)清除;
持久順序節(jié)點(diǎn):就是有順序的持久節(jié)點(diǎn),節(jié)點(diǎn)特性和持久節(jié)點(diǎn)是?樣的,只是額外特性表現(xiàn)在順序上。順序特性實(shí)質(zhì)是在創(chuàng)建節(jié)點(diǎn)的時(shí)候,會(huì)在節(jié)點(diǎn)名后?加上?個(gè)數(shù)字后綴,來(lái)表示其順序;
臨時(shí)節(jié)點(diǎn):就是會(huì)被?動(dòng)清理掉的節(jié)點(diǎn),它的?命周期和客戶端會(huì)話綁在?起,客戶端會(huì)話結(jié)束,節(jié)點(diǎn)會(huì)被刪除掉。與持久性節(jié)點(diǎn)不同的是,臨時(shí)節(jié)點(diǎn)不能創(chuàng)建?節(jié)點(diǎn);
臨時(shí)順序節(jié)點(diǎn):就是有順序的臨時(shí)節(jié)點(diǎn),和持久順序節(jié)點(diǎn)相同,在其創(chuàng)建的時(shí)候會(huì)在名字后?加上數(shù)字后綴;
事務(wù)ID:在Zookeeper中,對(duì)節(jié)點(diǎn)數(shù)據(jù)進(jìn)行更改的稱為事務(wù),概述為能夠改變Zookeeper服務(wù)器狀態(tài)的操作。對(duì)于每一個(gè)事務(wù)請(qǐng)求,Zookeeper都會(huì)為其分配一個(gè)全局唯一的事務(wù)ID,用ZXID(自增長(zhǎng)的)表示,通常是64位的數(shù)字。每個(gè)ZXID對(duì)應(yīng)一次數(shù)據(jù)的更新操作,從這些ZXID的順序可以間接識(shí)別出Zookeeper處理這些更新操作請(qǐng)求的全局順序。
節(jié)點(diǎn)的狀態(tài)信息
[zk: localhost:2181(CONNECTED) 0] get /
cZxid = 0x0 # Create ZXID,表示節(jié)點(diǎn)被創(chuàng)建時(shí)的事務(wù)ID
ctime = Thu Jan 01 08:00:00 CST 1970 # Create Time,表示節(jié)點(diǎn)創(chuàng)建時(shí)間
mZxid = 0x0 # Modified ZXID,表示節(jié)點(diǎn)最后?次被修改時(shí)的事務(wù)ID
mtime = Thu Jan 01 08:00:00 CST 1970 # Modified Time,表示節(jié)點(diǎn)最后?次被修改的時(shí)間
pZxid = 0x3600000010 # 該節(jié)點(diǎn)的子節(jié)點(diǎn)列表最后一次修改的事務(wù)ID
cversion = 126 # 子節(jié)點(diǎn)的版本號(hào)
dataVersion = 0 # 內(nèi)容版本號(hào)
aclVersion = 0 # 標(biāo)識(shí)acl版本
ephemeralOwner = 0x0 # 表示創(chuàng)建該臨時(shí)節(jié)點(diǎn)時(shí)的會(huì)話sessionID,如果是持久節(jié)點(diǎn)那么值為0
dataLength = 0 # 表示數(shù)據(jù)長(zhǎng)度
numChildren = 14 # 表示直系子節(jié)點(diǎn)數(shù)
Watcher機(jī)制
Zookeeper使用Watcher機(jī)制實(shí)現(xiàn)分布式數(shù)據(jù)的發(fā)布/訂閱功能
發(fā)布/訂閱
發(fā)布/訂閱系統(tǒng)定義了一種一對(duì)多的訂閱關(guān)系,能夠讓多個(gè)訂閱者同時(shí)監(jiān)聽(tīng)某一個(gè)主題對(duì)象,當(dāng)該主題對(duì)象的狀態(tài)發(fā)生變化時(shí),發(fā)布者會(huì)通知所有訂閱者,使他們能夠做出相應(yīng)的處理。
在Zookeeper中,其允許客戶端向服務(wù)端注冊(cè)一個(gè)Watcher監(jiān)聽(tīng),當(dāng)服務(wù)端的一些指定事件觸發(fā)了這個(gè)Watcher時(shí),那么Zookeeper就會(huì)向指定客戶端發(fā)送一個(gè)事件通知來(lái)實(shí)現(xiàn)分布式的通知功能。

具體?作流程為:
客戶端在向Zookeeper服務(wù)器注冊(cè)的同時(shí),會(huì)將Watcher對(duì)象存儲(chǔ)在客戶端的WatcherManager當(dāng)中,當(dāng)Zookeeper服務(wù)器觸發(fā)Watcher事件后,會(huì)向客戶端發(fā)送通知客戶端線程從WatcherManager中取出對(duì)應(yīng)的Watcher對(duì)象來(lái)執(zhí)?回調(diào)邏輯。
Leader選舉
選舉機(jī)制
- 半數(shù)機(jī)制:集群存活節(jié)點(diǎn)達(dá)半數(shù)以上,集群可用,因此Zookeeper適合安裝奇數(shù)臺(tái)服務(wù)器。
- Zookeeper雖然在配置?件中并沒(méi)有指定Master和Slave。但是,Zookeeper?作時(shí),是有?個(gè)節(jié)點(diǎn)為L(zhǎng)eader,其它為Follower,Leader是通過(guò)內(nèi)部的選舉機(jī)制產(chǎn)?的。
集群?次啟動(dòng)
在Zookeeper首次啟動(dòng)時(shí),在這里假設(shè)是按照id值的序號(hào)來(lái)順序啟動(dòng),分析其如何進(jìn)行選舉。

- 首先id為1的節(jié)點(diǎn)啟動(dòng),此時(shí)集群只有一臺(tái)機(jī)器啟動(dòng),該節(jié)點(diǎn)發(fā)出去的報(bào)文無(wú)響應(yīng),因此保持LOKKING狀態(tài)。
- 接著id為2的節(jié)點(diǎn)啟動(dòng),此時(shí)它和id為1的節(jié)點(diǎn)通信,互相交換??的選舉結(jié)果,由于兩者都沒(méi)有歷史數(shù)據(jù),所以id值較?的server2勝出,但是由于沒(méi)有達(dá)到超過(guò)半數(shù)以上的服務(wù)器都同意選舉它(這個(gè)例?中的半數(shù)以上是3),所以服務(wù)器1、2還是繼續(xù)保持LOOKING狀態(tài)。
- 接著id為3的節(jié)點(diǎn)啟動(dòng),根據(jù)前面的分析得到此時(shí)id為3的節(jié)點(diǎn)被選舉為L(zhǎng)eader。
- 隨后id為4,5的節(jié)點(diǎn)依次啟動(dòng)后,雖然它們的id值大,但是集群中已經(jīng)有半數(shù)以上的節(jié)點(diǎn)選舉了節(jié)點(diǎn)3為L(zhǎng)eader,所以節(jié)點(diǎn)4,5只能做Follower。
集群非首次啟動(dòng)
每個(gè)節(jié)點(diǎn)在選舉時(shí)都會(huì)參考?身節(jié)點(diǎn)的zxid值(事務(wù)ID);優(yōu)先選擇zxid值?的節(jié)點(diǎn)稱Leader!!
ZAB?致性協(xié)議
ZAB協(xié)議是Zookeeper為了解決集群分布式數(shù)據(jù)一致性問(wèn)題。
為什么要進(jìn)行數(shù)據(jù)的分布式存儲(chǔ)?在Zookeeper中有兩個(gè)好處:
- 消除單點(diǎn)故障問(wèn)題。將數(shù)據(jù)復(fù)制到多臺(tái)機(jī)器上,防止一臺(tái)機(jī)器宕機(jī)導(dǎo)致系統(tǒng)的不可用。
- 負(fù)載均衡。能夠讓分布在不同機(jī)器上的數(shù)據(jù)都能夠提供對(duì)外的客戶端服務(wù),有效提高性能。
但是Zookeeper引入了數(shù)據(jù)的分布式存儲(chǔ)時(shí),就可能會(huì)因?yàn)楦鞣N原因產(chǎn)生數(shù)據(jù)不一致的情況。
因此ZAB一致性協(xié)議就是用來(lái)解決這個(gè)問(wèn)題。
ZAB協(xié)議
ZK就是分布式?致性問(wèn)題的?業(yè)解決?案,paxos是其底層理論算法(晦澀難懂著名),其中zab,raft和眾多開(kāi)源算法是對(duì)paxos的?業(yè)級(jí)實(shí)現(xiàn)。ZK沒(méi)有完全采?paxos算法,?是使?了?種稱為Zookeeper Atomic Broadcast(ZAB,Zookeeper原?消息?播協(xié)議)的協(xié)議作為其數(shù)據(jù)?致性的核?算法。
ZAB 協(xié)議是為分布式協(xié)調(diào)服務(wù) Zookeeper 專?設(shè)計(jì)的?種?持崩潰恢復(fù)和原??播協(xié)議。
ZAB的具體體現(xiàn)
主備模式保證?致性

ZK怎么處理集群中的數(shù)據(jù)?
所有客戶端寫?數(shù)據(jù)都是寫?Leader中,然后,由 Leader 復(fù)制到Follower中。ZAB會(huì)將服務(wù)器數(shù)據(jù)的狀態(tài)變更以事務(wù)Proposal的形式?播到所有的副本進(jìn)程上,ZAB協(xié)議能夠保證了事務(wù)操作的?個(gè)全局的變更序號(hào)(ZXID)。
廣播消息
ZAB協(xié)議的消息廣播過(guò)程類似于二階段提交過(guò)程。
對(duì)于客戶端提交的寫請(qǐng)求全部由Leader接收,Leader 將請(qǐng)求封裝成?個(gè)事務(wù) Proposal(提議),將其發(fā)送給所有 Follwer ,如果收到超過(guò)半數(shù)反饋ACK,則執(zhí)? Commit 操作(先提交??,再發(fā)送 Commit 給所有 Follwer)。



不能正常反饋Follower恢復(fù)正常后會(huì)進(jìn)?數(shù)據(jù)同步階段最終與Leader保持?致;
細(xì)節(jié)如下:
- Leader接收到Client請(qǐng)求之后,會(huì)將這個(gè)請(qǐng)求封裝成?個(gè)事務(wù),并給這個(gè)事務(wù)分配?個(gè)全局遞增的唯? ID,稱為事務(wù)ID(ZXID),ZAB 協(xié)議要求保證事務(wù)的順序,因此必須將每?個(gè)事務(wù)按照 ZXID進(jìn)?先后排序然后處理。
- ZK集群為了保證任何事務(wù)操作能夠有序的順序執(zhí)?,只能是 Leader 服務(wù)器接受寫請(qǐng)求,即使是Follower 服務(wù)器接受到客戶端的請(qǐng)求,也會(huì)轉(zhuǎn)發(fā)到 Leader 服務(wù)器進(jìn)?處理。
zk提供的應(yīng)該是最終?致性的標(biāo)準(zhǔn)。zk所有節(jié)點(diǎn)接收寫請(qǐng)求之后可以在?定時(shí)間內(nèi)保證所有節(jié)點(diǎn)都能看到該條數(shù)據(jù)。
Leader 崩潰問(wèn)題
Leader宕機(jī)后,ZK集群?法正常?作,ZAB協(xié)議提供了?個(gè)?效且可靠的leader選舉算法。
Leader宕機(jī)后,被選舉的新Leader需要解決的問(wèn)題:
- ZAB 協(xié)議確保那些已經(jīng)在 Leader 提交的事務(wù)最終會(huì)被所有服務(wù)器提交。
- ZAB 協(xié)議確保丟棄那些只在 Leader 提出/復(fù)制,但沒(méi)有提交的事務(wù)。
基于上?的?的,ZAB協(xié)議設(shè)計(jì)了?個(gè)選舉算法:能夠確保已經(jīng)被Leader提交的事務(wù)被集群接受,丟棄還沒(méi)有提交的事務(wù)。
這個(gè)選舉算法的關(guān)鍵點(diǎn):保證選舉出的新Leader擁有集群中所有節(jié)點(diǎn)最?編號(hào)(ZXID)的事務(wù)。