RAFT

RAFT核心思想很容易理解,如果數個數據庫,初始狀態一致,只要之後的進行的操作一致,就能保證之後的數據一致。由此RAFT使用的是Log進行同步,並且將服務器分爲三中角色:Leader,Follower,Candidate,相互可以互相轉換。
RAFT從大的角度看,分爲兩個過程:
1. 選舉Leader
2. Leader生成Log,並與Follower進行Headbeats同步

選舉Leader

Follower自增當前任期,轉換爲Candidate,對自己投票,併發起RequestVote RPC,等待下面三種情形發生;

1. 獲得超過半數服務器的投票,贏得選舉,成爲Leader
2. 另一臺服務器贏得選舉,並接收到對應的心跳,成爲Follower
3. 選舉超時,沒有任何一臺服務器贏得選舉,自增當前任期,重新發起選舉

同步日誌

Leader接受客戶端請求,Leader更新日誌,並向所有Follower發送Heatbeats,同步日誌。所有Follwer都有ElectionTimeout,如果在ElectionTimeout時間之內,沒有收到Leader的Headbeats,則認爲Leader失效,重新選舉Leader
流程圖示:

安全性保證

1. 日誌的流向只有Leader到Follower,並且Leader不能覆蓋日誌
2. 日誌不是最新者不能成爲Candidate

  1. 在Raft中,問題分解爲:領導選取、日誌複製、安全和成員變化。

    基本概念

    複製狀態機(Replicated State Machine)

    1.png
    • 複製狀態機通過複製日誌來實現:

      • 日誌:每臺機器保存一份日誌,日誌來自於客戶端的請求,包含一系列的命令
      • 狀態機:狀態機會按順序執行這些命令
      • 一致性模型:分佈式環境下,保證多機的日誌是一致的,這樣回放到狀態機中的狀態是一致的
    • 一致性算法作用於一致性模型,一般有以下特性:

      • safety:在非拜占庭問題下(網絡延時,網絡分區,丟包,重複發包以及包亂序等),結果是正確的
      • availability:在半數以上機器能正常工作時,則系統可用
      • timing-unindependent:不依賴於時鐘來保證日誌一致性,錯誤的時鐘以及極端的消息時延最多會造成可用性問題

    注意:
    真實的實現中,建議狀態機的每個命令操作都採用冪等的,這樣一致性的保證會更容易。

    服務器狀態

    每臺服務器一定會處於三種狀態:

    1. 領導者
    2. 候選人
    3. 追隨者
    2.png

    追隨者只響應其他服務器的請求。如果追隨者沒有收到任何消息,它會成爲一個候選人並且開始一次選舉。收到大多數服務器投票的候選人會成爲新的領導人。領導人在它們宕機之前會一直保持領導人的狀態。

    任期(Term)

    Raft 算法將時間劃分成爲任意不同長度的任期(term)。任期用連續的數字進行表示。每一個任期的開始都是一次選舉(election),一個或多個候選人會試圖成爲領導人。如果一個候選人贏得了選舉,它就會在該任期的剩餘時間擔任領導人。在某些情況下,選票會被瓜分,有可能沒有選出領導人,那麼,將會開始另一個任期,並且立刻開始下一次選舉。Raft 算法保證在給定的一個任期最多隻有一個領導人。

    3.png

    RPC

    Raft 算法中服務器節點之間通信使用遠程過程調用(RPCs),並且基本的一致性算法只需要兩種類型的 RPCs。請求投票(RequestVote) RPCs 由候選人在選舉期間發起,然後附加條目(AppendEntries)RPCs 由領導人發起,用來複制日誌和提供一種心跳機制。爲了在服務器之間傳輸快照增加了第三種 RPC。當服務器沒有及時的收到 RPC 的響應時,會進行重試, 並且他們能夠並行的發起 RPCs 來獲得最佳的性能。
    RPC有三種:

    1. RequestVote RPC:候選人在選舉期間發起
    2. AppendEntries RPC:領導人發起的一種心跳機制,複製日誌也在該命令中完成
    3. InstallSnapshot RPC: 領導者使用該RPC來發送快照給太落後的追隨者。

    超時設置:

    1. BroadcastTime : 領導者的心跳超時時間
    2. Election Timeout: 追隨者設置的候選超時時間
    3. MTBT :指的是單個服務器發生故障的間隔時間的平均數

    BroadcastTime << ElectionTimeout << MTBF
    兩個原則:

    1. BroadcastTime應該比ElectionTimeout小一個數量級,爲的是使領導人能夠持續發送心跳信息(heartbeat)來阻止追隨者們開始選舉;
    2. ElectionTimeout也要比MTBF小几個數量級,爲的是使得系統穩定運行。

    一般BroadcastTime大約爲0.5毫秒到20毫秒,ElectionTimeout一般在10ms到500ms之間。大多數服務器的MTBF都在幾個月甚至更長。

  2. 領導人選取

    • 觸發條件:

      1. 一般情況下,追隨者接到領導者的心跳時,把ElectionTimeout清零,不會觸發;
      2. 領導者故障,追隨者的ElectionTimeout超時發生時,會變成候選者,觸發領導人選取;
    • 候選操作過程:

    追隨者自增當前任期,轉換爲Candidate,對自己投票,併發起RequestVote RPC,等待下面三種情形發生;

    1. 獲得超過半數服務器的投票,贏得選舉,成爲領導者;
    2. 另一臺服務器贏得選舉,並接收到對應的心跳,成爲追隨者;
    3. 選舉超時,沒有任何一臺服務器贏得選舉,自增當前任期,重新發起選舉;
    • 注意事項:

      1. 服務器在一個任期內,最多能給一個候選人投票,採用先到先服務原則;
      2. 候選者等待投票時,可能會接收到來自其它聲明爲領導人的的AppendEntries RPC。如果該領導人的任期(RPC中有)比當前候選人的當前任期要大,則候選人認爲該領導人合法,並轉換成追隨者;如果RPC中的任期小於候選人的當前任期,則候選人拒絕此次RPC,繼續保持候選人狀態;
      3. 候選人既沒有贏得選舉也沒有輸掉選舉:如果許多追隨者在同一時刻都成爲了候選人,選票會被分散,可能沒有候選人能獲得大多數的選票。當這種情形發生時,每一個候選人都會超時,並且通過自增任期號和發起另一輪 RequestVote RPC 來開始新的選舉。然而,如果沒有其它手段來分配選票的話,這種情形可能會無限的重複下去。所以Raft使用的隨機的選舉超時時間(150~300ms之間),來避免這種情況發生。
    • 問題探討:爲什麼這裏沒有談收到其他候選者的RequestVote RPC請求?
      可能的解釋:

      1. 候選者已經給自己投票了,一個候選者在一個任期只會給一個人投票,不會給其他人再投票了;
      2. 也有可能算法本身設定候選者就拒絕所有的其他服務器的請求。

     

  3. 日誌複製

    4.png

    接受命令的過程:

    1. 領導者接受客戶端請求;
    2. 領導者把指令追加到日誌;
    3. 發送AppendEntries RPC到追隨者;
    4. 領導者收到大多數追隨者的確認後,領導者Commit該日誌,把日誌在狀態機中回放,並返回結果給客戶端;

    提交過程:

    1. 在下一個心跳階段,領導者再次發送AppendEntries RPC給追隨者,日誌已經commited;
    2. 追隨者收到Commited日誌後,將日誌在狀態機中回放。

安全性

到目前爲止描述的機制並不能充分的保證每一個狀態機會按照相同的順序執行相同的指令,例如:一個跟隨者可能會進入不可用狀態同時領導人已經提交了若干的日誌條目,然後這個跟隨者可能會被選舉爲領導人並且覆蓋這些日誌條目;因此,不同的狀態機可能會執行不同的指令序列。

1. 領導者追加日誌(Append-Only)

領導者永遠不會覆蓋已經存在的日誌條目;
日誌永遠只有一個流向:從領導者到追隨者;

2. 選舉限制:投票阻止沒有全部日誌條目的服務器贏得選舉

如果投票者的日誌比候選人的新,拒絕投票請求;
這意味着要贏得選舉,候選者的日誌至少和大多數服務器的日誌一樣新,那麼它一定包含全部的已經提交的日誌條目。

3. 永遠不提交任期之前的日誌條目(只提交任期內的日誌條目)

在Raft算法中,當一個日誌被安全的複製到絕大多數的機器上面,即AppendEntries RPC在絕大多數服務器正確返回了,那麼這個日誌就是被提交了,然後領導者會更新commit index。

5.png

如果允許提交任期之前的日誌條目,那麼在步驟c中,我們就會把之前任期爲2的日誌提交到其他服務器中去,並造成了大多數機器存在了日誌爲2的情況。所以造成了d中S5中任期爲3的日誌條目會覆蓋掉已經提交的日誌的情況。

Raft 從來不會通過計算複製的數目來提交之前人氣的日誌條目。只有領導人當前任期的日誌條目才能通過計算數目來進行提交。一旦當前任期的日誌條目以這種方式被提交,那麼由於日誌匹配原則(Log Matching Property),之前的日誌條目也都會被間接的提交。

論文中的這段話比較難理解,更加直觀的說:由於Raft不會提交任期之前的日誌條目,那麼就不會從b過渡到c的情況,只能從b發生S5down機的情況下直接過渡到e,這樣就產生的更新的任期,這樣S5就沒有機會被選爲領導者了。

4. 候選者和追隨者崩潰

候選者和追隨者崩潰的情況處理要簡單的多。如果這類角色崩潰了,那麼後續發送給他們的 RequestVote和AppendEntries的所有RCP都會失敗,Raft算法中處理這類失敗就是簡單的無限重試的方式。

  如果這些服務器重新可用,那麼這些RPC就會成功返回。如果一個服務器完成了一個RPC,但是在響應Leader前崩潰了,那麼當他再次可用的時候還會收到相同的RPC請求,此時接收服務器負責檢查,比如如果收到了已經包含該條日誌的RPC請求,可以直接忽略這個請求,確保對系統是無害的。


集羣成員變更

集羣成員的變更和成員的宕機與重啓不同,因爲前者會修改成員個數進而影響到領導者的選取和決議過程,因爲在分佈式系統這對於majority這個集羣中成員大多數的概念是極爲重要的。

簡單的做法是,運維人員將系統臨時下線,修改配置,重新上線。但是這種做法存在兩個缺點:

  1. 更改時集羣不可用
  2. 人爲操作失誤風險

直接從一種配置轉到新的配置是十分不安全的

如下圖所示:

6.png

因爲各個機器可能在任何的時候進行轉換。在這個例子中,集羣配額從 3 臺機器變成了 5 臺。不幸的是,存在這樣的一個時間點,兩個不同的領導人在同一個任期裏都可以被選舉成功。一個是通過舊的配置,一個通過新的配置。

兩階段方法保證安全性:

爲了保證安全性,配置更改必須使用兩階段方法。在 Raft 中,集羣先切換到一個過渡的配置,我們稱之爲共同一致;一旦共同一致已經被提交了,那麼系統就切換到新的配置上。共同一致是老配置和新配置的結合。

共同一致允許獨立的服務器在不影響安全性的前提下,在不同的時間進行配置轉換過程。此外,共同一致可以讓集羣在配置轉換的過程人依然響應服務器請求。

一個領導人接收到一個改變配置從 C-old 到 C-new 的請求,他會爲了共同一致存儲配置(圖中的 C-old,new),以前面描述的日誌條目和副本的形式。一旦一個服務器將新的配置日誌條目增加到它的日誌中,他就會用這個配置來做出未來所有的決定。領導人完全特性保證了只有擁有 C-old,new 日誌條目的服務器纔有可能被選舉爲領導人。當C-old,new日誌條目被提交以後,領導人在使用相同的策略提交C-new,如下圖所示,C-old 和 C-new 沒有任何機會同時做出單方面的決定,這就保證了安全性。


一個配置切換的時間線。虛線表示已經被創建但是還沒有被提交的條目,實線表示最後被提交的日誌條目。領導人首先創建了 C-old,new 的配置條目在自己的日誌中,並提交到 C-old,new 中(C-old,new 的大多數和 C-new 的大多數)。然後他創建 C-new 條目並提交到 C-new 中的大多數。這樣就不存在 C-new 和 C-old 可以同時做出決定的時間點。



日誌壓縮

日誌會隨着系統的不斷運行會無限制的增長,這會給存儲帶來壓力,幾乎所有的分佈式系統(Chubby、ZooKeeper)都採用快照的方式進行日誌壓縮,做完快照之後快照會在穩定持久存儲中保存,而快照之前的日誌和快照就可以丟棄掉。

Raft的具體做法如下圖所示:

8.png

與Raft其它操作Leader-Based不同,snapshot是由各個節點獨立生成的。除了日誌壓縮這一個作用之外,snapshot還可以用於同步狀態:slow-follower以及new-server,Raft使用InstallSnapshot RPC完成該過程,不再贅述。

Client交互

  1. Client只向領導者發送請求;
  2. Client開始會向追隨者發送請求,追隨者拒絕Client的請求,並重定向到領導者;
  3. Client請求失敗,會超時重新發送請求;

Raft算法要求Client的請求線性化,防止請求被多次執行。有兩個解決方案:

  1. Raft算法提出要求每個請求有個唯一標識;
  2. Raft的請求保持冪等性;

   自增當前任期?當前任期結束,新的任期開始。

    當投票被瓜分後,所有的candidate同時超時,然後有可能進入新一輪的票數被瓜分,爲了避免這個問題。每個candidate的election timeout從150ms-300ms之間隨機取。這樣candidate發起新一輪的leader election的時間就會相同,誰的election timeout小誰成爲leader的機率就大。



發佈了21 篇原創文章 · 獲贊 2 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章