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)來保持集群中各個副本之間的數(shù)據(jù)一致性
。
1.zab 協(xié)議介紹
ZAB 協(xié)議包含兩種基本模式所坯,分別是
崩潰恢復(fù)
消息廣播
當(dāng)整個集群在啟動時(shí)挂捅,或者當(dāng) leader 節(jié)點(diǎn)出現(xiàn)網(wǎng)絡(luò)中斷、崩潰等情況 時(shí)状土,ZAB 協(xié)議就會進(jìn)入恢復(fù)模式并選舉產(chǎn)生新的 Leader伺糠,當(dāng) leader 服務(wù)器選舉出來后,并且集群中有過半的機(jī)器和該 leader 節(jié)點(diǎn)完成數(shù)據(jù)同步后(同步指的是數(shù)據(jù)同步累驮,用來保證集群中過半的機(jī)器能夠和 leader 服務(wù)器的數(shù)據(jù)狀態(tài)保持一致)舵揭,ZAB 協(xié)議就會退出恢復(fù)模式
。
當(dāng)集群中已經(jīng)有過半的 Follower 節(jié)點(diǎn)完成了和 Leader 狀態(tài)同步以后毒租,那么整個集群就進(jìn)入了消息廣播模式。這個時(shí)候惕医,在 Leader 節(jié)點(diǎn)正常工作時(shí)算色,啟動一臺新的服務(wù)器加入到集群,那這個服務(wù)器會直接進(jìn)入數(shù)據(jù)恢復(fù)模式灾梦,和leader 節(jié)點(diǎn)進(jìn)行數(shù)據(jù)同步。同步完成后即可正常對外提供非事務(wù)請求的處理能岩。
2.消息廣播
消息廣播的過程實(shí)際上是一個簡化版本的二階段提交過程
- leader 接收到消息請求后萧福,將消息賦予一個全局唯一的64 位自增 id,叫:zxid鲫忍,通過 zxid 的大小比較既可以實(shí)現(xiàn)因果有序這個特征
- leader 為每個 follower 準(zhǔn)備了一個 FIFO 隊(duì)列(通過 TCP協(xié)議來實(shí)現(xiàn)悟民,以實(shí)現(xiàn)了全局有序這一個特點(diǎn))將帶有 zxid的消息作為一個提案(proposal)分發(fā)給所有的 follower
- 當(dāng) follower 接收到 proposal,先把
proposal 寫到磁盤近忙,寫入成功以后再向 leader 回復(fù)一個 ack
- 當(dāng) leader 接收到
合法數(shù)量(超過半數(shù)節(jié)點(diǎn))的 ACK 后鸦泳,leader 就會向這些 follower 發(fā)送commit 命令,同時(shí)會在本地執(zhí)行該消息
- 當(dāng) follower 收到消息的 commit 命令以后击纬,會提交該消息
跟2pc相比不同之處在于:
在leader接收到超過合法的半數(shù)數(shù)量更振,會向follower發(fā)起commit請求,而2pc是全部多要合法
leader節(jié)點(diǎn)是先本地執(zhí)行該消息肯腕,而2pc是等待所有的參與者節(jié)點(diǎn)返回ack的消息实撒,才開始完成事務(wù)
leader 的投票過程,不需要 Observer的ack捷兰,也就是Observer 不需要參與投票過程负敏,但是 Observer 必須要同步 Leader 的數(shù)據(jù)從而在處理請求的時(shí)候保證數(shù)據(jù)的一致性
2.崩潰恢復(fù)
ZAB 協(xié)議的這個基于原子廣播協(xié)議的消息廣播過程,在正常情況下是沒有任何問題的顶考,但是一旦 Leader 節(jié)點(diǎn)崩潰妖泄,或者由于網(wǎng)絡(luò)問題導(dǎo)致 Leader 服務(wù)器失去了過半的Follower 節(jié)點(diǎn)的聯(lián)系(leader 失去與過半 follower 節(jié)點(diǎn)聯(lián)系浮庐,可能是 leader 節(jié)點(diǎn)和 follower 節(jié)點(diǎn)之間產(chǎn)生了網(wǎng)絡(luò)分區(qū)柬焕,那么此時(shí)的 leader 不再是合法的 leader 了),那么就會進(jìn)入到崩潰恢復(fù)模式斑举。在 ZAB 協(xié)議中富玷,為了保證程序的正確運(yùn)行,整個恢復(fù)過程結(jié)束后需要選舉出一個新的Leader
3.基本特性
為了使 leader 掛了后系統(tǒng)能正常工作赎懦,需要解決以下兩個問題
1. 已經(jīng)被處理的消息不能丟失
當(dāng) leader 收到合法數(shù)量 follower 的 ACKs 后励两,就向各個 follower 廣播 COMMIT 命令,同時(shí)也會在本地執(zhí)行 COMMIT 并向連接的客戶端返回成功当悔。但是如果在各個 follower 在收到 COMMIT 命令前 leader 就掛了,導(dǎo)致剩下的服務(wù)器并沒有執(zhí)行都這條消息盲憎。
leader 對事務(wù)消息發(fā)起 commit 操作饼疙,但是該消息在follower1 上執(zhí)行了溺森,但是 follower2 還沒有收到 commit澡罚,就已經(jīng)掛了肾请,而實(shí)際上客戶端已經(jīng)收到該事務(wù)消息處理成功的回執(zhí)了。所以在 zab 協(xié)議下需要保證所有機(jī)器都要執(zhí)行這個事務(wù)消息
-
2. 被丟棄的消息不能再次出現(xiàn)
當(dāng) leader 接收到消息請求生成 proposal 后就掛了隔显,其他 follower 并沒有收到此 proposal,因此經(jīng)過恢復(fù)模式重新選了 leader 后饵逐,這條消息是被跳過的括眠。 此時(shí),之前掛了的 leader 重新啟動并注冊成了 follower倍权,他保留了被跳過消息的 proposal 狀態(tài)掷豺,與整個系統(tǒng)的狀態(tài)是不一致的,需要將其刪除薄声。
ZAB 協(xié)議需要滿足上面兩種情況当船,就必須要設(shè)計(jì)一個leader 選舉算法:能夠確保已經(jīng)被 leader 提交的事務(wù)Proposal能夠提交、同時(shí)丟棄已經(jīng)被跳過的事務(wù)Proposal
默辨。
針對這個要求
如果 leader 選舉算法能夠保證新選舉出來的 Leader 服務(wù)器擁有集群中所有機(jī)器最高編號(ZXID 最大
)的事務(wù)Proposal德频,那么就可以保證這個新選舉出來的 Leader 一定具有已經(jīng)提交的提案。因?yàn)樗刑岚副?COMMIT 之前必須有超過半數(shù)的 follower ACK缩幸,即必須有超過半數(shù)節(jié)點(diǎn)的服務(wù)器的事務(wù)日志上有該提案的 proposal壹置,因此表谊,只要有合法數(shù)量的節(jié)點(diǎn)正常工作难咕,就必然有一個節(jié)點(diǎn)保存了所有被 COMMIT 消息的 proposal 狀態(tài),
另外一個步藕,zxid 是 64 位咙冗,高 32 位是 epoch 編號雾消,每經(jīng)過一次 Leader 選舉產(chǎn)生一個新的 leader狂窑,新的 leader 會將epoch 號+1泉哈,低 32 位是消息計(jì)數(shù)器丛晦,每接收到一條消息這個值+1烫沙,新 leader 選舉后這個值重置為 0
.這樣設(shè)計(jì)的好處在于老的 leader 掛了以后重啟,它不會被選舉為 leader瘸爽,因此此時(shí)它的 zxid 肯定小于當(dāng)前新的 leader蝶糯。當(dāng)老的leader 作為 follower 接入新的 leader 后,新的 leader 會讓它將所有的擁有舊的 epoch 號的未被 COMMIT 的proposal 清除
4.關(guān)于 ZXID
zxid肢扯,也就是事務(wù) id,為了保證事務(wù)的順序一致性铭腕,zookeeper 采用了遞增的事務(wù) id 號(zxid)來標(biāo)識事務(wù)累舷。所有的提議(proposal)都在被提出的時(shí)候加上了 zxid析孽。實(shí)現(xiàn)中 zxid 是一個 64 位的數(shù)字袜瞬,它高 32 位是 epoch(ZAB 協(xié)議通過 epoch 編號來區(qū)分 Leader 周期變化的策略)用來標(biāo)識 leader 關(guān)系是否改變,每次一個 leader 被選出來贴谎,它都會有一個新的epoch=(原來的 epoch+1)佩捞,標(biāo)識當(dāng)前屬于那個 leader 的統(tǒng)治時(shí)期一忱。低 32 位用于遞增計(jì)數(shù)帘营。
epoch 的變化大家可以做一個簡單的實(shí)驗(yàn)芬迄,
- 啟動一個 zookeeper 集群。
- 在 /tmp/zookeeper/VERSION-2 路 徑 下 會 看 到 一 個currentEpoch 文件算途。文件中顯示的是當(dāng)前的 epoch
- 把 leader 節(jié)點(diǎn)停機(jī),這個時(shí)候在看 currentEpoch 會有變化廓脆。 隨著每次選舉新的 leader停忿,epoch 都會發(fā)生變化