一致性協議:RAFT


http://www.cnblogs.com/mindwind/p/5231986.html

Raft 協議的易理解性描述

雖然 Raft 的論文比 Paxos 簡單版論文還容易讀了,但論文依然發散的比較多,相對冗長。讀完後掩卷沉思覺得還是整理一下才會更牢靠,變成真正屬於自己的。這裏我就藉助前面黑白棋落子裏第一種極簡思維來描述和概念驗證下 Raft 協議的工作方式。

在一個由 Raft 協議組織的集羣中有三類角色:

  1. Leader(領袖)
  2. Follower(羣衆)
  3. Candidate(候選人)

就像一個民主社會,領袖由民衆投票選出。剛開始沒有領袖,所有集羣中的參與者都是羣衆,那麼首先開啓一輪大選,在大選期間所有羣衆都能參與競選,這時所有羣衆的角色就變成了候選人,民主投票選出領袖後就開始了這屆領袖的任期,然後選舉結束,所有除領袖的候選人又變回羣衆角色服從領袖領導。這裏提到一個概念「任期」,用術語 Term 表達。關於 Raft 協議的核心概念和術語就這麼多而且和現實民主制度非常匹配,所以很容易理解。三類角色的變遷圖如下,結合後面的選舉過程來看很容易理解。

Leader 選舉過程

在極簡的思維下,一個最小的 Raft 民主集羣需要三個參與者(如下圖:A、B、C),這樣纔可能投出多數票。初始狀態 ABC 都是 Follower,然後發起選舉這時有三種可能情形發生。下圖中前二種都能選出 Leader,第三種則表明本輪投票無效(Split Votes),每方都投給了自己,結果沒有任何一方獲得多數票。之後每個參與方隨機休息一陣(Election Timeout)重新發起投票直到一方獲得多數票。這裏的關鍵就是隨機 timeout,最先從 timeout 中恢復發起投票的一方向還在 timeout 中的另外兩方請求投票,這時它們就只能投給對方了,很快達成一致。

選出 Leader 後,Leader 通過定期向所有 Follower 發送心跳信息維持其統治。若 Follower 一段時間未收到 Leader 的心跳則認爲 Leader 可能已經掛了再次發起選主過程。

Leader 節點對一致性的影響

Raft 協議強依賴 Leader 節點的可用性來確保集羣數據的一致性。數據的流向只能從 Leader 節點向 Follower 節點轉移。當 Client 向集羣 Leader 節點提交數據後,Leader 節點接收到的數據處於未提交狀態(Uncommitted),接着 Leader 節點會併發向所有 Follower 節點複製數據並等待接收響應,確保至少集羣中超過半數節點已接收到數據後再向 Client 確認數據已接收。一旦向 Client 發出數據接收 Ack 響應後,表明此時數據狀態進入已提交(Committed),Leader 節點再向 Follower 節點發通知告知該數據狀態已提交。

在這個過程中,主節點可能在任意階段掛掉,看下 Raft 協議如何針對不同階段保障數據一致性的。

1. 數據到達 Leader 節點前

這個階段 Leader 掛掉不影響一致性,不多說。

2. 數據到達 Leader 節點,但未複製到 Follower 節點

這個階段 Leader 掛掉,數據屬於未提交狀態,Client 不會收到 Ack 會認爲超時失敗可安全發起重試。Follower 節點上沒有該數據,重新選主後 Client 重試重新提交可成功。原來的 Leader 節點恢復後作爲 Follower 加入集羣重新從當前任期的新 Leader 處同步數據,強制保持和 Leader 數據一致。

3. 數據到達 Leader 節點,成功複製到 Follower 所有節點,但還未向 Leader 響應接收

這個階段 Leader 掛掉,雖然數據在 Follower 節點處於未提交狀態(Uncommitted)但保持一致,重新選出 Leader 後可完成數據提交,此時 Client 由於不知到底提交成功沒有,可重試提交。針對這種情況 Raft 要求 RPC 請求實現冪等性,也就是要實現內部去重機制。

4. 數據到達 Leader 節點,成功複製到 Follower 部分節點,但還未向 Leader 響應接收

這個階段 Leader 掛掉,數據在 Follower 節點處於未提交狀態(Uncommitted)且不一致,Raft 協議要求投票只能投給擁有最新數據的節點。所以擁有最新數據的節點會被選爲 Leader 再強制同步數據到 Follower,數據不會丟失並最終一致。

5. 數據到達 Leader 節點,成功複製到 Follower 所有或多數節點,數據在 Leader 處於已提交狀態,但在 Follower 處於未提交狀態

這個階段 Leader 掛掉,重新選出新 Leader 後的處理流程和階段 3 一樣。

6. 數據到達 Leader 節點,成功複製到 Follower 所有或多數節點,數據在所有節點都處於已提交狀態,但還未響應 Client

這個階段 Leader 掛掉,Cluster 內部數據其實已經是一致的,Client 重複重試基於冪等策略對一致性無影響。

7. 網絡分區導致的腦裂情況,出現雙 Leader

網絡分區將原先的 Leader 節點和 Follower 節點分隔開,Follower 收不到 Leader 的心跳將發起選舉產生新的 Leader。這時就產生了雙 Leader,原先的 Leader 獨自在一個區,向它提交數據不可能複製到多數節點所以永遠提交不成功。向新的 Leader 提交數據可以提交成功,網絡恢復後舊的 Leader 發現集羣中有更新任期(Term)的新 Leader 則自動降級爲 Follower 並從新 Leader 處同步數據達成集羣數據一致。

綜上窮舉分析了最小集羣(3 節點)面臨的所有情況,可以看出 Raft 協議都能很好的應對一致性問題,並且很容易理解。

總結

就引用 Raft 論文最後的一節的綜述來總結本文吧。

算法以正確性、高效性、簡潔性作爲主要設計目標。
雖然這些都是很有價值的目標,但這些目標都不會達成直到開發者寫出一個可用的實現。
所以我們相信可理解性同樣重要。

深以爲然,想想 Paxos 算法是 Leslie Lamport 在 1990 年就公開發表在了自己的網站上,想想我們是什麼時候才聽說的?什麼時候纔有一個可用的實現?而 Raft 算法是 2013 年發表的,大家在參考[5]上面可以看到有多少個不同語言開源的實現庫了,這就是可理解性的重要性。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章