ZAB協議
概述
- ZAB協議是專門為zookeeper實現分布式協調功能而設計。zookeeper主要是根據ZAB協議是實現分布式系統數據一致性。
- zookeeper根據ZAB協議建立了主備模型完成zookeeper集群中數據的同步。這里所說的主備系統架構模型是指,在zookeeper集群中,只有一台leader負責處理外部客戶端的事物請求(或寫操作),然后leader服務器將客戶端的寫操作數據同步到所有的follower節點中。
- ZAB的協議核心是在整個zookeeper集群中只有一個節點即Leader將客戶端的寫操作轉化為事物(或提議proposal)。Leader節點再數據寫完之后,將向所有的follower節點發送數據廣播請求(或數據復制),等待所有的follower節點反饋。在ZAB協議中,只要超過半數follower節點反饋OK,Leader節點就會向所有的follower服務器發送commit消息。即將leader節點上的數據同步到follower節點之上。
- ZAB協議中主要有兩種模式,第一是消息廣播模式;第二是崩潰恢復模式
消息廣播模式
-
在zookeeper集群中數據副本的傳遞策略就是采用消息廣播模式。zookeeper中數據副本的同步方式與二階段提交相似但是卻又不同。二階段提交的要求協調者必須等到所有的參與者全部反饋ACK確認消息后,再發送commit消息。要求所有的參與者要么全部成功要么全部失敗。二階段提交會產生嚴重阻塞問題。
-
ZAB協議中Leader等待follower的ACK反饋是指”只要半數以上的follower成功反饋即可,不需要收到全部follower反饋”
-
-
zookeeper中消息廣播的具體步驟如下:
- 4.1. 客戶端發起一個寫操作請求
4.2. Leader服務器將客戶端的request請求轉化為事物proposql提案,同時為每個proposal分配一個全局唯一的ID,即ZXID。
4.3. leader服務器與每個follower之間都有一個隊列,leader將消息發送到該隊列
4.4. follower機器從隊列中取出消息處理完(寫入本地事物日志中)畢后,向leader服務器發送ACK確認。
4.5. leader服務器收到半數以上的follower的ACK后,即認為可以發送commit
4.6. leader向所有的follower服務器發送commit消息。
- 4.1. 客戶端發起一個寫操作請求
-
zookeeper采用ZAB協議的核心就是只要有一台服務器提交了proposal,就要確保所有的服務器最終都能正確提交proposal。這也是CAP/BASE最終實現一致性的一個體現。
-
leader服務器與每個follower之間都有一個單獨的隊列進行收發消息,使用隊列消息可以做到異步解耦。leader和follower之間只要往隊列中發送了消息即可。如果使用同步方式容易引起阻塞。性能上要下降很多。
崩潰恢復
-
zookeeper集群中為保證任何所有進程能夠有序的順序執行,只能是leader服務器接受寫請求,即使是follower服務器接受到客戶端的請求,也會轉發到leader服務器進行處理。
-
如果leader服務器發生崩潰,則zab協議要求zookeeper集群進行崩潰恢復和leader服務器選舉。
-
ZAB協議崩潰恢復要求滿足如下2個要求:
- 3.1. 確保已經被leader提交的proposal必須最終被所有的follower服務器提交。
- 3.2. 確保丟棄已經被leader出的但是沒有被提交的proposal。
-
根據上述要求,新選舉出來的leader不能包含未提交的proposal,即新選舉的leader必須都是已經提交了的proposal的follower服務器節點。同時,新選舉的leader節點中含有最高的ZXID。這樣做的好處就是可以避免了leader服務器檢查proposal的提交和丟棄工作。
-
leader服務器發生崩潰時分為如下場景:
5.1. leader在提出proposal時未提交之前崩潰,則經過崩潰恢復之后,新選舉的leader一定不能是剛才的leader。因為這個leader存在未提交的proposal。
5.2 leader在發送commit消息之后,崩潰。即消息已經發送到隊列中。經過崩潰恢復之后,參與選舉的follower服務器(剛才崩潰的leader有可能已經恢復運行,也屬於follower節點范疇)中有的節點已經是消費了隊列中所有的commit消息。即該follower節點將會被選舉為最新的leader。剩下動作就是數據同步過程。
數據同步
- 在zookeeper集群中新的leader選舉成功之后,leader會將自身的提交的最大proposal的事物ZXID發送給其他的follower節點。follower節點會根據leader的消息進行回退或者是數據同步操作。最終目的要保證集群中所有節點的數據副本保持一致。
- 數據同步完之后,zookeeper集群如何保證新選舉的leader分配的ZXID是全局唯一呢?這個就要從ZXID的設計談起。
2.1 ZXID是一個長度64位的數字,其中低32位是按照數字遞增,即每次客戶端發起一個proposal,低32位的數字簡單加1。高32位是leader周期的epoch編號,至於這個編號如何產生(我也沒有搞明白),每當選舉出一個新的leader時,新的leader就從本地事物日志中取出ZXID,然后解析出高32位的epoch編號,進行加1,再將低32位的全部設置為0。這樣就保證了每次新選舉的leader后,保證了ZXID的唯一性而且是保證遞增的。
ZAB協議原理
- ZAB協議要求每個leader都要經歷三個階段,即發現,同步,廣播。
- 發現:即要求zookeeper集群必須選擇出一個leader進程,同時leader會維護一個follower可用列表。將來客戶端可以這follower中的節點進行通信。
- 同步:leader要負責將本身的數據與follower完成同步,做到多副本存儲。這樣也是體現了CAP中高可用和分區容錯。follower將隊列中未處理完的請求消費完成后,寫入本地事物日志中。
- 廣播:leader可以接受客戶端新的proposal請求,將新的proposal請求廣播給所有的follower。
Zab與Paxos
- Paxos算法的確是不關心請求之間的邏輯順序,而只考慮數據之間的全序,但很少有人直接使用paxos算法,都會經過一定的簡化、優化。
- Paxos算法在出現競爭的情況下,其收斂速度很慢,甚至可能出現活鎖的情況,例如當有三個及三個以上的proposer在發送prepare請求后,很難有一個proposer收到半數以上的回復而不斷地執行第一階段的協議。因此,為了避免競爭,加快收斂的速度,在算法中引入了一個Leader這個角色,在正常情況下同時應該最多只能有一個參與者扮演Leader角色,而其它的參與者則扮演Acceptor的角色。
在這種優化算法中,只有Leader可以提出議案,從而避免了競爭使得算法能夠快速地收斂而趨於一致;而為了保證Leader的健壯性,又引入了Leader選舉,再考慮到同步的階段,漸漸的你會發現對Paxos算法的簡化和優化已經和上面介紹的ZAB協議很相似了。