尋找一種易於理解的一致性算法(擴展版)下

本文首發於深刻淺出區塊鏈社區 原文連接:尋找一種易於理解的一致性算法(擴展版)原文已更新,請讀者前往原文閱讀算法

6 集羣成員變化

到目前爲止,咱們都假設集羣的配置(加入到一致性算法的服務器集合)是固定不變的。可是在實踐中,偶爾是會改變集羣的配置的,例如替換那些宕機的機器或者改變複製級別。儘管能夠經過暫停整個集羣,更新全部配置,而後重啓整個集羣的方式來實現,可是在更改的時候集羣會不可用。另外,若是存在手工操做步驟,那麼就會有操做失誤的風險。爲了不這樣的問題,咱們決定自動化配置改變而且將其歸入到 Raft 一致性算法中來。安全

爲了讓配置修改機制可以安全,那麼在轉換的過程當中不可以存在任什麼時候間點使得兩個領導人同時被選舉成功在同一個任期裏。不幸的是,任何服務器直接從舊的配置直接轉換到新的配置的方案都是不安全的。一次性自動的轉換全部服務器是不可能的,因此在轉換期間整個集羣存在劃分紅兩個獨立的大多數羣體的可能性(見圖 10)。性能優化

圖 10

圖 10:直接從一種配置轉到新的配置是十分不安全的,由於各個機器可能在任何的時候進行轉換。在這個例子中,集羣配額從 3 臺機器變成了 5 臺。不幸的是,存在這樣的一個時間點,兩個不一樣的領導人在同一個任期裏均可以被選舉成功。一個是經過舊的配置,一個經過新的配置。服務器

爲了保證安全性,配置更改必須使用兩階段方法。目前有不少種兩階段的實現。例如,有些系統在第一階段停掉舊的配置因此集羣就不能處理客戶端請求;而後在第二階段在啓用新的配置。在 Raft 中,集羣先切換到一個過渡的配置,咱們稱之爲共同一致;一旦共同一致已經被提交了,那麼系統就切換到新的配置上。共同一致是老配置和新配置的結合:網絡

  • 日誌條目被複制給集羣中新、老配置的全部服務器。
  • 新、舊配置的服務器均可以成爲領導人。
  • 達成一致(針對選舉和提交)須要分別在兩種配置上得到大多數的支持。

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

集羣配置在複製日誌中以特殊的日誌條目來存儲和通訊;圖 11 展現了配置轉換的過程。當一個領導人接收到一個改變配置從 C-old 到 C-new 的請求,他會爲了共同一致存儲配置(圖中的 C-old,new),之前面描述的日誌條目和副本的形式。一旦一個服務器將新的配置日誌條目增長到它的日誌中,他就會用這個配置來作出將來全部的決定(服務器老是使用最新的配置,不管他是否已經被提交)。這意味着領導人要使用 C-old,new 的規則來決定日誌條目 C-old,new 何時須要被提交。若是領導人崩潰了,被選出來的新領導人多是使用 C-old 配置也多是 C-old,new 配置,這取決於贏得選舉的候選人是否已經接收到了 C-old,new 配置。在任何狀況下, C-new 配置在這一時期都不會單方面的作出決定。併發

一旦 C-old,new 被提交,那麼不管是 C-old 仍是 C-new,在沒有通過他人批准的狀況下都不可能作出決定,而且領導人徹底特性保證了只有擁有 C-old,new 日誌條目的服務器纔有可能被選舉爲領導人。這個時候,領導人建立一條關於 C-new 配置的日誌條目並複製給集羣就是安全的了。再者,每一個服務器在見到新的配置的時候就會當即生效。當新的配置在 C-new 的規則下被提交,舊的配置就變得可有可無,同時不使用新的配置的服務器就能夠被關閉了。如圖 11,C-old 和 C-new 沒有任何機會同時作出單方面的決定;這保證了安全性。負載均衡

圖 11

圖 11:一個配置切換的時間線。虛線表示已經被建立可是尚未被提交的條目,實線表示最後被提交的日誌條目。領導人首先建立了 C-old,new 的配置條目在本身的日誌中,並提交到 C-old,new 中(C-old 的大多數和 C-new 的大多數)。而後他建立 C-new 條目並提交到 C-new 中的大多數。這樣就不存在 C-new 和 C-old 能夠同時作出決定的時間點。分佈式

在關於從新配置還有三個問題須要提出。第一個問題是,新的服務器可能初始化沒有存儲任何的日誌條目。當這些服務器以這種狀態加入到集羣中,那麼他們須要一段時間來更新追趕,這時還不能提交新的日誌條目。爲了不這種可用性的間隔時間,Raft 在配置更新的時候使用了一種額外的階段,在這個階段,新的服務器以沒有投票權身份加入到集羣中來(領導人複製日誌給他們,可是不考慮他們是大多數)。一旦新的服務器追遇上了集羣中的其餘機器,從新配置能夠像上面描述的同樣處理。函數

第二個問題是,集羣的領導人可能不是新配置的一員。在這種狀況下,領導人就會在提交了 C-new 日誌以後退位(回到跟隨者狀態)。這意味着有這樣的一段時間,領導人管理着集羣,可是不包括他本身;他複製日誌可是不把他本身算做是大多數之一。當 C-new 被提交時,會發生領導人過渡,由於這時是最先新的配置能夠獨立工做的時間點(將老是可以在 C-new 配置下選出新的領導人)。在此以前,可能只能從 C-old 中選出領導人。

第三個問題是,移除不在 C-new 中的服務器可能會擾亂集羣。這些服務器將不會再接收到心跳,因此當選舉超時,他們就會進行新的選舉過程。他們會發送擁有新的任期號的請求投票 RPCs,這樣會致使當前的領導人回退成跟隨者狀態。新的領導人最終會被選出來,可是被移除的服務器將會再次超時,而後這個過程會再次重複,致使總體可用性大幅下降。

爲了不這個問題,當服務器確認當前領導人存在時,服務器會忽略請求投票 RPCs。特別的,當服務器在當前最小選舉超時時間內收到一個請求投票 RPC,他不會更新當前的任期號或者投出選票。這不會影響正常的選舉,每一個服務器在開始一次選舉以前,至少等待一個最小選舉超時時間。然而,這有利於避免被移除的服務器擾亂:若是領導人可以發送心跳給集羣,那麼他就不會被更大的任期號廢黜。

7 日誌壓縮

Raft 的日誌在正常操做中不斷的增加,可是在實際的系統中,日誌不能無限制的增加。隨着日誌不斷增加,他會佔用愈來愈多的空間,花費愈來愈多的時間來重置。若是沒有必定的機制去清除日誌裏積累的陳舊的信息,那麼會帶來可用性問題。

快照是最簡單的壓縮方法。在快照系統中,整個系統的狀態都以快照的形式寫入到穩定的持久化存儲中,而後到那個時間點以前的日誌所有丟棄。快照技術被使用在 Chubby 和 ZooKeeper 中,接下來的章節會介紹 Raft 中的快照技術。

增量壓縮的方法,例如日誌清理或者日誌結構合併樹,都是可行的。這些方法每次只對一小部分數據進行操做,這樣就分散了壓縮的負載壓力。首先,他們先選擇一個已經積累的大量已經被刪除或者被覆蓋對象的區域,而後重寫那個區域還活躍的對象,以後釋放那個區域。和簡單操做整個數據集合的快照相比,須要增長複雜的機制來實現。狀態機能夠實現 LSM tree 使用和快照相同的接口,可是日誌清除方法就須要修改 Raft 了。

圖 12

圖 12:一個服務器用新的快照替換了從 1 到 5 的條目,快照值存儲了當前的狀態。快照中包含了最後的索引位置和任期號。

圖 12 展現了 Raft 中快照的基礎思想。每一個服務器獨立的建立快照,只包括已經被提交的日誌。主要的工做包括將狀態機的狀態寫入到快照中。Raft 也包含一些少許的元數據到快照中:最後被包含索引指的是被快照取代的最後的條目在日誌中的索引值(狀態機最後應用的日誌),最後被包含的任期指的是該條目的任期號。保留這些數據是爲了支持快照後緊接着的第一個條目的附加日誌請求時的一致性檢查,由於這個條目須要前一日誌條目的索引值和任期號。爲了支持集羣成員更新(第 6 節),快照中也將最後的一次配置做爲最後一個條目存下來。一旦服務器完成一次快照,他就能夠刪除最後索引位置以前的全部日誌和快照了。

儘管一般服務器都是獨立的建立快照,可是領導人必須偶爾的發送快照給一些落後的跟隨者。這一般發生在當領導人已經丟棄了下一條須要發送給跟隨者的日誌條目的時候。幸運的是這種狀況不是常規操做:一個與領導人保持同步的跟隨者一般都會有這個條目。然而一個運行很是緩慢的跟隨者或者新加入集羣的服務器(第 6 節)將不會有這個條目。這時讓這個跟隨者更新到最新的狀態的方式就是經過網絡把快照發送給他們。

安裝快照 RPC

由領導人調用以將快照的分塊發送給跟隨者。領導者老是按順序發送分塊。

參數 解釋
term 領導人的任期號
leaderId 領導人的 Id,以便於跟隨者重定向請求
lastIncludedIndex 快照中包含的最後日誌條目的索引值
lastIncludedTerm 快照中包含的最後日誌條目的任期號
offset 分塊在快照中的字節偏移量
data[] 原始數據
done 若是這是最後一個分塊則爲 true
結果 解釋
term 當前任期號(currentTerm),便於領導人更新本身

接收者實現

  1. 若是term < currentTerm就當即回覆
  2. 若是是第一個分塊(offset 爲 0)就建立一個新的快照
  3. 在指定偏移量寫入數據
  4. 若是 done 是 false,則繼續等待更多的數據
  5. 保存快照文件,丟棄具備較小索引的任何現有或部分快照
  6. 若是現存的日誌條目與快照中最後包含的日誌條目具備相同的索引值和任期號,則保留其後的日誌條目並進行回覆
  7. 丟棄整個日誌
  8. 使用快照重置狀態機(並加載快照的集羣配置)

圖 13

圖 13:一個關於安裝快照的簡要概述。爲了便於傳輸,快照都是被分紅分塊的;每一個分塊都給了跟隨者生命的跡象,因此跟隨者能夠重置選舉超時計時器。

在這種狀況下領導人使用一種叫作安裝快照的新的 RPC 來發送快照給太落後的跟隨者;見圖 13。當跟隨者經過這種 RPC 接收到快照時,他必須本身決定對於已經存在的日誌該如何處理。一般快照會包含沒有在接收者日誌中存在的信息。在這種狀況下,跟隨者丟棄其整個日誌;它所有被快照取代,而且可能包含與快照衝突的未提交條目。若是接收到的快照是本身日誌的前面部分(因爲網絡重傳或者錯誤),那麼被快照包含的條目將會被所有刪除,可是快照後面的條目仍然有效,必須保留。

這種快照的方式背離了 Raft 的強領導人原則,由於跟隨者能夠在不知道領導人狀況下建立快照。可是咱們認爲這種背離是值得的。領導人的存在,是爲了解決在達成一致性的時候的衝突,可是在建立快照的時候,一致性已經達成,這時不存在衝突了,因此沒有領導人也是能夠的。數據依然是從領導人傳給跟隨者,只是跟隨者能夠從新組織他們的數據了。

咱們考慮過一種替代的基於領導人的快照方案,即只有領導人建立快照,而後發送給全部的跟隨者。可是這樣作有兩個缺點。第一,發送快照會浪費網絡帶寬而且延緩了快照處理的時間。每一個跟隨者都已經擁有了全部產生快照須要的信息,並且很顯然,本身從本地的狀態中建立快照比經過網絡接收別人發來的要經濟。第二,領導人的實現會更加複雜。例如,領導人須要發送快照的同時並行的將新的日誌條目發送給跟隨者,這樣纔不會阻塞新的客戶端請求。

還有兩個問題影響了快照的性能。首先,服務器必須決定何時應該建立快照。若是快照建立的過於頻繁,那麼就會浪費大量的磁盤帶寬和其餘資源;若是建立快照頻率過低,他就要承受耗盡存儲容量的風險,同時也增長了從日誌重建的時間。一個簡單的策略就是當日志大小達到一個固定大小的時候就建立一次快照。若是這個閾值設置的顯著大於指望的快照的大小,那麼快照對磁盤壓力的影響就會很小了。

第二個影響性能的問題就是寫入快照須要花費顯著的一段時間,而且咱們還不但願影響到正常操做。解決方案是經過寫時複製的技術,這樣新的更新就能夠被接收而不影響到快照。例如,具備函數式數據結構的狀態機自然支持這樣的功能。另外,操做系統的寫時複製技術的支持(如 Linux 上的 fork)能夠被用來建立完整的狀態機的內存快照(咱們的實現就是這樣的)。

8 客戶端交互

這一節將介紹客戶端是如何和 Raft 進行交互的,包括客戶端如何發現領導人和 Raft 是如何支持線性化語義的。這些問題對於全部基於一致性的系統都存在,而且 Raft 的解決方案和其餘的也差很少。

Raft 中的客戶端發送全部請求給領導人。當客戶端啓動的時候,他會隨機挑選一個服務器進行通訊。若是客戶端第一次挑選的服務器不是領導人,那麼那個服務器會拒絕客戶端的請求而且提供他最近接收到的領導人的信息(附加條目請求包含了領導人的網絡地址)。若是領導人已經崩潰了,那麼客戶端的請求就會超時;客戶端以後會再次重試隨機挑選服務器的過程。

咱們 Raft 的目標是要實現線性化語義(每一次操做當即執行,只執行一次,在他調用和收到回覆之間)。可是,如上述,Raft 是能夠執行同一條命令屢次的:例如,若是領導人在提交了這條日誌以後,可是在響應客戶端以前崩潰了,那麼客戶端會和新的領導人重試這條指令,致使這條命令就被再次執行了。解決方案就是客戶端對於每一條指令都賦予一個惟一的序列號。而後,狀態機跟蹤每條指令最新的序列號和相應的響應。若是接收到一條指令,它的序列號已經被執行了,那麼就當即返回結果,而不從新執行指令。

只讀的操做能夠直接處理而不須要記錄日誌。可是,在不增長任何限制的狀況下,這麼作可能會冒着返回髒數據的風險,由於領導人響應客戶端請求時可能已經被新的領導人做廢了,可是他還不知道。線性化的讀操做必須不能返回髒數據,Raft 須要使用兩個額外的措施在不使用日誌的狀況下保證這一點。首先,領導人必須有關於被提交日誌的最新信息。領導人徹底特性保證了領導人必定擁有全部已經被提交的日誌條目,可是在他任期開始的時候,他可能不知道那些是已經被提交的。爲了知道這些信息,他須要在他的任期裏提交一條日誌條目。Raft 中經過領導人在任期開始的時候提交一個空白的沒有任何操做的日誌條目到日誌中去來實現。第二,領導人在處理只讀的請求以前必須檢查本身是否已經被廢黜了(他本身的信息已經變髒了若是一個更新的領導人被選舉出來)。Raft 中經過讓領導人在響應只讀請求以前,先和集羣中的大多數節點交換一次心跳信息來處理這個問題。可選的,領導人能夠依賴心跳機制來實現一種租約的機制,可是這種方法依賴時間來保證安全性(假設時間偏差是有界的)。

9 算法實現和評估

咱們已經爲 RAMCloud 實現了 Raft 算法做爲存儲配置信息的複製狀態機的一部分,而且幫助 RAMCloud 協調故障轉移。這個 Raft 實現包含大約 2000 行 C++ 代碼,其中不包括測試、註釋和空行。這些代碼是開源的。同時也有大約 25 個其餘獨立的第三方的基於這篇論文草稿的開源實現,針對不一樣的開發場景。同時,不少公司已經部署了基於 Raft 的系統。

這一節會從三個方面來評估 Raft 算法:可理解性、正確性和性能。

9.1 可理解性

爲了和 Paxos 比較 Raft 算法的可理解能力,咱們針對高層次的本科生和研究生,在斯坦福大學的高級操做系統課程和加州大學伯克利分校的分佈式計算課程上,進行了一次學習的實驗。咱們分別拍了針對 Raft 和 Paxos 的視頻課程,並準備了相應的小測驗。Raft 的視頻講課覆蓋了這篇論文的全部內容除了日誌壓縮;Paxos 講課包含了足夠的資料來建立一個等價的複製狀態機,包括單決策 Paxos,多決策 Paxos,從新配置和一些實際系統須要的性能優化(例如領導人選舉)。小測驗測試一些對算法的基本理解和解釋一些邊角的示例。每一個學生都是看完第一個視頻,回答相應的測試,再看第二個視頻,回答相應的測試。大約有一半的學生先進行 Paxos 部分,而後另外一半先進行 Raft 部分,這是爲了說明二者從第一部分的算法學習中得到的表現和經驗的差別。咱們計算參加人員的每個小測驗的得分來看參與者是否在 Raft 算法上更加容易理解。

咱們儘量的使得 Paxos 和 Raft 的比較更加公平。這個實驗偏心 Paxos 表如今兩個方面:43 個參加者中有 15 我的在以前有一些 Paxos 的經驗,而且 Paxos 的視頻要長 14%。如表格 1 總結的那樣,咱們採起了一些措施來減輕這種潛在的偏見。咱們全部的材料均可供審查。

關心 緩和偏見採起的手段 可供查看的材料
相同的講課質量 二者使用同一個講師。Paxos 使用的是如今不少大學裏常用的。Paxos 會長 14%。 視頻
相同的測驗難度 問題以難度分組,在兩個測驗裏成對出現。 小測驗
公平評分 使用評價量規。隨機順序打分,兩個測驗交替進行。 評價量規(rubric)

表 1:考慮到可能會存在的偏見,對於每種狀況的解決方法,和相應的材料。

參加者平均在 Raft 的測驗中比 Paxos 高 4.9 分(總分 60,那麼 Raft 的平均得分是 25.7,而 Paxos 是 20.8);圖 14 展現了每一個參與者的得分。配置t-檢驗(又稱student‘s t-test)代表,在 95% 的可信度下,真實的 Raft 分數分佈至少比 Paxos 高 2.5 分。

圖 14

圖 14:一個散點圖表示了 43 個學生在 Paxos 和 Raft 的小測驗中的成績。在對角線之上的點表示在 Raft 得到了更高分數的學生。

咱們也創建了一個線性迴歸模型來預測一個新的學生的測驗成績,基於如下三個因素:他們使用的是哪一個小測驗,以前對 Paxos 的經驗,和學習算法的順序。模型預測,對小測驗的選擇會產生 12.5 分的差異。這顯著的高於以前的 4.9 分,由於不少學生在以前都已經有了對於 Paxos 的經驗,這至關明顯的幫助 Paxos,對 Raft 就沒什麼太大影響了。可是奇怪的是,模型預測對於先進行 Paxos 小測驗的人而言,Raft的得分低了6.3分; 雖然咱們不知道爲何,這彷佛在統計上是有意義的。

咱們同時也在測驗以後調查了參與者,他們認爲哪一個算法更加容易實現和解釋;這個的結果在圖 15 上。壓倒性的結果代表 Raft 算法更加容易實現和解釋(41 人中的 33個)。可是,這種本身報告的結果不如參與者的成績更加可信,而且參與者可能由於咱們的 Raft 更加易於理解的假說而產生偏見。

圖 15

圖 15:經過一個 5 分制的問題,參與者(左邊)被問哪一個算法他們以爲在一個高效正確的系統裏更容易實現,右邊被問哪一個更容易向學生解釋。

關於 Raft 用戶學習有一個更加詳細的討論。

9.2 正確性

在第 5 節,咱們已經制定了正式的規範,和對一致性機制的安全性證實。這個正式規範使用 TLA+ 規範語言使圖 2 中總結的信息很是清晰。它長約400行,並做爲證實的主題。同時對於任何想實現 Raft 的人也是十分有用的。咱們經過 TLA 證實系統很是機械的證實了日誌徹底特性。然而,這個證實依賴的約束前提尚未被機械證實(例如,咱們尚未證實規範的類型安全)。並且,咱們已經寫了一個非正式的證實關於狀態機安全性是完備的,而且是至關清晰的(大約 3500 個詞)。

9.3 性能

Raft 和其餘一致性算法例如 Paxos 有着差很少的性能。在性能方面,最重要的關注點是,當領導人被選舉成功時,何時複製新的日誌條目。Raft 經過不多數量的消息包(一輪從領導人到集羣大多數機器的消息)就達成了這個目的。同時,進一步提高 Raft 的性能也是可行的。例如,很容易經過支持批量操做和管道操做來提升吞吐量和下降延遲。對於其餘一致性算法已經提出過不少性能優化方案;其中有不少也能夠應用到 Raft 中來,可是咱們暫時把這個問題放到將來的工做中去。

咱們使用咱們本身的 Raft 實現來衡量 Raft 領導人選舉的性能而且回答兩個問題。首先,領導人選舉的過程收斂是否快速?第二,在領導人宕機以後,最小的系統宕機時間是多久?

圖 16

圖 16:發現並替換一個已經崩潰的領導人的時間。上面的圖考察了在選舉超時時間上的隨機化程度,下面的圖考察了最小選舉超時時間。每條線表明了 1000 次實驗(除了 150-150 毫秒只試了 100 次),和相應的肯定的選舉超時時間。例如,150-155 毫秒意思是,選舉超時時間從這個區間範圍內隨機選擇並肯定下來。這個實驗在一個擁有 5 個節點的集羣上進行,其廣播時延大約是 15 毫秒。對於 9 個節點的集羣,結果也差很少。

爲了衡量領導人選舉,咱們反覆的使一個擁有五個節點的服務器集羣的領導人宕機,並計算須要多久才能發現領導人已經宕機並選出一個新的領導人(見圖 16)。爲了構建一個最壞的場景,在每一的嘗試裏,服務器都有不一樣長度的日誌,意味着有些候選人是沒有成爲領導人的資格的。另外,爲了促成選票瓜分的狀況,咱們的測試腳本在終止領導人以前同步的發送了一次心跳廣播(這大約和領導人在崩潰前複製一個新的日誌給其餘機器很像)。領導人均勻的隨機的在心跳間隔裏宕機,也就是最小選舉超時時間的一半。所以,最小宕機時間大約就是最小選舉超時時間的一半。

圖 16 中上面的圖代表,只須要在選舉超時時間上使用不多的隨機化就能夠大大避免選票被瓜分的狀況。在沒有隨機化的狀況下,在咱們的測試裏,選舉過程每每都須要花費超過 10 秒鐘因爲太多的選票瓜分的狀況。僅僅增長 5 毫秒的隨機化時間,就大大的改善了選舉過程,如今平均的宕機時間只有 287 毫秒。增長更多的隨機化時間能夠大大改善最壞狀況:經過增長 50 毫秒的隨機化時間,最壞的完成狀況(1000 次嘗試)只要 513 毫秒。

圖 16 中下面的圖顯示,經過減小選舉超時時間能夠減小系統的宕機時間。在選舉超時時間爲 12-24 毫秒的狀況下,只須要平均 35 毫秒就能夠選舉出新的領導人(最長的一次花費了 152 毫秒)。然而,進一步下降選舉超時時間的話就會違反 Raft 的時間不等式需求:在選舉新領導人以前,領導人就很難發送完心跳包。這會致使沒有意義的領導人改變並下降了系統總體的可用性。咱們建議使用更爲保守的選舉超時時間,好比 150-300 毫秒;這樣的時間不大可能致使沒有意義的領導人改變,並且依然提供不錯的可用性。

10 相關工做

已經有不少關於一致性算法的工做被髮表出來,其中不少均可以歸到下面的類別中:

  • Lamport 關於 Paxos 的原始描述,和嘗試描述的更清晰。
  • 關於 Paxos 的更詳盡的描述,補充遺漏的細節並修改算法,使得能夠提供更加容易的實現基礎。
  • 實現一致性算法的系統,例如 Chubby,ZooKeeper 和 Spanner。對於 Chubby 和 Spanner 的算法並無公開發表其技術細節,儘管他們都聲稱是基於 Paxos 的。ZooKeeper 的算法細節已經發表,可是和 Paxos 着實有着很大的差異。
  • Paxos 能夠應用的性能優化。
  • Oki 和 Liskov 的 Viewstamped Replication(VR),一種和 Paxos 差很少的替代算法。原始的算法描述和分佈式傳輸協議耦合在了一塊兒,可是核心的一致性算法在最近的更新裏被分離了出來。VR 使用了一種基於領導人的方法,和 Raft 有不少類似之處。

Raft 和 Paxos 最大的不一樣之處就在於 Raft 的強領導特性:Raft 使用領導人選舉做爲一致性協議裏必不可少的部分,而且將盡量多的功能集中到了領導人身上。這樣就可使得算法更加容易理解。例如,在 Paxos 中,領導人選舉和基本的一致性協議是正交的:領導人選舉僅僅是性能優化的手段,並且不是一致性所必需要求的。可是,這樣就增長了多餘的機制:Paxos 同時包含了針對基本一致性要求的兩階段提交協議和針對領導人選舉的獨立的機制。相比較而言,Raft 就直接將領導人選舉歸入到一致性算法中,並做爲兩階段一致性的第一步。這樣就減小了不少機制。

像 Raft 同樣,VR 和 ZooKeeper 也是基於領導人的,所以他們也擁有一些 Raft 的優勢。可是,Raft 比 VR 和 ZooKeeper 擁有更少的機制由於 Raft 儘量的減小了非領導人的功能。例如,Raft 中日誌條目都遵循着從領導人發送給其餘人這一個方向:附加條目 RPC 是向外發送的。在 VR 中,日誌條目的流動是雙向的(領導人能夠在選舉過程當中接收日誌);這就致使了額外的機制和複雜性。根據 ZooKeeper 公開的資料看,它的日誌條目也是雙向傳輸的,可是它的實現更像 Raft。

和上述咱們說起的其餘基於一致性的日誌複製算法中,Raft 的消息類型更少。例如,咱們數了一下 VR 和 ZooKeeper 使用的用來基本一致性須要和成員改變的消息數(排除了日誌壓縮和客戶端交互,由於這些都比較獨立且和算法關係不大)。VR 和 ZooKeeper 都分別定義了 10 中不一樣的消息類型,相對的,Raft 只有 4 中消息類型(兩種 RPC 請求和對應的響應)。Raft 的消息都稍微比其餘算法的要信息量大,可是都很簡單。另外,VR 和 ZooKeeper 都在領導人改變時傳輸了整個日誌;因此爲了可以實踐中使用,額外的消息類型就很必要了。

Raft 的強領導人模型簡化了整個算法,可是同時也排斥了一些性能優化的方法。例如,平等主義 Paxos (EPaxos)在某些沒有領導人的狀況下能夠達到很高的性能。平等主義 Paxos 充分發揮了在狀態機指令中的交換性。任何服務器均可以在一輪通訊下就提交指令,除非其餘指令同時被提出了。然而,若是指令都是併發的被提出,而且互相之間不通訊溝通,那麼 EPaxos 就須要額外的一輪通訊。由於任何服務器均可以提交指令,因此 EPaxos 在服務器之間的負載均衡作的很好,而且很容易在 WAN 網絡環境下得到很低的延遲。可是,他在 Paxos 上增長了很是明顯的複雜性。

一些集羣成員變換的方法已經被提出或者在其餘的工做中被實現,包括 Lamport 的原始的討論,VR 和 SMART。咱們選擇使用共同一致的方法由於他對一致性協議的其餘部分影響很小,這樣咱們只須要不多的一些機制就能夠實現成員變換。Lamport 的基於 α 的方法之因此沒有被 Raft 選擇是由於它假設在沒有領導人的狀況下也能夠達到一致性。和 VR 和 SMART 相比較,Raft 的從新配置算法能夠在不限制正常請求處理的狀況下進行;相比較的,VR 須要中止全部的處理過程,SMART 引入了一個和 α 相似的方法,限制了請求處理的數量。Raft 的方法同時也須要更少的額外機制來實現,和 VR、SMART 比較而言。

11 結論

算法的設計一般會把正確性,效率或者簡潔做爲主要的目標。儘管這些都是頗有意義的目標,可是咱們相信,可理解性也是同樣的重要。在開發者把算法應用到實際的系統中以前,這些目標沒有一個會被實現,這些都會必然的偏離發表時的形式。除非開發人員對這個算法有着很深的理解而且有着直觀的感受,不然將會對他們而言很難在實現的時候保持原有指望的特性。

在這篇論文中,咱們嘗試解決分佈式一致性問題,可是一個廣爲接受可是十分使人費解的算法 Paxos 已經困擾了無數學生和開發者不少年了。咱們創造了一種新的算法 Raft,顯而易見的比 Paxos 要容易理解。咱們同時也相信,Raft 也能夠爲實際的實現提供堅實的基礎。把可理解性做爲設計的目標改變了咱們設計 Raft 的方式;隨着設計的進展,咱們發現本身重複使用了一些技術,好比分解問題和簡化狀態空間。這些技術不只提高了 Raft 的可理解性,同時也使咱們堅信其正確性。

12 感謝

這項研究必須感謝如下人員的支持:Ali Ghodsi,David Mazie`res,和伯克利 CS 294-91 課程、斯坦福 CS 240 課程的學生。Scott Klemmer 幫咱們設計了用戶調查,Nelson Ray 建議咱們進行統計學的分析。在用戶調查時使用的關於 Paxos 的幻燈片很大一部分是從 Lorenzo Alvisi 的幻燈片上借鑑過來的。特別的,很是感謝 DavidMazieres 和 Ezra Hoch,他們找到了 Raft 中一些難以發現的漏洞。許多人提供了關於這篇論文十分有用的反饋和用戶調查材料,包括 Ed Bugnion,Michael Chan,Hugues Evrard,Daniel Giffin,Arjun Gopalan,Jon Howell,Vimalkumar Jeyakumar,Ankita Kejriwal,Aleksandar Kracun,Amit Levy,Joel Martin,Satoshi Matsushita,Oleg Pesok,David Ramos,Robbert van Renesse,Mendel Rosenblum,Nicolas Schiper,Deian Stefan,Andrew Stone,Ryan Stutsman,David Terei,Stephen Yang,Matei Zaharia 以及 24 位匿名的會議審查人員(可能有重複),而且特別感謝咱們的領導人 Eddie Kohler。Werner Vogels 發了一條早期草稿連接的推特,給 Raft 帶來了極大的關注。咱們的工做由 Gigascale 系統研究中心和 Multiscale 系統研究中心給予支持,這兩個研究中心由關注中心研究程序資金支持,一個是半導體研究公司的程序,由 STARnet 支持,一個半導體研究公司的程序由 MARCO 和 DARPA 支持,在國家科學基金會的 0963859 號批准,而且得到了來自 Facebook,Google,Mellanox,NEC,NetApp,SAP 和 Samsung 的支持。Diego Ongaro 由 Junglee 公司,斯坦福的畢業團體支持。

本文經TopJohn受權轉自TopJohn's Blog

深刻淺出區塊鏈 - 系統學習區塊鏈,打造最好的區塊鏈技術博客。

相關文章
相關標籤/搜索