《In Search of an Understandable Consensus Algorithm》翻译
Abstract
Raft是一種用于管理replicated log的consensus algorithm。它能和Paxos產(chǎn)生同樣的結(jié)果,有著和Paxos同樣的性能,但是結(jié)構(gòu)卻不同于Paxos;它讓Raft比Paxos更易于理解,并且也為用它構(gòu)建實(shí)際的系統(tǒng)提供了更好的基礎(chǔ)。為了增強(qiáng)可理解性,Raft將例如leader election, log replication以及safety等共識(shí)的關(guān)鍵元素進(jìn)行了分離,并且提供了更強(qiáng)的一致性用于減少必須考慮的狀態(tài)。從用戶調(diào)查的結(jié)果來看,Raft比Paxos更易于學(xué)生學(xué)習(xí)。Raft包含了一種新的機(jī)制用于改變cluster membership,并通過overlapping majority來保證安全性。
1 Introduction
Consensus algorithm允許一群機(jī)器像一個(gè)整體一樣工作,即使其中的一些成員發(fā)生故障也不會(huì)出現(xiàn)問題。正因?yàn)檫@一點(diǎn),它在構(gòu)建可靠的大規(guī)模軟件系統(tǒng)的過程中起著關(guān)鍵的作用。Paxos一直主導(dǎo)著過去十年對(duì)consensus algorithm的討論:許多共識(shí)的實(shí)現(xiàn)都基于Paxos或者受到它的影響,并且Paxos已經(jīng)成為了用來教授學(xué)生關(guān)于共識(shí)的主要工具。
不幸的是,Paxos太難以理解了,盡管已經(jīng)做了很多嘗試想使它變得更加平易近人。另外,為了支持實(shí)際的系統(tǒng),它的結(jié)構(gòu)需要做非常復(fù)雜的改變。因此,系統(tǒng)架構(gòu)師和學(xué)生都對(duì)Paxos感到很痛苦。
在我們自己和Paxos經(jīng)歷了一番痛苦掙扎之后,我們決定發(fā)明一種新的consensus algorithm來為系統(tǒng)的構(gòu)建和教學(xué)提供更好的基礎(chǔ)。我們的主要目標(biāo)有點(diǎn)特別,是為了讓它更加易于理解:我們是否能為實(shí)際的系統(tǒng)定義一個(gè)consensus algorithm,并且描述它的方式能比Paxos更加易于理解?此外,我們想要該算法有利于the development of intuitions,而這對(duì)系統(tǒng)構(gòu)建者是必不可少的。算法能工作很重要,但是能清楚地顯示它為什么能工作同樣非常重要。
這項(xiàng)工作的結(jié)果就是一個(gè)叫做Raft的consensus algorithm。在設(shè)計(jì)Raft的時(shí)候,我們使用了一些額外的技術(shù)用于提供可理解性,包括decomposition(Raft分離了leader election, log replication和safety)以及狀態(tài)空間的減少(和Paxos相比,Raft降低了不確定性以及sever之間能達(dá)到一致的方法)。一個(gè)由來自兩個(gè)大學(xué)的43位學(xué)生組成的用戶調(diào)查顯示Raft要比Paxos易于理解的多;在同時(shí)學(xué)習(xí)了兩種方法之后,其中的33名學(xué)生回答Raft的問題要比回答Paxos更好。
Raft在很多方面和現(xiàn)存的consensus algorithm類似,但是它有以下這些獨(dú)特的特性:
- Strong leader:Raft比其他consensus algorithm使用了更強(qiáng)形式的leadership。比如,log entry只能從leader流向其他server。這簡(jiǎn)化了對(duì)于replicated log的管理并且使Raft更加易于理解。
- Leader election:Raft使用隨機(jī)的時(shí)鐘來選舉leader。這只是在原來所有的consensus algorithm都需要的heartbeats的基礎(chǔ)上增加了小小的一點(diǎn)東西,但是卻簡(jiǎn)單快速地解決了沖突。
- Membership changes:Raft通過一種新的joint consensus的方法來實(shí)現(xiàn)server集合的改變,其中兩個(gè)不同配置下的majority在過度階段會(huì)發(fā)生重合。這能讓集群在配置改變時(shí)也能繼續(xù)正常運(yùn)行。
我們相信不論對(duì)于教學(xué)還是用于真實(shí)系統(tǒng)實(shí)現(xiàn)的基礎(chǔ),Raft都要優(yōu)于Paxos和其他的共識(shí)算法。它比其他算法更簡(jiǎn)答也更加易于理解;它能完全滿足實(shí)際系統(tǒng)的需求;它有很多開源的實(shí)現(xiàn)并且被很多公司使用;它的安全性已經(jīng)被完全證實(shí)了;并且它的效率也完全可以和其他算法相媲美。
論文的剩余部分介紹了replicated state machine問題(Section 2),討論了Paxos的優(yōu)缺點(diǎn)(Section 3),描述了可理解性的一般方法(Section 4),描述了Raft consensus algorithm(Section 5-7),評(píng)估Raft(Section 8),并且討論了相關(guān)工作(Section 9)。Raft中的一小部分元素在這里因?yàn)槠脑蚴÷粤?#xff0c;但是它們可以在一份擴(kuò)展的技術(shù)報(bào)告里找到。其余的內(nèi)容描述了client怎么和系統(tǒng)進(jìn)行交互以及Raft log的空間怎么被回收。
2 Replicated state machines
consensus algorithm通常在replicated state machine的上下文中出現(xiàn)。在這種方法中,一群server上的state machine對(duì)同一個(gè)狀態(tài)的拷貝進(jìn)行計(jì)算,即使其中一些server宕機(jī)了也能正常運(yùn)行。Replicated state machine通常用于解決分布式系統(tǒng)中的容錯(cuò)問題。例如,擁有單一的cluster leader的大規(guī)模系統(tǒng),例如GFS,HDFS和RAMCloud通常會(huì)用一個(gè)單獨(dú)的replicated state machine來管理leader的選舉以及存儲(chǔ)一些在拯救leader崩潰的配置信息。Replicated state machine典型的例子包括Chubby和ZooKeeper。
Replicated state machine通常用一個(gè)replicated log來實(shí)現(xiàn),如Figure 1所示。每一個(gè)server存儲(chǔ)了一個(gè)包含一系列命令的log,而它的state machine順序執(zhí)行這些命令。每一個(gè)log以同樣的順序包含了同樣的指令,所以每一個(gè)state machine都會(huì)處理相同的命令。因?yàn)槊恳粋€(gè)state machine都是確定性的,因此計(jì)算將得到同樣的狀態(tài)和輸出結(jié)果。
Consensus algorithm的作用是保證replicated log的一致性。server中的consensus module用于從client處接受命令并且將它們加入log。它會(huì)和其他serer的consensus module進(jìn)行通信,從而確保每一個(gè)log都以相同的順序包含相同的請(qǐng)求,每一個(gè)server的state machine都按順序處理它們的log,并且將輸出返回給client。最終,這些server呈現(xiàn)出的是一個(gè)單一的,高度可靠的state machine。
用于實(shí)際系統(tǒng)的consensus algorithm通常具有以下特性:
- 在所有的non-Byzantine條件下要確保正確性(從不返回一個(gè)錯(cuò)誤的結(jié)果),包括網(wǎng)絡(luò)延遲,分區(qū)以及網(wǎng)絡(luò)包的丟失,重復(fù)和亂序。
- 只要majority of servers是可操作的并且能相互之間進(jìn)行通信,以及和client進(jìn)行通信,那么系統(tǒng)必須是可用的。因此,一個(gè)由五臺(tái)server組成的集群必須能忍受兩臺(tái)server的故障。Server發(fā)生故障時(shí),可以認(rèn)為是暫停了;它們可能稍后會(huì)從恢復(fù)到存儲(chǔ)在stable storage中的狀態(tài)并且重新加入集群。
- 它們不依賴于時(shí)間來確保log的一致性:fault clocks和extreme message delays在最差的情況下也只能導(dǎo)致系統(tǒng)不可用的問題。
- 通常情況下,當(dāng)集群中的大多數(shù)server已經(jīng)對(duì)單一的RPC做出相應(yīng)時(shí),可以認(rèn)為一個(gè)命令完成了。少數(shù)慢的server不應(yīng)該影響整個(gè)系統(tǒng)的性能。
3 What's wrong with Paxos?
在過去的十年中,Leslie Lamport的Paxos協(xié)議幾乎成了consensus的同義詞:它是在課程中最常被教授的協(xié)議,并且很多consensus的實(shí)現(xiàn)都以它作為起點(diǎn)。Paxos首先定義了一個(gè)在單一的decision上能達(dá)到agreement的協(xié)議,例如一個(gè)單一的replicated log entry。我們將這樣的一個(gè)子集稱之為single-decree Paxos。之后Paxos可以將該協(xié)議的多個(gè)實(shí)例組合在一起去形成一系列的decision作為log(multi-Paxos)。Paxos保證了safety和liveness,并且它支持cluster membership的改變。它的正確性已經(jīng)被證明了并且在一般的情況下也被證明是高效的。
不幸的是,Paxos有兩個(gè)重要的缺陷。第一個(gè)缺陷是Paxos太難以理解了。它的完整描述是出了名的晦澀;很少有人能成功理解它,即使能也是花了很大的功夫。因此,已經(jīng)做了很多嘗試,試圖用一個(gè)更簡(jiǎn)單的版本解釋Paxos。雖然它們都著力于single-decree版本,但是仍然非常具有挑戰(zhàn)性。在一項(xiàng)針對(duì)NSDI 2012與會(huì)者的調(diào)查中,我們發(fā)現(xiàn)很少有人對(duì)Paxos感到舒服,即使是那些經(jīng)驗(yàn)豐富的研究人員。我們自己也對(duì)Paxos感到非常痛苦,我們?cè)诓荒芾斫馔暾膮f(xié)議,直到我們閱讀了幾個(gè)簡(jiǎn)化版的描述以及設(shè)計(jì)了我們自己的替代協(xié)議,而這整個(gè)過程持續(xù)了將近一年。
我們認(rèn)為Paxos的晦澀來源于它將single-decree subset作為自己的基礎(chǔ)。Single-decree Paxos被認(rèn)為是微妙的:它被劃分為兩個(gè)不能用直覺來顯示的階段并且不能單獨(dú)理解。因此,這就導(dǎo)致了很難對(duì)single-decree protocol是如何工作的建立起直覺。而multi-Paxos的composition rule則更加添加了復(fù)雜性。我們堅(jiān)信對(duì)于在multiple decision的情況下到達(dá)consensus這個(gè)問題肯定能以其他更直接,更明顯的方式被分解。
Paxos的第二個(gè)問題是它并沒有為實(shí)際的實(shí)現(xiàn)提供一個(gè)很好的基礎(chǔ)。一大原因是對(duì)于multi-Paxos沒有一個(gè)廣受認(rèn)可的算法。Lamport的描述主要針對(duì)的是single-decree Paxos;它為multi-Paxos提供了一個(gè)大概的框架,但是很多細(xì)節(jié)并沒有提及。對(duì)于充實(shí)以及優(yōu)化Paxos已經(jīng)做了很多努力,但是它們各自之間,以及和Lamport的概述都不相同。像Chubby這樣的系統(tǒng)已經(jīng)實(shí)現(xiàn)了類Paxos算法,但是它的很多細(xì)節(jié)并沒有公開。
另外,Paxos的架構(gòu)也不利于構(gòu)建實(shí)際系統(tǒng);這是它按single-decree分解的另一個(gè)后果。例如,獨(dú)立地選取一系列的log entry并且將它們?nèi)诤铣梢粋€(gè)順序的log并沒有太多好處,僅僅只是增加了復(fù)雜度。相反,構(gòu)建一個(gè)圍繞按順序擴(kuò)展log的系統(tǒng)是更簡(jiǎn)單和高效的。Paxos的另一個(gè)問題是它將對(duì)稱的peer-to-peer作為核心(雖然在最后為了優(yōu)化性能建議了一種弱形式的leadership)。這在只需要做一個(gè)decision的簡(jiǎn)單場(chǎng)景中是可行的,但是很少有實(shí)際的系統(tǒng)會(huì)使用這種方法。如果要有一系列的decision要決定,那么先選擇一個(gè)leader,然后再讓leader去協(xié)調(diào)decision。
因此,實(shí)際系統(tǒng)很少和Paxos類似。各種實(shí)現(xiàn)都以Paxos開始,然后發(fā)現(xiàn)實(shí)現(xiàn)起來很困難,于是最后開發(fā)出了一個(gè)完全不同的架構(gòu)。這是極其費(fèi)時(shí)并且容易出錯(cuò)的,而Paxos的難以理解則更加加劇了這個(gè)問題。Paxos的正確性理論很好證明,但是實(shí)際的實(shí)現(xiàn)和Paxos太過不同,因此這些證明就沒什么價(jià)值了。接下來這段來自Chubby的評(píng)論是非常典型的:
Paxos算法的描述和現(xiàn)實(shí)世界的系統(tǒng)的需求之間有巨大的矛盾....而最終的系統(tǒng)都將建立在一個(gè)未經(jīng)證明的協(xié)議之上
因?yàn)檫@些問題的存在,我們得出這樣的結(jié)論,Paxos并沒有為實(shí)際系統(tǒng)的構(gòu)建或者是教學(xué)提供一個(gè)很好的基礎(chǔ)。基于在大規(guī)模軟件系統(tǒng)中consensus的重要性,我們決定嘗試能否設(shè)計(jì)出另外一種比Paxos有著更好性質(zhì)的consensus algorithm。而Raft就是我們實(shí)驗(yàn)得到的結(jié)果。
4 Designing for understandability
我們?cè)谠O(shè)計(jì)Raft的時(shí)候有以下幾個(gè)目標(biāo):它必須為系統(tǒng)的構(gòu)建提供完整并且實(shí)際有效的基礎(chǔ),而這能極大地減少開發(fā)者的設(shè)計(jì)工作;它必須在所有條件下都是安全的,在典型的操作條件下是可用的,在通常的操作中是高效的。但我們最重要的目標(biāo),也是最大的挑戰(zhàn),就是可理解性。我們必須讓廣大的讀者能比較容易地理解這個(gè)算法。并且要能夠建立對(duì)這個(gè)算法的直覺,從而讓系統(tǒng)構(gòu)建者能做一些實(shí)際實(shí)現(xiàn)中必要的擴(kuò)展。在設(shè)計(jì)Raft的很多節(jié)點(diǎn)上,我們要在很多可選方法之間做出選擇。在這些情況下,我們基于可理解性對(duì)這些方法進(jìn)行評(píng)估:對(duì)于每一個(gè)可選方案的描述是否困難(比如,它的狀態(tài)空間的復(fù)雜度是多少,以及它是否有subtle implication?)以及讀者是否能輕松地完全理解這種方法。
后來我們意識(shí)到這種分析方法具有很強(qiáng)的主觀性;于是我們使用了兩種方法讓分析變得更具通用性。第一種是關(guān)于問題分解的眾所周知的方法:是否有可能,我們可以將問題分解為可以被相對(duì)獨(dú)立地解釋,理解并且被解決的幾部分。例如,在Raft中,我們分解了leader election, log replication, safety和membership changes這幾部分。
我們的第二種方法是通過減少需要考慮的狀態(tài)數(shù),盡量讓系統(tǒng)更一致以及盡可能地減少非確定性,來簡(jiǎn)化state space。另外,log不允許存在hole,Raft限制了log之間存在不一致的可能。雖然在大多數(shù)情況下,我們都要減少不確定性,但是在某些情況下,不確定性確實(shí)提高了可理解性。特別地,隨機(jī)化的方法會(huì)引入不確定性,但是通過以相同的方式處理所有可能的選擇(choose any; it doesn't matter),確實(shí)減少了state space。我們就使用了隨機(jī)化來減少了Raft的leader election algorithm。
5 The Raft consensus algorithm
Raft是一種用于管理Section 2中所描述的形式的replicated log的算法。Figure 2以精簡(jiǎn)的形式概述了這一算法,而Figure 3列出了該算法的關(guān)鍵特性,而這些特性將在本節(jié)的剩余部分分別進(jìn)行討論。
Raft首先通過選舉一個(gè)distinguished leader來實(shí)現(xiàn)consensus,然后將管理replicated log的責(zé)任全部給予這個(gè)leader。leader從client處接收log entry,再將它備份到其他server中,接著告訴server什么時(shí)候能安全地將log entry加入state machine中。leader的存在簡(jiǎn)化了replicated log的管理。比如,leader可以在不詢問其他leader的情況下決定將新的entry存放在log的什么位置并且數(shù)據(jù)簡(jiǎn)單地從leader流向其他server。leader可能會(huì)發(fā)生故障或者和其他server斷開,在這種情況下,會(huì)有新的leader被選舉出來。
通過選舉leader,Raft將consesus problem分解成三個(gè)相對(duì)獨(dú)立的子問題,它們會(huì)在接下來的子章節(jié)中討論:
- Leader election:在一個(gè)已有的leader故障之后,必須要有一個(gè)新的leader被選舉出來(Section 5.2)
- Log replication:leader必須從client處接收log entry并且將它們?cè)诩褐羞M(jìn)行備份,強(qiáng)制使其他log與它自己一致(Section 5.3)
- Safety:Raft中最關(guān)鍵的safety property就是Figure 3所示的State Machine Safety Property:如果有任何的server已經(jīng)將一個(gè)特定的log entry加入它的state machine中,那么其他的server對(duì)于同一個(gè)log index的log entry必須相同
在展示了consensus algorithm之后,本節(jié)將討論可用性以及時(shí)間在系統(tǒng)中扮演的角色
5.1 Raft basics
一個(gè)Raft集群包含多個(gè)server;一般都是五個(gè),因此系統(tǒng)能忍受兩臺(tái)機(jī)器的故障。在任意給定時(shí)刻,每個(gè)server都處于以下三個(gè)狀態(tài)中的一個(gè):leader,follower,或者candidate。在正常情況下,只有一個(gè)leader,其他都是follower。follower是很被動(dòng)的,它們不會(huì)自己發(fā)送請(qǐng)求,只是簡(jiǎn)單地對(duì)來自leader和candidate的請(qǐng)求進(jìn)行回復(fù)。leader對(duì)所有來自client的請(qǐng)求進(jìn)行處理(如果一個(gè)client和follower進(jìn)行交互,follower會(huì)將它重定向給leader),第三種狀態(tài),candidate,是用來選舉Section 5.2中描述的新的leader。Figure 4顯示了各種狀態(tài)以及它們之間的轉(zhuǎn)換;關(guān)于轉(zhuǎn)換將在下文進(jìn)行討論。
?
Raft將時(shí)間劃分成任意長(zhǎng)度的term,如Figure 5所示。Term以連續(xù)的整數(shù)進(jìn)行編號(hào)。每個(gè)term以一個(gè)election開始,這個(gè)階段會(huì)有一個(gè)或多個(gè)candidate競(jìng)選leader,如Section 5.2所示。 如果一個(gè)candidate競(jìng)選成功,那么它將在term剩下的時(shí)間里作為leader。在有些情況下,一個(gè)election可能導(dǎo)致一個(gè)split vote。在這種情況下,term將以一種沒有l(wèi)eader的狀態(tài)結(jié)束;而一個(gè)新的term(伴隨著一個(gè)新的選舉)將馬上開始。Raft將保證在給定的一個(gè)term中,總是最多只有一個(gè)leader。
不同的server可能在不同的時(shí)間觀察到term的轉(zhuǎn)換,而在有些情況下,一個(gè)server可能會(huì)觀察不到election甚至是一個(gè)完整的term。term在Raft中扮演的是一個(gè)logical clock的角色,它能夠讓server去檢測(cè)那些需要淘汰的信息,例如過時(shí)的leader。每個(gè)server都存儲(chǔ)了一個(gè)current term number,它會(huì)隨著時(shí)間單調(diào)遞增。current term會(huì)隨著server之間的交互而改變;如果一個(gè)server的current term比其他的小,那么它就會(huì)將自己的current term更新到更大的值。如果一個(gè)candidate或者leader發(fā)現(xiàn)它的term已經(jīng)過時(shí)了,那么它就會(huì)立即恢復(fù)到follower state。如果一個(gè)server接收到一個(gè)來自過時(shí)的term的請(qǐng)求,那么拒絕它。
Raft servers之間通過RPC進(jìn)行通信,而consensus algorithm需要兩種類型的RPC。RequestVote RPC由candidate在election期間發(fā)起(Section 5.2),AppendEntries RPC由leader發(fā)起,用于備份log entry和提供heartbeat(Section 5.3)。如果一個(gè)server沒有收到回復(fù),那么它會(huì)及時(shí)重發(fā)RPC,并且它們會(huì)并行發(fā)送RPC用于提高性能。
5.2 Leader election
Raft使用一種heartbeat mechanism 來觸發(fā)leader election。當(dāng)server啟動(dòng)的時(shí)候,默認(rèn)作為follower。server如果能持續(xù)地從leader或者candidate處獲取合法的RPC,那么它將始終保持follower狀態(tài)。為了保持自己的權(quán)威性,leader會(huì)階段性地發(fā)送heartbeats(不帶有l(wèi)og entry的AppendEntry RPC)給所有的follower。如果一個(gè)server在一個(gè)叫做election timeout的時(shí)間段中沒有收到交互信息,那么它就會(huì)認(rèn)為不存在一個(gè)viable leader,并且開始一輪新的election選出新的leader。
為了開始一個(gè)election,follower會(huì)增加它的current term并且轉(zhuǎn)換為candidate state。接著它會(huì)投票給自己,并且并行地給集群中的其他server發(fā)送RequestVote RPC。candidate將持續(xù)保持這種狀態(tài),直到以下三個(gè)條件中的一個(gè)被觸發(fā):(a) 它贏得了選舉,(b) 另一個(gè)server宣布它自己是leader,或者(c) 過了一段時(shí)間之后也沒有winner。這些情況將在接下來分別進(jìn)行討論。
如果一個(gè)candidate收到了來自集群中的majority個(gè)server對(duì)于同一個(gè)term的投票,那么它將贏得election。每一個(gè)server在給定的term中都最多只會(huì)投票給一個(gè)candidate,并且基于first-come-first-serverd原則(Section 5.4中將對(duì)于投票添加一個(gè)額外的約束)。majority原則確保了在一個(gè)給定的term中最多只有一個(gè)candidate可以贏得election(Figure 3中的Election Safety Property)。一旦一個(gè)candidate贏得了election,它將成為leader。之后它將向所有其他的server發(fā)送hearbeat用以確保自己的權(quán)威并且防止新一輪的election。
當(dāng)在等待投票時(shí),一個(gè)candidate可能會(huì)收到來自另一個(gè)server的AppendEntry RPC聲稱自己是leader。如果該leader的term(包含在該RPC中)至少和candidate的current term一樣大,那么candiate認(rèn)為該leader是合法的并且返回到follower的狀態(tài)。如果RPC中的term比candidate的current term要小,那么candidate會(huì)拒絕該RPC并且依然保持為candidate狀態(tài)。
第三種可能的情況是一個(gè)candidate在election中既沒有贏也沒有輸:如果在同一時(shí)刻有很多follower成為了candidate,投票將會(huì)分裂因此沒有candidate會(huì)獲得majority。當(dāng)這種情況發(fā)生時(shí),每個(gè)candidate都會(huì)timeout并且通過增加term和發(fā)送新一輪的RequestVote RPC來開始新的election。然而,如果沒有額外的措施,splite vote可能會(huì)一直重復(fù)下去。
?Raft使用隨機(jī)的election timeout來確保split vote很少會(huì)發(fā)生并且保證即使發(fā)生了也很快會(huì)被解決。為了在一開始就避免split ovte,election timeout會(huì)在一個(gè)固定區(qū)間內(nèi)隨機(jī)選擇(e.g., 150-300ms)。這就將server鋪散開來從而保證在大多數(shù)情況下只有一個(gè)server會(huì)timeout;它將贏得election并且在其他的server timeout之前發(fā)送heartbeat。同樣的機(jī)制也被用在處理split vote上。每個(gè)candidate在election開始的時(shí)候重新隨機(jī)確定一個(gè)election timeout并在下一次election開始前靜靜等待timeout的到來;這就減少了在下一個(gè)新的election的時(shí)候發(fā)生split vote的可能。Section 8.3展示了使用這種方法快速選擇一個(gè)leader的過程。
Election是一個(gè)展示可理解性作為指導(dǎo)我們做出設(shè)計(jì)選擇的一個(gè)很好的例子。一開始我們計(jì)劃使用一個(gè)rank system:每個(gè)candidate都會(huì)賦予一個(gè)唯一的rank,它會(huì)被用來在相互競(jìng)爭(zhēng)的candidate之中做出選擇。當(dāng)一個(gè)candidate發(fā)現(xiàn)另一個(gè)candidate有更高的rank,那么它就會(huì)退回到follower的狀態(tài),從而讓有更高rank的candidate能更容易贏得下一輪election。但我們發(fā)現(xiàn)這種方法會(huì)在可用性方面產(chǎn)生一些微妙的問題(如果有著更高rank的server發(fā)生了故障,一個(gè)低rank的server可能需要timeout并且重新成為candidate,但是這個(gè)過程發(fā)生地太快,則會(huì)引發(fā)新的leader選擇過程)。我們對(duì)這一算法做了多次調(diào)整,但是每次調(diào)整之后都有新的corner cases產(chǎn)生。最后我們得出結(jié)論,隨機(jī)重試的方法是更明顯也更易理解的方法。
5.3 Log replication
一旦一個(gè)leader被選擇出來以后,它開始處理client request。每個(gè)client request都包含了需要由replicated state machine執(zhí)行的command。leader用command擴(kuò)展log,作為新的entry,接著并行地給其他server發(fā)生AppendEntry RPC來備份entry。當(dāng)該entry被安全地備份之后(如下所述),leader會(huì)讓它的state machine執(zhí)行該entry,并且將執(zhí)行結(jié)果返回給client。如果follower崩潰了或者運(yùn)行很慢,抑或是丟包了,leader會(huì)不停地重發(fā)AppendEntry RPC直到所有的follower最終都保存了所有的log entry。
Log以Figure 6中的形式被組織。當(dāng)一個(gè)entry被leader接收的時(shí)候,每個(gè)log entry都會(huì)包含一個(gè)state machine command和term number。log entry中的term number是用來檢測(cè)log之間的不一致性并且確保Figure 3中的一些特性的。同時(shí),每個(gè)log entry都有一個(gè)整數(shù)的index用于標(biāo)示它在log中的位置。
leader決定何時(shí)讓state machine執(zhí)行l(wèi)og entry是安全的,而這樣的entry叫做committed。Raft保證所有committed entry都是durable并且最終會(huì)被所有可用的state machine執(zhí)行。一旦創(chuàng)建它的leader已經(jīng)將它備份到majority個(gè)server中,log entry就會(huì)被committed(e.g., Figure 6中的entry 7)。同時(shí)它也會(huì)commit leader的log中所有前綴的entry,包括那些由之前的leader創(chuàng)建的entry。Section 5.4中會(huì)討論在leader改變之后應(yīng)用這條規(guī)則會(huì)產(chǎn)生的一些微妙的問題,同時(shí)它也會(huì)展示這樣的關(guān)于的commitment的定義是安全的。leader會(huì)追蹤它已知被committed最高的index,并且會(huì)在之后的AppendEntry RPC(包括heartbeat)包含這個(gè)index從而讓其他server能發(fā)現(xiàn)它。一旦follower知道了一個(gè)log entry被committed,它最終會(huì)讓本地的state machine運(yùn)行這個(gè)entry(以log的順序)。
我們?cè)O(shè)計(jì)了Raft log mechanism來保持不同server的log之間的高度一致性。這不僅簡(jiǎn)化了系統(tǒng)行為讓它們變得可預(yù)測(cè),并且這也是確保安全性的重要組件。Raft維護(hù)了以下特性,它們合起來構(gòu)成了Figure 3所示的Log Matching Property:
- 如果不同的log中的兩個(gè)entry有相同的index和term,那么它們存儲(chǔ)相同的command
- 如果不同的log中的兩個(gè)entry有相同的index和term,那么它們前綴的entry都是相同的
第一個(gè)特性確保了leader對(duì)于給定的log index和term,它最多產(chǎn)生一個(gè)entry,并且log entry永遠(yuǎn)不會(huì)改變它在log中的位置。第二個(gè)特性則由AppendEntry一個(gè)簡(jiǎn)單的一致性檢查來保證。在發(fā)送一個(gè)AppendEntry RPC的時(shí)候,leader會(huì)在其中包含新的entry之前的那個(gè)entry的index和term。如果follower沒有在log中有同樣index和term的entry,那么它就會(huì)拒絕新的entry。一致性檢查扮演了induction step:log的initial empty state是滿足Log Matching Property的,而一致性檢查則在log擴(kuò)展的時(shí)候保證了Log Matching Property。因此,當(dāng)AppendEntry成功返回的時(shí)候,leader就知道該follower的log和它自己是一致的。
在進(jìn)行正常操作的時(shí)候,leader和follower的操作始終是一致的,因此AppendEntry的一致性檢查用于不會(huì)失敗。但是,leader崩潰會(huì)導(dǎo)致log處于不一致的狀態(tài)(老的leader可能還沒有將它log中的所有entry完全備份)。而這些不一致性可能隨著一系列的leader和follower的崩潰而疊加。Figure 7說明了follower的log可能和新的leader不一致的情況。follower中可能會(huì)遺漏一些leader中的entry,同時(shí)它里面也可能有一些leader中沒有的額外的entry,或者兩者都有。log中遺失的或者額外的entry中可能跨越多個(gè)term。
為了讓follower的log和自己保持一致,leader必須找到兩個(gè)log一致的最遠(yuǎn)的entry,并且刪除follower該entry之后所有的entry。所有這些操作都用于回應(yīng)AppendEntry RPC的一致性檢查。leader為每一個(gè)follower維護(hù)了一個(gè)nextIndex,它代表了leader將會(huì)發(fā)送給follower的下一個(gè)log entry。當(dāng)一個(gè)leader剛剛開始執(zhí)行的時(shí)候,它會(huì)將所有的nextIndex都初始化為它自己log的最后一個(gè)entry的index加一(Figure 7中的11)。如果follower和leader的log不一致,AppendEntry RPC的一致性檢查會(huì)在下一個(gè)AppendEntry RPC的時(shí)候失敗。在收到一個(gè)rejection之后,leader會(huì)減小它的nextIndex并且重發(fā)AppendEntry RPC。最終nextIndex會(huì)達(dá)到leader和follower的log匹配的狀態(tài)。此時(shí),AppendEntry會(huì)成功返回,移除了follower的log中沖突的entry并且會(huì)根據(jù)leader的log進(jìn)行擴(kuò)展(如果有的話)。一旦AppendEntry成功,follower已經(jīng)和leader的log一致了,而且將在term的接下來部分保持。該協(xié)議可以通過減少rejected AppendEntry RPC的數(shù)目來優(yōu)化。
在這種機(jī)制下,leader不用在它剛剛成為leader的時(shí)候執(zhí)行任何額外的動(dòng)作用于恢復(fù)log的一致性。它只是正常地開始執(zhí)行,并且log會(huì)隨著AppendEntry一致性檢查的失敗而不斷收斂。leader從來不會(huì)覆寫或者刪除它自己log的entry(Figure 3中的Leader Append-Only Property)。
該log replication mechanism展示了Section 2中想要達(dá)到的consensus property:Raft可以接收,備份,并且執(zhí)行新的log entry只要有majority個(gè)server活著;在正常情況下,一個(gè)新的entry會(huì)在單一的一輪RPC中被備份到cluster的一個(gè)majority中;因此一個(gè)運(yùn)行較慢的follower并不會(huì)影響性能。
5.4 Safety
在前面的章節(jié)中描述了Raft如何選舉leader以及備份log entry。但是之前描述的機(jī)制并不足以保證每個(gè)state machine以同樣的順序執(zhí)行同樣的command。比如,follower可能在leader commit多個(gè)log entry的時(shí)候一直處于不可用的狀態(tài),而之后它可能被選作leader并且用新的entry覆寫這些entry;因此,不同的state machine可能會(huì)執(zhí)行不同的command sequences。
本節(jié)中我們通過給哪些server能被選舉為leader增加約束來完善Raft算法。該約束確保任何給定的term的leader會(huì)包含之前term所有commit的entry(Figure 3中的Leader Completeness Property)。通過增加election restriction,我們更加細(xì)化了commitment的規(guī)則。最后,我們展示了Leader Completeness Property的證明草圖并且展示了它如何能讓replicated state machine正確操作。
5.4.2 Election restriction
任何leader-based consensus algorithm,leader最終都必須存儲(chǔ)所有的committed log entry。在一些consensus algorithm中,例如Viewstamped Replication,即使一開始沒有包含全部的committed entry也能被選為leader。這些算法都會(huì)包含額外的機(jī)制用于識(shí)別遺失的entry并且將它們傳輸給新的leader,要么在election期間,要么在這不久之后。不幸的是,這需要額外的機(jī)制以及復(fù)雜度。Raft使用了一種更簡(jiǎn)單的方法,它保證在選舉期間每個(gè)新的leader都包含了之前term都包含的所有entry,從而不需要將這些entry傳輸?shù)絣eader。這意味著log entry的流動(dòng)是單方向的,只從leader流向follower,而leader從不會(huì)覆寫log中已有的entry。
Raft使用voting process來防止那些log不包含全部committed entry的candidate贏得election。candidate為了贏得選舉必須和cluster的majority進(jìn)行交互,這意味著每個(gè)committed entry必須都在其中的一個(gè)majority存在。如果一個(gè)candidate的log至少和任何majority中的log保持up-to-date("up-to-date"將在下文精確定義),那么它就包含了所有committed entry。RequestVote RPC實(shí)現(xiàn)了這一約束:RPC中包含了candidate的log信息,voter會(huì)拒絕投票,如果它自己的log比該candidate的log更up-to-date。
Raft通過比較log中l(wèi)ast entry的index和term來確定兩個(gè)log哪個(gè)更up-to-date。如果兩個(gè)log的last entry有不同的term,那么擁有較大term的那個(gè)log更up-to-date。如果兩個(gè)log以相同的term結(jié)束,那么哪個(gè)log更長(zhǎng)就更up-to-date。
5.4.2 Committing entries from previous terms
如Section 5.3中所述,leader知道current term中的entry已經(jīng)被提交了,一旦該term已經(jīng)被majority個(gè)server存儲(chǔ)了。如果一個(gè)leader在committing an entry之前就崩潰了,那么未來的leader就會(huì)試著完成該entry的備份。但是leader很難馬上確認(rèn)之前term的entry已經(jīng)commited一旦它被存儲(chǔ)于majority個(gè)server中。Figure 8展示了這樣一種情況,一個(gè)old log entry已經(jīng)被存儲(chǔ)在majority個(gè)server中,但是它仍然可以被future leader覆寫。
為了防止Figure 8中這樣問題的發(fā)生,Raft從不會(huì)通過計(jì)算備份的數(shù)目來提交之前term的log entry。只有l(wèi)eader的當(dāng)前term的log entry才通過計(jì)算備份數(shù)committed;一旦當(dāng)前term的entry以這種方式被committed了,那么之前的所有entry都將因?yàn)長(zhǎng)og Matching Property而被間接committed。其實(shí)在很多情況下,leader可以非常安全地確定一個(gè)old entry已經(jīng)被committed了(比如,如果該entry已經(jīng)被存儲(chǔ)在所有server中了),但是Raft為了簡(jiǎn)單起見使用了一種更保守的方法。
因?yàn)閘eader從之前的term備份entry時(shí),log要保留之前的term number,這會(huì)讓Raft在commitment rule中引入額外的復(fù)雜度。在其他consensus algorithm中,如果一個(gè)新的leader從之前的term備份entry時(shí),它必須使用它自己的新的term number。因?yàn)閘og entry的term number不隨時(shí)間和log的不同而改變,這就能讓Raft更加容易地進(jìn)行推導(dǎo)。另外,Raft中的新的leader與其他算法相比只需要從之前的term傳輸更少的log entry(其他的算法必須傳輸備份的log entry進(jìn)行重新編號(hào)在它們被committed之前)。
5.4.3 Safety argument
給出了完整的Raft算法之后,我們可以進(jìn)一步論證Leader Completeness Property成立(該論據(jù)基于safety proof;參見Section 8.2)。我們假設(shè)Leader Completeness Property是不成立的,接著推出矛盾。假設(shè)term T的leader(leaderT) commit了一個(gè)該term的log entry,但是該log entry并沒有被未來的term的leader存儲(chǔ)。考慮滿足大于T的最小的term U,它的leader(leaderU)沒有存儲(chǔ)該entry。
1、該committed entry在leaderU選舉期間一定不存在于它的log中(leader從不刪除或者覆寫entry)。
2、leaderT將entry備份到了集群的majority中,并且leaderU獲取了來自集群的majority的投票,如Figure 9所示。而voter是達(dá)到矛盾的關(guān)鍵。
3、voter一定在投票給leaderU之前已經(jīng)接受了來自leaderT的committed entry;否則它將拒絕來自leaderT的AppendEntry request(因?yàn)樗腸urrent term高于T)。
4、當(dāng)voter投票給leaderU的時(shí)候它依然保有該entry,因?yàn)槊總€(gè)intervening leader都包含該entry(根據(jù)假設(shè)),leader從不刪除entry,而follower只刪除它們和leader矛盾的entry。
5、voter投票給leaderU,因此leaderU的log一定和voter的log一樣up-to-date。這就導(dǎo)致了兩個(gè)矛盾中的其中一個(gè)矛盾。
6、首先,如果voter和leaderU共享同一個(gè)last log term,那么leaderu的log至少要和voter的log一樣長(zhǎng),因此它的log包含了voter的log中的每一個(gè)entry。這是一個(gè)矛盾,因?yàn)関oter包含了committed entry而leaderU假設(shè)是不包含的。
7、除非,leaderU的last log term必須比voter的大。進(jìn)一步說,它必須大于T,因?yàn)関oter的last log term至少是T(它包含了term T的committed entry)。之前創(chuàng)建leaderU的last log entry的leader必須在它的log中包含了committed entry(根據(jù)假設(shè))。那么,根據(jù)Log Matching Property,leaderU的log必須包含committed entry,這也是一個(gè)矛盾。
8、這完成了矛盾。因此,所有term大于T的leader必須包含所有來自于T并且在term T提交的entry。
9、Log Matching Property確保了future leader也會(huì)包含那些間接committed的entry,例如Figure 8(d)中的index 2。
給定Leader Completeness Property,證明Figure 3中的State Machine Safety Property就比較容易,即讓所有的state machine以相同的順序執(zhí)行同樣的log entry。
5.5 Follower and candidate crashes
直到現(xiàn)在我們一直關(guān)注leader failures。follower和candidate的崩潰比起leader的崩潰要容易處理得多,而且它們的處理方式是相同的。如果一個(gè)follower或者candidate崩潰了,那么之后發(fā)送給它的RequestVote和AppendEntry RPC都會(huì)失敗。Raft通過不斷地重試來處理這些故障;如果崩潰的服務(wù)器重啟了,之后RPC就會(huì)成功完成。如果server在完成了RPC但是在回復(fù)之前崩潰了,那么它會(huì)在重啟之后收到一個(gè)同樣的RPC。但是Raft的RPC是冪等的,因此不會(huì)造成什么問題。比如一個(gè)follower接收了包含一個(gè)已經(jīng)在log中存在的entry的AppendEntry request,它會(huì)直接忽略。
5.6 Timing and availability
我們對(duì)于Raft的一個(gè)要求是,它的安全性不能依賴于時(shí)間:系統(tǒng)不會(huì)因?yàn)橛行┦录l(fā)生地比預(yù)期慢了或快了而產(chǎn)生錯(cuò)誤的結(jié)果。然而,可用性(系統(tǒng)及時(shí)響應(yīng)client的能力)將不可避免地依賴于時(shí)間。比如,因?yàn)閟erver崩潰造成的信息交換的時(shí)間比通常情況下來得長(zhǎng),candidate就不能停留足夠長(zhǎng)的時(shí)間來贏得election;而沒有一個(gè)穩(wěn)定的leader,Raft將不能進(jìn)一步執(zhí)行。
leader election是Raft中時(shí)間起最重要作用的地方。當(dāng)系統(tǒng)滿足以下的timing requirement的時(shí)候,Raft就能夠選舉并且維護(hù)一個(gè)穩(wěn)定的leader:
broadcastTime << electionTimeout << MTBF
在這個(gè)不等式中,broadcastTime是server并行地向集群中的每個(gè)server發(fā)送RPC并且收到回復(fù)的平均時(shí)間;electionTimeout就是如Section 5.2中描述的選舉超時(shí);MTBF是單個(gè)server發(fā)生故障的時(shí)間間隔。broadcastTime必須比electionTimeout小幾個(gè)數(shù)量級(jí),這樣leader就能可靠地發(fā)送heartbeat message從而防止follower開始選舉;通過隨機(jī)化的方法確定electionTimeout,該不等式又讓split vote不太可能出現(xiàn)。electionTimeout必須比MTBF小幾個(gè)數(shù)量級(jí),從而讓系統(tǒng)能穩(wěn)定運(yùn)行。當(dāng)leader崩潰時(shí),系統(tǒng)會(huì)在大概一個(gè)electionTimeout里不可用;我們希望這只占整個(gè)時(shí)間的很小一部分。
broadcastTime和MTBF都是底層系統(tǒng)的特性,而electionTimeout是我們必須選擇的。Raft的RPC通常要求接收者持久化信息到stable storage,因此broadcastTime的范圍在0.5ms到20ms之間,這取決于存儲(chǔ)技術(shù)。因此,electionTimeout可以取10ms到500ms。通常,server的MTBF是幾個(gè)月或者更多,因此很容易滿足timing requirement。
6 Cluster membership changes
?直到現(xiàn)在為止,我們都假設(shè)集群的configuration(參與consensus algorithm的server集合)是固定的。但實(shí)際上,偶爾改變configuration是必要的,比如在server發(fā)生故障時(shí)將其移除或者改變the degree of replication。雖然這可以通過停止整個(gè)集群,更新configuration file,再重啟集群實(shí)現(xiàn),但是這會(huì)讓集群在轉(zhuǎn)換期間變得不可用。另外,如果這其中存在手動(dòng)操作的話,還會(huì)有操作失誤的風(fēng)險(xiǎn)。為了防止這些情況的發(fā)生,我們決定自動(dòng)化configuration change并且將它們和Raft consensus algorithm結(jié)合起來。
為了保證configuration change mechanism的安全,在轉(zhuǎn)換期間不能有任意時(shí)刻對(duì)于同一個(gè)term有兩個(gè)leader。不幸的是,任何從old configuration轉(zhuǎn)換到new configuration的方法都是不安全的。不可能一次性對(duì)所有server進(jìn)行自動(dòng)轉(zhuǎn)換,所以在轉(zhuǎn)換期間集群會(huì)被潛在地分隔為兩個(gè)獨(dú)立的majority(見Figure 10)。
為了保證安全性,configuration change必須使用two-phase的方法。有很多種方法實(shí)現(xiàn)two-phase,比如有些系統(tǒng)使用first phase來禁用old configuration,從而不能處理client request;然后在second phase中使用new configuration。在Raft中,集群首先轉(zhuǎn)換到一個(gè)transitional configuration,我們稱作joint consensus;一旦joint consensus被committed之后,系統(tǒng)就過渡到new configuration。joint consensus 同時(shí)結(jié)合了old configuration和new configuration。
- log entry會(huì)被備份到兩個(gè)configuration的所有server中
- 來自任意一個(gè)configuration的server都可能會(huì)成為leader
- Agreement(election和entry的commitment)需要同時(shí)得到old configuration和new configuration的majority
joint consensus允許單個(gè)的server在不妥協(xié)安全性的情況下,在不同的時(shí)間對(duì)進(jìn)行configuration的過渡。另外,joint consensus允許集群在configuration轉(zhuǎn)換期間依舊能夠處理來自client的請(qǐng)求。
集群的configuration被存儲(chǔ)在replicated log的special entry中,并且通過它來通信;Figure 11說明了configuration改變的過程。當(dāng)leader收到了一個(gè)將configuration從Cold轉(zhuǎn)換到Cnew請(qǐng)求,它會(huì)將joint consensus的configuration(figure中的Cold,new)作為一個(gè)log entry存儲(chǔ)并且使用上文描述的機(jī)制進(jìn)行備份。一旦一個(gè)給定的server將一個(gè)new configuration entry加入它的log中,它就會(huì)在以后所有的decision中使用該configuration(server總是使用它log中的latest configuration,而不管該entry是否被committed)。這意味著leader會(huì)使用Cold,new來決定何時(shí)Cold,new被committed。如果該leader崩潰了,一個(gè)新的leader可能使用Cold或者Cold,new,這取決于winning candidate是否收到了Cold,new。在任何情況下,Cnew都不能在這個(gè)階段做單方面的決定。
?一旦Cold,new被committed,Cold或者Cnew就不能在沒有對(duì)方同意的情況下單獨(dú)做decision了,而Leader Completeness Property則確保了Cold,new的log entry的server才能被選作leader。現(xiàn)在leader創(chuàng)建一個(gè)描述Cnew的log entry并且將它備份到整個(gè)集群是安全的。同樣,這個(gè)configuration只要server看到它就會(huì)生效。當(dāng)新的configuration在Cnew的規(guī)則被committed時(shí),old configuration就不再有效了,而那些不在new configuration中的server就會(huì)被關(guān)閉。如Figure 11所示,沒有一個(gè)時(shí)刻,Cold或者Cnew會(huì)單方面做決定;這就保證了安全性。
對(duì)于reconfiguration還有三個(gè)問題需要處理。第一個(gè)問題是新加入的server可能初始的時(shí)候沒有存儲(chǔ)任何log entry。如果它們以這種狀態(tài)直接添加進(jìn)集群,可能會(huì)花費(fèi)相當(dāng)多的時(shí)間讓它們趕上來,而在這期間就不能commit新的log entry了。為了避免availability gaps,Raft在configuration change之前引入了一個(gè)additional phase,在這期間新的server作為non-voting member(leader將log entry向它們備份,但是在計(jì)算majority時(shí),并不考慮它們)加入集群。一旦新加入的server趕上了集群中的其他server之后,reconfiguration就會(huì)按照上面描述的步驟進(jìn)行。
第二個(gè)問題是集群的leader可能并不包含在new configuration中。在這種情況下,leader一旦commit了Cnew?log entry之后leader就會(huì)step down(返回follower的狀態(tài))。這意味著會(huì)有這樣一段時(shí)間(當(dāng)在commit Cnew)時(shí),leader可能會(huì)管理一個(gè)并不包含它自己的集群;它備份log entry,但是并不把它自己考慮在majority的計(jì)算中。leader的轉(zhuǎn)換會(huì)在Cnew被committed之后發(fā)生,因?yàn)檫@是第一次new configuration可以獨(dú)立運(yùn)行(總是可以在Cnew中選出一個(gè)leader)。在這之前,只有Cold中的server能被選為leader。
第三個(gè)問題是removed server(那些不在Cnew中的server)可能會(huì)破壞集群。這些server不會(huì)收到heartbeats,所以它們會(huì)timeout并且開始new election。于是它們會(huì)用新的term number發(fā)送RequestVote RPC,這會(huì)導(dǎo)致current leader恢復(fù)到follower的狀態(tài)。一個(gè)新的leader最終會(huì)被選舉出來,但是removed server還會(huì)再次timeout,而這個(gè)過程會(huì)不斷重復(fù),最終導(dǎo)致可用性非常差。
為了防止這樣的情況發(fā)生,server會(huì)無視RequestVote RPC,如果它們認(rèn)為current leader依舊存在的話。特別地,如果一個(gè)server在election timeout內(nèi)收到了一個(gè)RequestVote RPC,它不會(huì)更新它的term或者進(jìn)行投票。這不會(huì)影響正常的election,在開始election之前每個(gè)server都至少等待一個(gè)最小的election timeout。然而,這避免了removed server帶來的破壞;如果一個(gè)leader能夠從它的集群中得到heartbeat,那么它就不會(huì)受到更大的term number的影響。
7 Clients and log compaction
由于篇幅的原因本章就略過了,但是相關(guān)的資料在本論文的擴(kuò)展版中可以獲得。其中描述了client如何和Raft進(jìn)行交互,包括client怎么找到cluster leader以及Raft如何支持linearizable semantics。擴(kuò)展版本中還描述了如何利用snapshotting的方法回收replicated log的空間。這些問題在所有consensus-based system中都會(huì)出現(xiàn),Raft的解決方案和它們是類似的。
8 Implementation and evalution
我們已經(jīng)將Raft作為存儲(chǔ)RAMCloud配置信息的replicated state machine實(shí)現(xiàn)并且協(xié)助RAMCloud coordinator的故障轉(zhuǎn)移。Raft的實(shí)現(xiàn)大概包含2000行C++代碼,不包括測(cè)試,注釋以及空白行。源代碼可以自由獲取。同時(shí)還有25個(gè)基于本論文的關(guān)于Raft的獨(dú)立第三方開源實(shí)現(xiàn)。同時(shí),還有各種公司在部署Raft-based systems。本節(jié)的剩余部分將從可理解性,正確性以及性能三個(gè)標(biāo)準(zhǔn)來評(píng)估Raft。
....
10 Conclusion
算法的設(shè)計(jì)通常以正確性,效率以及簡(jiǎn)潔作為主要目標(biāo)。雖然這些目標(biāo)都是非常有意義的,但是我們認(rèn)為可理解性同樣重要。在開發(fā)者將算法實(shí)際實(shí)現(xiàn)以前,這一切都不可能實(shí)現(xiàn),而這些實(shí)現(xiàn)往往都會(huì)偏離或者擴(kuò)展算法的本意。除非開發(fā)者對(duì)算法有了深刻的理解并且能夠?qū)λ⒅庇X,否則將很難從它們的實(shí)現(xiàn)中獲得想要的特性。
一個(gè)被普遍接收但是難以理解的算法Paxos已經(jīng)困擾了學(xué)生和開發(fā)者很多年了,而在本篇論文中,我們解決了distributed consensus的這個(gè)問題。我們開發(fā)了一種新的算法,Raft,就像上面展示的,它比Paxos更加易于理解。我們同樣相信Raft為實(shí)際系統(tǒng)的構(gòu)建提供了一個(gè)更好的基礎(chǔ)。以可理解性作為主要目標(biāo)改變了我們對(duì)Raft的設(shè)計(jì);隨著設(shè)計(jì)的進(jìn)行我們發(fā)現(xiàn)我們?cè)诓粩嘀赜靡恍┘夹g(shù),例如解構(gòu)問題,以及簡(jiǎn)化狀態(tài)空間。這些技術(shù)不僅提高了Raft的可理解性,同時(shí)也更讓我們相信它的正確性。
總結(jié)
以上是生活随笔為你收集整理的《In Search of an Understandable Consensus Algorithm》翻译的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: git提交代码的两种方法步骤
- 下一篇: extern关键字讲解