背景
一面在考查技識訓礎首先被問到過raft協議如何選主?主掛了選出的新主如何重新進行日志復制?
raft協議一直都是分布式系統一致性的難點,能講清楚很不容易,
下面我們就通過現場還原的方式講講該如何回答這兩個問題的,
現場還原
Q1面試官:那你先說一下raft協議是如何選主吧?
A1 我:為了保證資料一致性,最好的方式是唯一節點去讀,唯一節點去寫,這樣的資料肯定是一致的,但是分布式架構顯然不可能一個節點處理,因此raft提出在集群的所有節點中需要有一個節點來充當這個唯一節點,在一段時間內,只有這一個節點負責讀寫資料,然后其他節點同步資料,這個唯一的節點就叫leader節點,其他負責同步資料的節點叫follower節點,在集群中,還會有其他狀態的節點,例如candidate節點,這種節點只有在選主的時候才會涉及,所以三種角色定義如下:
1.跟隨者(follower):相當于普通群眾,默默地接收和處理來自領導者的訊息,當領導者心跳超時的時候,它就會主動站出來,推薦自己當候選人,
2.候選人(candidate):將向其它節點發送請求投票(RequestVote)RPC訊息,通知其他節點來投票,如果贏得了大多數選票,就晉升位領導者,
3.領導者(leader):不講道理的霸道總裁,平常的主要作業內容就是3部分,處理寫請求、管理日志復制和不斷地發送心跳資訊,通知其它結點“我是領導者,不要發起新的選舉”,
節點中的主選舉和現實生活中的選舉十分類似,就是投票,集群中獲票數最多的那個,就是leaderer節點,所以為防止出現平局,一般在部署節點的時候,會將節點個數設定為奇數(2n+1),
那么,這些節點該如何選舉呢?我們來看下面這個例子
在集群中,有三個節點A、B、C[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳

?
初始狀態下,所有節點都是follower,沒有leader,過了一段時間A變成了candidate開始發起選舉,憑啥A能變成candidate呢?因為如上圖可以看到,集群中每個節點都有一個election timeout,它表示選舉超時時間,每個節點等待leader節點心跳資訊的election timeout都是150ms~300ms的一個亂數,每當節點的election timeout到了就會觸發自己成為candidate,A的選舉超時時間先到了(150ms),它會最先因為沒有等到leader的心跳資訊發生超時,
在這里,只有candidate狀態的節點才可以競選成為leader,B、C這兩個follower是沒有資格變為leader的,除此以外,每個節點中還有一個欄位叫任期編號(term),這個term是一個全域的、連續遞增的整數,每進行一次選舉term值加1,如果candidate贏得選舉,它會稱為leader直到任期結束,此時A觸發了選舉,它就增加自己的term,并推舉自己為候選人,先給自己投上一票,然后向其他節點發送請求投票的RPC訊息,請它們選舉自己為領導者,

當B、C接收到A的請求投票RPC訊息后,B、C開始投票,此時只有A一個candidate,在term為1的這屆任期內目前也還沒有進行過投票,那么它將把選票投給節點A,并增加自己的term,

如果candidate在選舉超時時間內贏得了大多數選票,它將成為本屆任期內新的leaderer,節點A當選leader后,為了鞏固自己的“統治”,防止任期之間其它節點因為自身的election timeout而觸發選舉,它將周期性地發送RPC心跳資訊,B和C收到心跳訊息后,會重置election timeout,心跳檢測時間很短,要遠遠小于選舉超時時間election timeout,

B和C收到心跳資訊后,會發送心跳回應并重置election timeout,

假設A發送的心跳檢測資訊由于網路原因(延遲、丟包等)沒有傳送到B、C這兩個follower節點,B、C剛好election timeout則觸發自身選舉,此時C修改自身的任期編號term為2,自身狀態變為candidate,并且投了自身一票,發起選舉,

這時候C的任期值term設為2大于A的任期值,在Raft協議中但凡收到任期編號值大于自己的節點,都會更改自身節點的term值并切換為follower并重置自己的election timeout,因此,A直接變成follower,
此外,如果一個節點接收到一個包含較小的term值的請求,那么它會直接拒絕這個要求,舉個例子,假如節點C的term為4,當收到包含term為3的請求投票RPC訊息,那么節點C會拒絕這個訊息,
Q2面試官:回答得挺好,那么剛才你提到部署的時候節點數一般是奇數,那么現在就是偶數個節點怎么辦?
A2 我:假如現在變成了四個節點A、B、C、D,A和B同時進入了candidate狀態并開始發起選舉,如果A和B中任意一個獲得了超過半數以上的多數票則變為leader,如果它們兩個經過一次選舉后得到的票數相同或者都沒有超過半數則宣告選舉失敗并結束,等待A和B這兩個節點中任意一個節點的election timeout超時,然后發起新一輪選舉,A、B票數相同,則之后等待哪個先超時,假如A先超時,則A發起選舉,由于A的term顯然是最大的,則A會選為leader,
Q3面試官:那再講下一般是如何日志復制的呢?
A3我:raft除了可以實作一系列值的共識以外還能夠達成各節點日志一致,
副本是以日志的形式存在,日志由日志項組成,日志就好比是資料表,日志項(log entry)就好比是表里面的記錄,日志項是一種資料格式,它主要包括用戶指定的資料,也就是指令(command),此外還包含一些附加資訊,比如索引值,任期編號,如下圖所示

指令:客戶端請求指定的,狀態機需要執行的指令,
索引值:日志項對應的整數索引值,用來標識日志項,是一個連續的、單調遞增的整數號碼,
任期編號:創建這條日志項的leader的任期編號,
那么如何進行日志復制呢?我們舉個例子
- 首先,接收到客戶端的指令后,為該指令創建一個新日志項并追加到本地日志檔案中,

- 這里A作為leader,向B、C發送日志復制(Append Entries RPC)請求,這個RPC訊息是根據節點不同而訊息也不同的,

- 當B、C接收到訊息后,把命令成功寫入本地日志檔案后向A發送資訊,

-
A收到大多數follower的回復資訊后可以確定一個日志項被safely replicated了,將應用這條日志項到狀態機中,將執行結果回傳給客戶端,如果某個follower遇到例外情況(宕機或者網路丟包),則會一直給這個follower發送日志復制RPC請求,

-
A向B、C這兩個follower發送commit成功的通知

- B和C收到日志復制RPC訊息后,它們先commit自己的日志資料,然后再通知A自己已更新結束,

到此整個資料同步也就結束了,不過這是一個理想狀態下的日志復制程序,在實際環境中,復制日志的時候,你可能會遇到行程崩潰、服務器宕機等問題,這些問題會導致日志不一致,那么在這種情況下
每個節點都有兩個索引,一個是當前提交索引值commitIndex,一個是目前資料的最后一行索引值lastAppliedIndex,它表示最后一個應用到狀態機的log序號,
leader節點除了需要存盤自身節點的commitIndex和lastAppliedIndex之外,還需要知道每個follower的情況,因此,leader多了一張表,這張表記錄了所有follower 的存盤情況,表有兩個屬性,一個是nextIndex,每個follower維護一個nextIndex,表示leaderer給每一個follower發送的下一條日志項的索引,另一個是matchIndex記錄的是leaderer已知的follower節點的資料,
Q4面試官:換成新主后如何日志達到一致
A4我:首先,leader通過發送日志復制RPC的一致性檢查找到follower與自己相同日志項的最大索引值,
然后,leader強制復制follower更新覆寫的不一致日志項,
leader給follower發送日志復制資訊中帶著(PrevLogTerm, PrevLogEntry),PrevLogEntry表示當前復制日志項前一條的索引值,
lPrevLogTerm表示當前要復制的日志項前面一條的任期編號,
比如,下圖中leader將索引值為8的日志項發送給follower,那么PrevLogTerm值為4,PrevLogEntry為7,

-
leader通過日志復制RPC訊息發送當前日志項到follower,比如上圖PrevLogEntry值為7,PrevLogTerm值為4,
-
如果follower在它的日志中,找不到與PrevLogEntry為7,PrecvLogTerm值為4的日志項表示它和leader的日志檔案不一致了,那么follower拒絕接受新的日志項,并回傳失敗資訊給leader,
-
leader遞減要復制的日志項的索引值,并發送日志項到follower,既值為(6,3)的日志項,
-
如果follower在它的日志中找到了PrevLogEntry值為6,PrevLogTerm值為3的日志項,日志復制RPC回傳成功,這樣leader就知道在PrevLogEntry值為6,PrevLogTerm值為3的位置,follower和leader的日志項相同,
-
leader發送日志復制RPC訊息給follower,follower復制并覆寫該索引之后的日志項,最終實作了集群各節點日志的一致,
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/303637.html
標籤:其他
上一篇:2021ICPC網路賽第二場The 2021 ICPC Asia Regionals Online Contest (II) 【L Euler Function】
