當前位置:菜譜大全網 - 菜譜 - 共識算法:Raft

共識算法:Raft

第壹部分談到了拜占庭將軍的問題:當叛徒和信使可能被叛亂或暗殺時,許多拜占庭將軍如何達成壹致決定是否進攻?如果妳還不知道,可以看看上壹篇文章《拜占庭將軍問題》。本文主要介紹簡化的拜占庭通用問題的解決方案:Raft壹致性算法。

所以拜占庭將軍的問題是按照常見的工作問題來簡化的:假設將軍中沒有叛軍,信使的信息可靠但可能被暗殺,將軍們如何達成壹致的決定?

這個簡化的問題有很多解決方案。第壹個被證明的共識算法是Paxos,是拜占庭壹般問題的作者Leslie Lamport在1990年提出的。起初,它以高難度的論文而聞名。後來這家夥重新發了壹張2001做的簡單紙Paxos,還是挺難懂的。

由於Paxos難以理解和實現,斯坦福大學的壹位教授在2014發表了壹個新的分布式協議Raft。與Paxos相比,Raft的運行效率基本相當,但更容易理解,更容易用於系統開發。

讓我們用拜占庭將軍的例子來幫助理解Raft。

Raft的解決方案大概可以理解為先在所有將軍中選壹個將軍,所有的決定都由將軍來做。選舉:比如現在有A,B,C三個將軍,每個將軍都有隨機時間倒計時裝置。倒計時壹結束,這個將軍就會把自己當成將軍候選人,然後派使者去問其他將軍能不能選我當將軍。假設現在A將軍的倒計時已經結束,他派了壹個信使把投票的信息傳達給B將軍和C將軍,如果B將軍和C將軍還沒有把自己當成候選人(倒計時還沒有結束),還沒有投票給別人,那麽他們就投票給A將軍,當信使回到A將軍那裏的時候,A將軍就知道他已經得到了足夠的票數成為將軍。之後由將軍決定是否進攻,再派使者通知其他兩位將軍。如果過了壹段時間還沒收到回復(送信人可能被暗殺),那就再派壹個送信人,直到收到回復。

故事就講到這裏吧。希望不做技術的朋友大概能明白筏的原理。我們從比較技術的角度來說壹下Raft的原理。

從拜占庭將軍的故事到分布式系統,每個將軍相當於壹個分布式網絡節點,每個節點有三種狀態:追隨者、候選人、領導者,狀態之間相互轉化。詳情請參考下圖。

每個節點都有壹個選舉超時,時間隨機在150ms到300ms之間。有幾種情況會重置超時:

在救生筏運行期間,有兩個主要活動:

假設有五個節點,如圖5所示,所有五個節點的初始狀態都是Follower。

壹個節點的倒計時結束(超時)後,該節點的狀態變為Candidate開始選舉,並向其他幾個節點發送選舉請求Vote。

其他四個節點全部返回成功,這個節點的狀態從候選變為領導。經過壹小段時間後,向所有從節點發送壹個心跳,以保持所有節點的狀態,從節點在收到主節點的心跳後重置超時。

這是選擇領導者的最簡單的情況。只要超過半數的節點投票支持,候選人就會當選為領袖。在五個節點的情況下,三個節點(包括候選節點本身)就可以了。

壹開始已經有壹個領導了,所有節點運行正常。

領導者失敗並掛斷,其他四個追隨者將重新選舉領導者。

四個節點的選擇過程與五個節點的選擇過程相似。選擇新引線後,原始引線將恢復並重新連接。這時候我該怎麽辦?在Raft中,記錄了第壹輪選舉。重新加入的領袖在第壹輪選舉($ Term 1)中當選,但現在的領袖是$ Term 2,所有原來的領袖都會有意識地降級為追隨者。

假設壹開始有四個節點,都還是Follower。

有兩個關註者同時超時,都成為候選人開始選舉,分別向壹個關註者發送投票請求。

兩個跟隨者分別平安歸來。此時,兩位候選人都只有2票,需要3票才能當選領袖。

兩個候選人將向另壹個沒有投票給自己的追隨者發送投票請求。

然而,由於追隨者已經在這壹輪選舉中投票,他們都拒絕了他們的請求。所以在$ Term 2中沒有選擇領導者。

此時,兩個節點的狀態是候選,兩個是跟隨者,但他們的倒計時定時器仍在運行,超時第壹的節點將投票啟動新壹輪的$ Term 3。

兩個追隨者還沒有在$ Term 3中投票,所以他們回到OK。此時,候選人有三票,被選為領導者。

如果領導者心跳的時間晚於另壹個候選人超時的時間,則另壹個候選人仍將發送選舉請求。

兩位追隨者已經完成投票,並拒絕了該候選人的投票請求。

領導發出心跳,候選人收到後,狀態自動變為跟隨者,完成領導的選擇。

以上是木筏最重要的活動之壹的介紹,以及不同情況下如何選擇主活動。

Raft在實際應用場景中的壹致性更多的體現在不同節點之間的數據壹致性上。當客戶端向任何節點發送請求時,它都可以收到壹致的返回。當壹個節點出現故障時,其他節點仍然可以使用現有數據正常運行。選擇主服務器後復制日誌就是為了實現這個目標。

起初,領導者和兩個追隨者都沒有任何數據。

客戶端向領導者發送請求以存儲數據“sally ”,領導者首先將數據寫入本地日誌。此時,數據仍未提交(尚未確認,以紅色表示)。

領導者向兩個追隨者發送AppendEntries請求。如果跟隨者上的數據之間沒有沖突,那麽數據會被臨時寫入本地日誌,跟隨者的數據仍然是未提交的。

Follower在本地寫入數據並返回OK。領導收到後成功返回。只要收到的成功返回的數量超過壹半(包括領導者),領導者就將數據“sally”的狀態更改為Committed。(這時,領導可以回到客戶端。)

領導者再次向追隨者發送AppendEntries請求。收到請求後,跟隨者將本地日誌中未提交的數據更改為已提交。這樣就完成了整個復制日誌的過程,三個節點的數據是壹致的。

在網絡分區的情況下,部分節點無法相互通信,Raft在這種情況下也能保證數據的壹致性。

起初,五個節點處於相同的網絡狀態。

網絡分區把節點分成兩邊,壹邊兩個節點,另壹邊三個節點。

這兩個節點在這裏已經有了壹個Leader,來自客戶端的數據“bob”通過Leader同步到了跟隨者。

因為只有兩個節點,少於三個節點,“bob”的狀態仍然是未提交的。所以在這裏,服務器將向客戶端返回壹個錯誤。

另壹個分區有三個節點,因此重新選擇主分區。客戶端數據“tom”被發送到新的領導者,並通過類似於先前網絡狀態中的過程被同步到其他兩個追隨者。

因為這個分區有三個節點,超過壹半,數據“tom”已經提交。

網絡狀態恢復,五個節點再次處於相同的網絡狀態。但是“鮑勃”和“湯姆”存在數據沖突。

三個節點的領導者廣播AppendEntries。

兩個節點的分區的Leader自動降級為Follower,因為這個分區的數據“bob”沒有提交,錯誤返回給客戶端。客戶機知道請求不成功,所以當收到AppendEntries請求時,跟隨者可以刪除“bob”。然後同步“tom”,通過這樣的過程,完成網絡分區情況下的復制日誌,保證了數據的壹致性。

Raft是壹種可以在分布式系統中實現強壹致性的算法。每個系統節點有三種狀態:追隨者、候選人和領導者。實現Raft算法最重要的兩件事是:選主和復制日誌。

參考鏈接:

Raft官網:/raft/

我本來不想壹張壹張地貼圖,但是家裏無法訪問這個鏈接,就幹脆把整個過程重復了壹遍。)