Raft協議和ZAB協議
分散式系統設計中,在極大提高可用性、容錯性的同時,帶來了一致性問題(CAP理論),Raft協議和ZAB協議就是用於解決分散式中的一致性問題的方案。
一、Raft協議
1. Raft協議是什麼?
Raft協議是一種分散式一致性演算法(共識演算法),它是為了替代複雜難懂的 Paxos 演算法而生的。共識就是多個節點對某一個事件達成一致的演算法,即使出現部分節點故障,網路延時等情況,也不影響各節點,進而提高系統的整體可用性。Raft是使用較為廣泛的分散式協議,我們熟悉的etcd註冊中心就採用了這個演算法。
Raft演算法將分散式一致性分解為多個子問題,包括Leader選舉(Leader election)、日誌複製(Log replication)、安全性(Safety)、日誌壓縮(Log compaction)等。
2. 系統中的角色
Raft將系統中的角色分為領導者(Leader)、跟從者(Follower)和候選者(Candidate)。
- Leader:Leader:接受客戶端請求,並生成日誌條目,然後向 Follower 節點同步這些日誌。只有當該日誌條目被大多數節點持久化後,Leader 才會將該日誌條目標記為已提交,並通知 Follower 節點提交該日誌。Follower 節點在收到提交通知後,才會提交日誌,確保系統的日誌一致性。
- Follower:接受並持久化Leader同步的日誌,在Leader告知日誌可以提交後,提交日誌。當Leader出現故障時,主動推薦自己為候選人。
- Candidate:Leader選舉過程中的臨時角色。向其他節點傳送請求投票資訊,如果獲得大多數選票,則晉升為Leader。
Raft 要求系統在任意時刻最多隻有一個Leader,正常工作期間只有Leader和Follower,Raft演算法將時間劃分為任意不同長度的任期(Term),每一任期的開始都是一次選舉,一個或多個候選人會試圖稱為Leader,在成功選舉Leader後,Leader會在整個任期內管理整個叢集:負責處理所有的客戶端互動,日誌複製等,Follower 僅僅響應領導者的請求。如果Leader選舉失敗,該任期就會因為沒有Leader而結束,開始下一任期,並立刻開始下一次選舉。
3. Leader選舉
Raft使用心跳機制來觸發領導者選舉,當伺服器啟動時,初始化都是Follower身份,由於沒有Leader,Followers無法與Leader保持心跳,因此,Followers會認為Leader已經下線,進而轉為Candidate狀態,然後Candidate向叢集其他節點請求投票,同意自己成為Leader,如果Candidate收到超過半數節點的投票(N/2 +1),它將獲勝成為Leader。
如下圖:
1)選舉觸發時機
Leader向所有Follower週期性傳送heartbeat,如果Follower在選舉超時時間內沒有收到Leader的heartbeat,就會等待一段隨機的時間後發起一次Leader選舉。
2)唯一投票
在Raft協議中,一個節點在一次任期(term)內只能投一次票。這是為了防止同一候選者在一輪選舉中獲得多次投票,或者多個候選者在同一輪選舉中都獲得同一節點的投票,從而確保選舉的公正性。
在進入選舉投票時,每個節點都會先給自己投票,那會不會出現所有的節點都給自己投票呢?注意上述中 Candidate 和 Follower 的區別。
Follower 在一段時間內(超時時間)沒有接收到 Leader 的心跳,它就會把自己標記為 Candidate,成為 Candidate 後才會給自己投票,並給其他節點發起請求投票。但每個節點的超時時間都是隨機的,所以所有 Follower 節點進入 Candidate 狀態的時間是不一樣的。當第一個 Candidate 傳送請求投票給其他節點時,其他節點基本還是 Follower 狀態,還沒有把票投給自己。
同樣如果第一輪選舉失敗,要發起下一輪選舉。每個節點還是經過隨機的不同超時時間後,再進入 Candidate 狀態。
3)任期
在Raft協議中,任期被用作邏輯時鐘,並用於解決衝突。每當選舉開始時,候選者都會增加它們的任期。這樣可以確保每一輪選舉都有一個唯一的標識,同時也能防止過期的選舉結果影響新的選舉。
如果第一輪選舉失敗了,第二輪選舉開始時,候選者依然會首先增加它們的任期。例如,假設一個節點在第一輪選舉中沒有獲得足夠的投票,然後開始第二輪選舉。此時,如果它沒有增加其任期,那麼就可能出現一個問題:這個節點可能同時在第一輪和第二輪選舉中都是候選者。這將導致混亂,因為其他節點可能不知道他們應該對哪一輪選舉進行投票。
4. 日誌同步
Raft演算法實現日誌同步的具體過程如下:
1)Leader收到來自客戶端的請求,將之封裝成log entry並追加到自己的日誌中;
2)Leader並行地向系統中所有節點傳送日誌複製訊息;
3)接收到訊息的節點確認訊息沒有問題,則將log entry追加到自己的日誌中,並向Leader返回ACK表示接收成功;
4)Leader若在隨機超時時間內收到大多數節點的ACK,則將該log entry應用到狀態機並向客戶端返回成功。
如下圖:
二、ZAB協議
1. ZAB協議是什麼?
ZAB 協議主要是用在 ZooKeeper 叢集中。同 Raft協議一樣,都是為了替代複雜難懂的 Paxos 演算法,二者的相似度很高。
2. ZAB 協議核心
在 Zookeeper 中只有一個 Leader,並且只有 Leader 可以處理外部客戶端的事務請求,並將其轉換成一個事務 Proposal(寫操作),然後 Leader 伺服器再將事務 Proposal 操作的資料同步到所有 Follower(資料廣播/資料複製)。
Zookeeper 採用 Zab 協議的核心就是隻要有一臺伺服器提交了 Proposal,就要確保所有伺服器最終都能正確提交 Proposal,這也是 CAP/BASE 最終實現一致性的體現。
2. ZAB 兩種模式
ZAB 協議有兩種模式:一種是訊息廣播模式,另一種是崩潰恢復模式。
1)訊息廣播模式
在系統正常執行時,所有的資料更新操作都由一個領導者節點(Leader)發起,然後透過原子廣播方式傳遞到所有的追隨者節點(Follower)。
在 Zookeeper 叢集中資料副本的傳遞策略就是採用訊息廣播模式,Zookeeper 中的資料副本同步方式與2PC方式相似但卻不同,2PC是要求協調者必須等待所有參與者全部反饋ACK確認訊息後,再傳送 commit 訊息,要求所有參與者要麼全成功要麼全失敗,2PC方式會產生嚴重的阻塞問題。
而 Zookeeper 中 Leader 等待 Follower 的 ACK 反饋是指:只要半數以上的 Follower 成功反饋即可,不需要收到全部的 Follower 反饋。
2)崩潰恢復模式
一旦 Leader 伺服器出現崩潰或者由於網路原因導致 Leader 伺服器失去了與過半 Follower 的聯絡,那麼就會進入崩潰恢復模式。
Zookeeper 叢集中為保證任何程序能夠順序執行,只能是 Leader 伺服器接收寫請求,其他伺服器接收到客戶端的寫請求,也會轉發至 Leader 伺服器進行處理。
Zab 協議崩潰恢復需滿足以下2個請求:
確保已經被 Leader 提交的 proposal 必須最終被所有的 Follower 伺服器提交
確保丟棄已經被 Leader 提出的但沒有被提交的 Proposal
也就是新選舉出來的 Leader 不能包含未提交的 Proposal,必須都是已經提交了的 Proposal 的 Follower 伺服器節點,新選舉出來的 Leader 節點中含有最高的 ZXID,所以,在 Leader 選舉時,將 ZXID 作為每個 Follower 投票時的資訊依據。這樣做的好處是避免了 Leader 伺服器檢查 Proposal 的提交和丟棄工作。
3. Leader 選舉
ZAB協議的選舉過程主要發生在恢復模式中,一般在系統啟動或者領導者節點故障時觸發,主要分以下幾步:
1)開始選舉
每個節點首先投給自己一票,並將自己的編號和最後一條已經提交的事務的ZXID(Zookeeper Transaction ID,包含了事務的epoch和計數器)傳送給其他所有節點,表示它推舉自己成為領導者。
2)收集選票:接收到其他節點的投票資訊後,每個節點會比較其他節點的ZXID和自己的ZXID。如果其他節點的ZXID更高(epoch或者計數器更大),或者ZXID相同但是節點編號更大,那麼就會將票投給這個節點。
3)計票:每個節點收集到超過半數的投票(包括自己的)後,就會認為選舉完成,選出的領導者就是得票最多的節點。如果有多個節點的票數相同,就選擇ZXID最大的節點,如果還是相同,就選擇節點編號最大的。
4)領導者確認
選舉完成後,新的領導者會向所有節點傳送領導者確認訊息,其他節點收到確認訊息後,會向領導者傳送已經接受領導者的訊息。
5)新領導者工作
當領導者收到大多數節點的確認訊息時,就可以開始提供服務,處理客戶端的請求,從而結束了選舉過程。
總結:ZAB協議的選舉過程是為了在領導者節點故障時快速選出新的領導者,恢復系統的正常執行,同時還確保了系統的一致性。
三、Raft協議和ZAB協議的區別
透過選舉流程來看,二者差別不大,它們在領導者選舉的過程中主要區別在於:
1. 選舉條件
在Raft中,如果 Follower 在一段時間內沒有收到 Leader 的心跳資訊,就會主動進入候選人狀態並啟動新一輪選舉,原因可能只是 Leader 節點繁忙而無法及時響應等情況。而在ZAB除了系統啟動時,只有等到 Leader 故障,無法提供服務時才會進行選舉。Raft更偏向於積極選舉,只要有可能就嘗試選舉新的領導者,而ZAB更傾向於保持現狀,只有在確定領導者無法提供服務時才觸發選舉。
2. 投票規則
Raft 中,每個節點只能投票一次,並且投票給第一個請求投票的候選人。而在 ZAB 協議中,節點可能會改變自己的投票,投給 ZXID 更大的節點。所以 ZAB 不存在隨機超時時間,雖然第一票都會投給自己,但後續如果決定其他節點的 ZXID 更大,就修改自己的選票。
3. 票數要求:在Raft 中,候選人在獲得超過半數的投票後成為 Leader。在 ZAB 中,新的領導者被選出後,還需要得到超過半數的節點的確認才能開始工作。
4. 決定因素
在Raft中,選舉過程嚴格按照輪次進行,每輪選舉只能選出一位Leader,選出 Leader 很大程度取決於隨機的超時時間和日誌最新。而在 ZAB 中,選舉的結果主要取決於節點的 ZXID 以及節點編號。ZXID最大的節點通常是最近處理過事務,資料最新的節點。
參考連結:
https://juejin.cn/post/7143541597165060109
https://juejin.cn/post/7001070049200963621