關於Raft算法的共識性算法考究

前言

Raft算法爲主從結構, 其分佈式一致性來源於集羣的寫全委託給LeaderLeader進程自身保證順序與一致性, 併發起投票要求Follower追加寫, 一旦過半贊成寫請求(同時附加寫的動作), 則該寫完成。
.
需要注意的是, 集羣的寫是線性一致性/強一致性的, 同時基於Follower轉發的集羣的讀也是現行一致性/強一致性的。並非ZAB的順序一致性

這兩天想到一個問題, raft算法的成員共識性問題。我之前的理解是:

Raft有共識性問題。 當未實現所有日誌提交的Follower,之後被選舉爲新的leader之後, 源於raft日誌的leader覆蓋規則, 將導致數據丟失。

↑↑上面這個想法是錯誤的↑↑Raft算法的安全性保證(阻止不包含最新Term和日誌編號的Follower成爲Leader、複製舊Leader數據)達成共識,確保了成員數據的一致性(相應的,ZAB使用主從相互拷貝的形式,達成集羣共識)。


關於Raft, 我對其做了一個Java版的實現, 地址在: https://github.com/srctar/raft。 歡迎閱讀。
目前實現了 raft 協議的下述功能:

  • 集羣選舉.
  • 數據一致性.
  • 集羣配置(集羣節點信息, 以及集羣的數目)更改.
  • 緊急提交.
  • 日誌壓縮.

Raft算法選舉

選舉流程參考網站:http://thesecretlivesofdata.com/raft/
本文的部分圖片以及理論基礎參考: https://blog.csdn.net/luoyhang003/article/details/61915666
如下Gif:

在這裏插入圖片描述
選舉主要注意兩點:

  1. 心跳超時(不管是初始態還是運行態);
  2. 只要當前機器尚未投票(包括自己), 就一定投票給申請投票者,同時重置心跳準備再次超時。

由於是多線程操作, 時序圖與流程圖皆不好畫, 請參閱文字:

Raft爲集羣狀態定義爲: ELECTION(選舉態), PROCESSING(運行態)
.
每個Raft節點有三個狀態:FOLLOWERLEADERCANDIDATE(選舉者)

  1. 獨立線程心跳超時(一般是100ms);
    a. 獨立線程可以位於FOLLOWER, 也可以位於剛啓動的集羣節點,還可以位於宕機、網絡中斷的節點。
    b. LEADER節點無該獨立線程(它負責給別的節點發心跳)。
    c. -
  2. 該線程休眠 150~300ms高於心跳超時時間100ms
    a.此操作非常重要,用以防止選票分散,進而導致長期超時
    b.休眠中的線程可以接受投票。
    c. -
  3. 投自己一票,並向集羣中的節點申請投票。
    a. 節點處於集羣選舉中ELECTION,且未給任何節點投票,節點默認接受投票申請。
    b. -
  4. 當某節點收到過半讚許,節點立馬轉化爲 LEADER。 關閉心跳線程, 同時給其它節點發送心跳。
    a. 節點處於運行態 PROCESSING, 且自身是LEADER顯然,一定有個老leader網斷了,然後又網好了。 只要對方的Term大於自己, 那自己立馬轉化爲FOLLOWER
    b. -
  5. 選舉態的節點收到心跳, 轉化爲FOLLOWER, 同時重設心跳線程。
    a. 注意, 節點處於選舉態 ELECTION, 需要心跳發送者的Term高於自己,否則返回拒絕(APPEND_ENTRIES_DENY)
    b. 節點處於運行態 PROCESSING, 需要匹配心跳者是否是集羣LEADER。是則重置心跳線程, 否則直接拒絕。
    c. -

如上選舉算法設計, 合理的確保下如下表格中的case, 能快速選上leader、且非過半宕機時,集羣可用:

Case 擔憂點 解決方案
正常啓動選Leader 選不上 重選/啓動時參與選舉有線程休眠時間150~300ms, 此時接受投票一定贊同,確保選舉
不過半的Follower宕機/失聯 可用性 可用, Leader不宕機,不影響選舉, 不過半宕機,不影響數據投票
過半Follower宕機 可用性 Leader不宕機,還能接受數據, 過半宕機,影響數據投票, 集羣不可用
不過半宕機, 包含Leader 可用性 可用, 心跳超時再選舉, 通常一輪就能選出新Leader,集羣正常服務
不過半宕機, 包含Leader 可用性 不可用, 選不出Leader
Leader失聯 集羣狀態 其他機器依舊能選上新Leader, 期序Term累加,舊Leader恢復之後接受心跳轉爲Follower
Leader宕機 集羣狀態 其他機器依舊能選上新Leader, 重啓之後接受心跳轉爲Follower

Raft算法數據一致性

此處講解的一致性, 分爲兩點:

  1. Raft 集羣正常運行態的數據一致性;
  2. Raft 集羣宕機恢復後的數據一致性。

正常運行態的強一致性

正常運行態, Raft的寫滿足強一致性/線性一致性在這裏插入圖片描述
但是讀只能滿足到順序一致性。


也是如上圖, 在最後一步, 如果客戶端讀到還沒有全部同步完畢的節點, 可能導致讀取到老舊的數據。
但是源於Raft的日誌式數據屬性, 客戶端不再會讀到更早的數據, 只會讀取到更新的數據, 因此滿足順序一致性

Raft集羣的數據共識(集羣恢復時)

本節講的是集羣某些機器宕機, 數據也沒有來得及同步的情況下, 集羣如何保證的數據一致性。
↓↓↓↓↓↓↓↓注意下面例子,Raft是解決了的, 實際並不存在↓↓↓↓↓↓↓↓

極端情況,新Leader上位,集羣狀態卻如下圖:

如上圖,相對於新的leader:

  1. a、b 丟失了部分數據
  2. c、d 多出來部分數據
  3. e、f 既丟失, 又多出來了數據

畢竟Raft的同步邏輯,過半提交則爲提交, 之後Leader一直重試保證數據一致。
像b, 網絡不佳,就是沒同步上;
像d, 它就是上一個leader,自身提交前,還沒來得及集羣同步,網斷了;

那類似這種情況, Raft集羣的數據共識是怎麼達成的呢? 如下方案:

  1. 選舉限制。 除了匹配Term外, 還匹配日誌版本, 大於等於自身日誌版本的投票纔會被授予。以此確保多數贊成的數據是最新的。
  2. 嘗試複製老舊Leader上已提交(過半贊成)的日誌,因爲已提交, 則至少當前被複制條目以及之前的日誌都是可以被提交的。

如上操作確保了只有持有最新日誌的節點才能成爲Leader, 且它將會嘗試複製老舊Leader的日誌數據。
此項操作通過排序和重發布確保數據的有序性, 但是會一定程度的增加系統複雜度。

Raft算法的其他集羣變更、日誌壓縮功能

這部分功能沒有實現, 具體可參閱 https://blog.csdn.net/luoyhang003/article/details/61915666

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