??ZAB是Zookeeper使用的分布式一致性協(xié)議,英文全稱(chēng)是:Zookeeper Atomic Broadcast,因此ZAB也稱(chēng)之為Zookeeper原子廣播協(xié)議。在解決分布式一致性方面,Zookeeper并沒(méi)有使用Paxos,而是采用了ZAB協(xié)議。基于ZAB協(xié)議,Zookeeper實(shí)現(xiàn)一種主備模式的系統(tǒng)架構(gòu)來(lái)保持集群中主備副本之間數(shù)據(jù)的一致性。ZAB協(xié)議包括兩種基本模式:消息廣播(Message Broadcasting)和崩潰恢復(fù)(Leader Activation)。下面來(lái)詳細(xì)介紹這兩種基本模式的實(shí)現(xiàn)過(guò)程。
消息廣播
??消息廣播是Zookeeper用來(lái)保證寫(xiě)入事務(wù)一致性的方法,在Zookeeper集群中,存在以下三種角色的節(jié)點(diǎn):
Leader:Zookeeper集群的核心角色,在集群?jiǎn)?dòng)或崩潰恢復(fù)中通過(guò)Follower參與選舉產(chǎn)生,為客戶(hù)端提供讀寫(xiě)服務(wù),并對(duì)事務(wù)請(qǐng)求進(jìn)行處理。
Follower:Zookeeper集群的核心角色,在集群?jiǎn)?dòng)或崩潰恢復(fù)中參加選舉,沒(méi)有被選上就是這個(gè)角色,為客戶(hù)端提供讀取服務(wù),也就是處理非事務(wù)請(qǐng)求,F(xiàn)ollower不能處理事務(wù)請(qǐng)求,對(duì)于收到的事務(wù)請(qǐng)求會(huì)轉(zhuǎn)發(fā)給Leader。
Observer:觀察者角色,不參加選舉,為客戶(hù)端提供讀取服務(wù),處理非事務(wù)請(qǐng)求,對(duì)于收到的事務(wù)請(qǐng)求會(huì)轉(zhuǎn)發(fā)給Leader。使用Observer的目的是為了擴(kuò)展系統(tǒng),提高讀取性能。
??下面通過(guò)幾張圖對(duì)ZAB的消息廣播過(guò)程進(jìn)行簡(jiǎn)單的介紹。
- Zookeeper各節(jié)點(diǎn)會(huì)接收來(lái)自客戶(hù)端的請(qǐng)求,如果是非事務(wù)請(qǐng)求,各節(jié)點(diǎn)自行進(jìn)行相應(yīng)的處理。若接收到的是客戶(hù)端的事務(wù)請(qǐng)求,如果當(dāng)前節(jié)點(diǎn)是Follower則將該請(qǐng)求轉(zhuǎn)發(fā)給當(dāng)前集群中的Leader節(jié)點(diǎn)進(jìn)行處理。

- Leader接收到事務(wù)處理的請(qǐng)求后,將向所有的Follower節(jié)點(diǎn)發(fā)出Proposal提議,并等待各Follower的Ack反饋。在廣播事務(wù)之前Leader服務(wù)器會(huì)先給這個(gè)事務(wù)分配一個(gè)全局單調(diào)遞增的唯一ID,也就是事務(wù)ID(zxid),每一個(gè)事務(wù)必須按照zxid的先后順序進(jìn)行處理。而且Leader服務(wù)器會(huì)為每一個(gè)Follower分配一個(gè)單獨(dú)的隊(duì)列,然后將需要廣播的事務(wù)放到隊(duì)列中。

- 各Follower節(jié)點(diǎn)對(duì)Leader節(jié)點(diǎn)的Proposal進(jìn)行Ack反饋,Leader對(duì)接收到的Ack進(jìn)行統(tǒng)計(jì),如果超多半數(shù)Follower進(jìn)行了Ack,此時(shí)進(jìn)行下一步操作,否則之間向客戶(hù)端進(jìn)行事務(wù)請(qǐng)求失敗的Response。

- 如果Leader節(jié)點(diǎn)接收到了超過(guò)半數(shù)的Ack響應(yīng),此時(shí)Leader會(huì)向所有的Follower發(fā)出事務(wù)Commit的指令,同時(shí)自己也執(zhí)行一次Commit,并向客戶(hù)端進(jìn)行事務(wù)請(qǐng)求成功的Response。

??Zookeeper的消息廣播過(guò)程類(lèi)似 2PC(Two Phase Commit),ZAB僅需要超過(guò)一半以上的Follower返回 Ack 信息就可以執(zhí)行提交,大大減小了同步阻塞,提高了可用性。
崩潰恢復(fù)
??在Zookeeper集群?jiǎn)?dòng)、運(yùn)行過(guò)程中,如果Leader出現(xiàn)崩潰、網(wǎng)絡(luò)斷開(kāi)、服務(wù)停止或重啟等異常情況,或集群中有新服務(wù)器加入時(shí),ZAB會(huì)讓當(dāng)前集群快速進(jìn)入崩潰恢復(fù)模式并選舉出新的Leader節(jié)點(diǎn),在此期間整個(gè)集群不對(duì)外提供任何讀取服務(wù)。當(dāng)產(chǎn)生了新的Leader后并集群中過(guò)半Follower完成了與Leader的狀態(tài)同步,那么ZAB協(xié)議就會(huì)讓Zookeeper集群從崩潰恢復(fù)模式轉(zhuǎn)換成消息廣播模式。崩潰恢復(fù)的目的就是保證當(dāng)前Zookeeper集群快速選舉出一個(gè)新的Leader并完成與其他Follower的狀態(tài)同步,以便盡快進(jìn)入消息廣播模式對(duì)外提供服務(wù)。
??Zookeeper崩潰恢復(fù)的主要任務(wù)就是選舉Leader(Leader Election),Leader選舉分兩個(gè)場(chǎng)景:一個(gè)是Zookeeper服務(wù)器啟動(dòng)時(shí)Leader選舉,另一個(gè)是Zookeeper集群運(yùn)行過(guò)程中Leader崩潰后的Leader選舉。在詳細(xì)介紹Leader選舉過(guò)程之前,需要先介紹幾個(gè)參數(shù):
myid: 服務(wù)器ID,這個(gè)是在安裝Zookeeper時(shí)配置的,myid越大,該服務(wù)器在選舉中被選為L(zhǎng)eader的優(yōu)先級(jí)會(huì)越大。
zxid: 事務(wù)ID,這個(gè)是由Zookeeper集群中的Leader節(jié)點(diǎn)進(jìn)行Proposal時(shí)生成的全局唯一的事務(wù)ID,由于只有Leader才能進(jìn)行Proposal,所以這個(gè)zxid很容易做到全局唯一且自增。因?yàn)镕ollower沒(méi)有生成zxid的權(quán)限。zxid越大,表示當(dāng)前節(jié)點(diǎn)上提交成功了最新的事務(wù),這也是為什么在崩潰恢復(fù)的時(shí)候,需要優(yōu)先考慮zxid的原因。
epoch: 投票輪次,每完成一次Leader選舉的投票,當(dāng)前Leader節(jié)點(diǎn)的epoch會(huì)增加一次。在沒(méi)有Leader時(shí),本輪此的epoch會(huì)保持不變。
另外在選舉的過(guò)程中,每個(gè)節(jié)點(diǎn)的當(dāng)前狀態(tài)會(huì)在以下幾種狀態(tài)之中進(jìn)行轉(zhuǎn)變。
LOOKING: 競(jìng)選狀態(tài)。
FOLLOWING: 隨從狀態(tài),同步Leader 狀態(tài),參與Leader選舉的投票過(guò)程。
OBSERVING: 觀察狀態(tài),同步Leader 狀態(tài),不參與Leader選舉的投票過(guò)程。
LEADING: 領(lǐng)導(dǎo)者狀態(tài)。
集群?jiǎn)?dòng)時(shí)的Leader選舉
??假設(shè)現(xiàn)在存在一個(gè)由5個(gè)Zookeeper服務(wù)器組成的集群Sever1,Sever2,Sever3,Sever4和Sever5,集群的myid分別為:1, 2,3,4,5。依次按照myid遞增的順序進(jìn)行啟動(dòng)。由于剛啟動(dòng)時(shí)zxid和epoch都為0,因此Leader選舉的關(guān)鍵因素成了myid。
- 啟動(dòng)Sever1,此時(shí)整個(gè)集群中只有Sever1啟動(dòng),Sever1無(wú)法與其他任何服務(wù)建立通信,立即進(jìn)入LOOKING狀態(tài),此時(shí)Server1給自己投1票(上來(lái)都覺(jué)得自己可以做Leader),由于1不大于集群總數(shù)的一半,即2,此時(shí)Sever1保持LOOKING狀態(tài)。
- 啟動(dòng)Sever2,此時(shí)Sever2與Server1建立通信,Sever1和Sever2互相交換投票信息,Server1投票的myid為1,Server2投票的myid為2,此時(shí)選取myid最大的,因此Sever1的投票會(huì)變成2,但是由于目前投票Server2的服務(wù)器數(shù)量為2臺(tái),小于集群總數(shù)的一半2,因此Sever1和Sever2繼續(xù)保持LOOKING狀態(tài)。
- 啟動(dòng)Sever3,此時(shí)三臺(tái)服務(wù)器之間建立了通信,Server3進(jìn)入LOOKING狀態(tài),并與前兩臺(tái)服務(wù)器交換投票信息,Server1和Server2的投票信息為2,Server3投票自己,即myid為3,這個(gè)時(shí)候選擇myid最大的作為L(zhǎng)eader。此時(shí)集群中投票3的服務(wù)器數(shù)量變成了3臺(tái),此時(shí)3>2,Sever3立刻變成LEADING狀態(tài),Sever1和Sever2變成FOLLOWING狀態(tài)。
- 啟動(dòng)Sever4,Sever4進(jìn)入LOOKING狀態(tài)并與前三臺(tái)服務(wù)器建立通信,由于集群中已經(jīng)存在LEADING狀態(tài)的節(jié)點(diǎn),因此,Sever4立刻變?yōu)镕OLLOWING狀態(tài),此時(shí)Sever3依舊處于LEADING狀態(tài)。
5.動(dòng)Sever5,Sever5與Sever4一樣,在與其他服務(wù)器建立通信后會(huì)立刻變?yōu)镕OLLOWING狀態(tài),此時(shí)Sever3依舊處于LEADING狀態(tài)。
最終整個(gè)Zookeeper集群中,Server3成為L(zhǎng)eader,Server1,Server2,Server4和Server5成為Follower,最終Server3的epoch加一。
Leader崩潰時(shí)的Leader選舉
??在Zookeeper集群剛啟動(dòng)的時(shí)候,zxid和epoch并不參與群首選舉。但是如果Zookeeper集群在運(yùn)行了一段時(shí)間之后崩潰了,那么epoch和zxid在Leader選舉中的重要性將大于myid。重要性的排序?yàn)椋篹poch zxid
myid。當(dāng)某一個(gè)Follower與Leader失去通信的時(shí)候,就會(huì)進(jìn)入Leader選舉,此時(shí)Follower會(huì)跟集群中的其他節(jié)點(diǎn)進(jìn)行通信,但此時(shí)會(huì)存在兩種情況:
- Follower與Leader失去通信,但此時(shí)集群中的Follower并未崩潰,且與其他Follower保持正常通信。此時(shí)當(dāng)該Follower與其他Follower進(jìn)行通信時(shí),其他Follower會(huì)告訴他,老大還活著,這個(gè)時(shí)候,F(xiàn)ollower僅需要與Leader建立通信即可。
- Leader真的崩潰了,此時(shí)集群中所有節(jié)點(diǎn)之間會(huì)進(jìn)行通信,當(dāng)?shù)弥洗髵炝酥?,每個(gè)節(jié)點(diǎn)都會(huì)開(kāi)啟爭(zhēng)老大模式,各自會(huì)將當(dāng)前節(jié)點(diǎn)最新的epoch,zxid和myid發(fā)送出來(lái),參與投票,此時(shí)各節(jié)點(diǎn)之間會(huì)參照epoch
zxid
myid進(jìn)行Leader選舉,最后投票數(shù)超過(guò)集群數(shù)量一般的節(jié)點(diǎn)會(huì)成為新的Leader。
??這種崩潰后的Leader選舉機(jī)制也很好理解,如果Leader掛了,優(yōu)先選擇集群中最后做過(guò)(epoch)Leader的節(jié)點(diǎn)為新的Leader節(jié)點(diǎn),其次選取有最新事務(wù)提交的節(jié)點(diǎn)(zxid)為L(zhǎng)eader,最后才按默認(rèn)的最大機(jī)器編號(hào)(myid)進(jìn)行投票。