1. 程式人生 > >分散式學習之raft演算法

分散式學習之raft演算法

0、背景介紹

一、為什麼要學習分散式系統以及raft演算法

二、我的分散式系統學習方法

三、總結

參考連結:

raft經典場景分析

一致性演算法允許多臺機器作為一個叢集協同工作,並且在其中的某幾臺機器出故障時叢集仍然能正常工作。 

正因為如此,一致性演算法在建立可靠的大規模軟體系統方面發揮了關鍵作用。 在過去十年中,Paxos 是一致性演算法的主流,

大多數一致性演算法的實現都是基於 Paxos 或受其影響,Paxos 已成為用於教授學生一致性相關知識的主要工具。

但不幸的是,Paxos 實在是太難以理解,我們開始著手尋找一個新的一致性演算法,可以為系統開發和教學提供更好的幫助。 

下面就是我們的主角閃亮登場,Raft 的一致性演算法

一、Raft基礎

分為以下幾點:

1) 一個 Raft 叢集包含若干個伺服器節點;通常是 5 個(奇數個),這樣的系統可以容忍 2 個節點的失效。

1.2  節點狀態

每個節點有三個狀態,他們會在這三個狀態之間進行變換。客戶端只能從主節點寫資料,從節點裡讀資料。

現在我們將leader、follower 或者 candidate三種狀態,類比現實世界中選舉流程中的角色

leader對應“國會議員”,當獲取多數派的投票後,candidate會晉升成leader狀態

follower對應“老百姓”,有

candidate對應“候選人”,

3) 在正常情況下,叢集中只有一個 leader ,並且其他的節點全部都是 follower 。

4) Follower 都是被動的:他們不會發送任何請求,只是簡單的響應來自 leader 和 candidate 的請求。

5) Leader 處理所有的客戶端請求(如果一個客戶端和 follower 通訊,follower 會將請求重定向給 leader)。

二、Leader選舉流程

所有伺服器節點​初始狀態都是Follwer狀態,一個伺服器節點只要能從 leader 或 candidate 處接收到有效的 RPC 就一直保持 follower 狀態。

有兩種超時時間timeout來控制選舉,

一種是election timeout,是節點從followers狀態轉換到candidate狀態的等待時間,隨機初始化值為150ms ~ 300ms

2.1 初始化時,所有follower都在等待成為candidate的場景

當某個follower的election timeout先到達後,follower 先增加自己的當前任期號並且轉換到 candidate 狀態

然後投票給自己並且並行地向叢集中的其他伺服器節點發送 RequestVote RPC(讓其他伺服器節點投票給它)

2.2 獲得多數派投票成為leader

當一個 candidate節點 獲得多數派的followers的投票,它就贏得了這次選舉併成為 leader 。然後它會follower節點發送心跳訊息來確定自己的地位並阻止新的選舉。 

2.3 接收到leader的AppendEntries訊息

在等待投票期間,candidate 可能會收到另一個聲稱自己是 leader 的伺服器節點發來的 AppendEntries RPC 。如果這個 leader 的任期號(包含在RPC中)不小於 candidate 當前的任期號,那麼 candidate 會承認該 leader 的合法地位並回到 follower 狀態。 如果 RPC 中的任期號比自己的小,那麼 candidate 就會拒絕這次的 RPC 並且繼續保持 candidate 狀態。

2.4 同時存在兩個candidate,並且獲得選票相同

圖中,A和D同時成為candidate

如果有兩個 follower 同時成為 candidate ,那麼選票可能會被瓜分以至於沒有 candidate 贏得過半的投票。

當這種情況發生時,每一個候選人都會超時,然後通過增加當前任期號來開始一輪新的選舉。然而,如果沒有其他機制的話,該情況可能會無限重複。

Raft 演算法使用隨機選舉超時時間的方法來解決這個問題,每個 candidate 在開始一次選舉的時候會重置一個隨機的選舉超時時間,然後一直等待直到選舉超時;這樣減小了在新的選舉中再次發生選票瓜分情況的可能性。

D節點由於隨機的超時時間比A節點的超時時間短,先達到超時狀態,獲得大多數的選票成為Leader。

三、日誌複製過程

3.1 Leader發起request請求

å¾ç

request請求後在leader節點寫入日誌條目,此時leader節點為uncommited狀態,複製狀態機並沒有執行命令

3.2 leader節點發送日誌條目到所有followers節點

å¾ç

Leader節點並行的向所有followers節點發送AppendEntries RPC 請求(簡稱“心跳包”),子節點複製上面的日誌條目後,由於心跳包還沒傳回主節點,Leader節點仍然為uncommitted狀態

3.3 心跳包傳回Leader節點,複製狀態機執行命令,進行更新

å¾ç

心跳包傳回Leader節點,Leader得知大多數follower伺服器已經將該命令寫入日誌條目中,

當Leader被選出來後,就可以接受客戶端發來的請求了(Leader是接收客戶端請求的唯一載體),每個請求包含一條需要被複制狀態機執行的命令。 Leader會把請求作為一個日誌條目追加到日誌中,然後給其它的follower伺服器發AppendEntries RPC請求,讓他們複製該日誌條目。當大多數follower伺服器已經將該命令寫入日誌條目中,leader 會應用該條目到它的狀態機中(狀態機執行該指令),然後返回結果給客戶端。如果某個Follower宕機了或者執行的很慢,或者網路丟包了,則會一直給這個Follower發AppendEntries RPC直到日誌一致。

當一條日誌是commited時,Leader才可以將它應用到狀態機中。Raft保證一條commited的log entry已經持久化了並且會被所有的節點執行。

當一個新的Leader被選出來時,它的日誌和其它的Follower的日誌可能不一樣,這個時候,就需要一個機制來保證日誌的一致性。一個新Leader產生時,叢集狀態可能如下: