【翻譯】Raft 共識演演算法:叢整合員變更

2022-10-15 18:00:50

轉載請註明出處:https://www.cnblogs.com/morningli/p/16770129.html

之前都在叢集設定是固定的(參與共識演演算法的server集合)假設下討論raft。在實踐中,偶爾有需要改變設定,比如說當server故障時替換server,或者改變複製級別。雖然可以通過下線整個叢集,更新組態檔,重啟叢集來實現,但是這樣會導致叢集在改變的過程中一直不可用。另外,人工操作存在操作錯誤的風險。為了避免這樣的問題,raft通過自動化設定變更並將它包含到raft共識演演算法中。

為了保證設定變更機制是安全的,必須保證不存在轉換過程中有兩個leader在同一個term內被選舉出來。不幸的是,server直接從老設定轉換到新設定的任何方法都是不安全的。不可能自動一下子自動切換所有的server,所以叢集在轉換期間存在分裂成兩個獨立的大多數的可能性(見 Figure 10)。

為了保證安全性,設定變更必須使用兩階段方法。有不同的方式來實現兩階段。舉個例子,一些系統使用第一階段禁用老的設定,這樣系統無法處理使用者端請求;然後第二階段啟用新的設定。在raft叢集首先切換到一個過度的設定,稱為joint consensus;一旦joint consensus被提交,系統切換到新的設定。joint consensus結合了新老設定:

  • 紀錄檔記錄複製到新老設定的所有server
  • 兩個設定中任何一個server都可以作為leader
  • 達成一致(針對選舉和提交)需要分別在兩種設定上獲得大多數的支援。

joint consensus允許各個伺服器在不同時間在設定之間進行轉換,而不會影響安全性。此外,joint consensus允許叢集在整個設定更改期間繼續為使用者端請求提供服務。

叢集設定通過複製的紀錄檔中的特殊記錄來儲存和交流;Figure 11介紹了設定變更過程。當leader接收到一個將設定從Cold修改為Cnew的請求時,它會為joint consensus (圖中的Cold,new)將這個設定儲存成一個紀錄檔記錄並複製這個記錄。一旦一個server將這個新的設定記錄新增到它的紀錄檔裡,它以後的決定都會使用這個設定(server總會使用紀錄檔中最新的設定,無論這個設定是否提交)。這意味著leader將會使用Cold,new的規則來決定Cold,new這個記錄什麼時候是committed的。如果leader崩潰了,一個新的leader有可能包含設定Cold或者Cold,new,取決於取勝的candidate有沒有收到Cold,new。在這個期間,任何情況Cnew不能單方面做決定。

一旦Cold,new已經被提交,Cold或者Cnew都不能在沒有得到對方同意的情況下做決定的,Leader Completeness Property保證了只有包含Cold,new的記錄的server會被選為leader。leader這是建立一個Cnew的紀錄檔並複製到叢集中是安全的。這個設定會在server接收到後立馬生效。當新的設定在Cnew的規則下被提交時,老的設定已經不重要了,不在新設定中的server可以被關停。如Figure 11所示,不存在Cold和Cnew單方面做決定的時候。這保證了安全性。

設定變更還有三個問題需要解決。第一個問題是新的server剛開始不會儲存任何紀錄檔。如果新server被新增到叢集,它們跟上紀錄檔需要一些時間,這段時間內不能提交新的紀錄檔記錄。為了避免這種可用性的間隔時間,raft在更新設定之前引入了額外的步驟,新加入叢集的server作為一個 non-voting 成員(leader複製記錄給它們,但是在大多數投票時不會將它考慮進來)。一旦這個新server追上叢集中其他server的進度,設定更新像上面描述的過程一樣。

第二個問題是叢集leader可能不屬於新設定中的成員。這種情況,leader提交了Cnew後立馬下臺(變回follower狀態)。這表示會有一段時間(正在提交Cnew)leader會管理一個不包含自己的叢集;它複製紀錄檔記錄但是在計算大多數時不會把自己考慮進去。在Cnew被提交的時候變更leader是因為這是新設定可以獨立執行的最早的時間點(新的leader肯定會包含Cnew)。在這個點之前,有可能選出一個包含Cold設定的leader。

第三個問題是移除server(不在Cnew)會擾亂叢集。這些server不會受到心跳,所以它們會超時並開始新的投票。它們會使用新的term傳送RequestVote RPCs ,這會導致當前的leader轉換到follower狀態。最終會選出一個新的leader,但是已經移除的server會再次超時,上面的過程會重複傳送,影響了可用性。

為了避免這樣的問題,server在確認當前leader存在時,會忽略RequestVote RPCs。確切的來說,如果server在最小選舉超時時間內收到一個來自當前leader的 RequestVote RPC ,它不會更新它的term或者投票。這不會影響正常的選舉,每個server在開始選舉之前都至少會等待一個最小選舉超時時間。然而,這避免了來自移除節點的干擾:如果一個leader可以傳送心跳到叢集中,它不會被更大的term罷免。


參考:
https://github.com/maemual/raft-zh_cn