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

最新內(nèi)容會(huì)更新在主站深入淺出區(qū)塊鏈社區(qū)
原文鏈接:尋找一種易于理解的一致性算法(擴(kuò)展版)

6 集群成員變化

到目前為止,我們都假設(shè)集群的配置(加入到一致性算法的服務(wù)器集合)是固定不變的。但是在實(shí)踐中,偶爾是會(huì)改變集群的配置的,例如替換那些宕機(jī)的機(jī)器或者改變復(fù)制級(jí)別。盡管可以通過暫停整個(gè)集群,更新所有配置,然后重啟整個(gè)集群的方式來實(shí)現(xiàn),但是在更改的時(shí)候集群會(huì)不可用。另外,如果存在手工操作步驟,那么就會(huì)有操作失誤的風(fēng)險(xiǎn)。為了避免這樣的問題,我們決定自動(dòng)化配置改變并且將其納入到 Raft 一致性算法中來。

為了讓配置修改機(jī)制能夠安全,那么在轉(zhuǎn)換的過程中不能夠存在任何時(shí)間點(diǎn)使得兩個(gè)領(lǐng)導(dǎo)人同時(shí)被選舉成功在同一個(gè)任期里。不幸的是,任何服務(wù)器直接從舊的配置直接轉(zhuǎn)換到新的配置的方案都是不安全的。一次性自動(dòng)的轉(zhuǎn)換所有服務(wù)器是不可能的,所以在轉(zhuǎn)換期間整個(gè)集群存在劃分成兩個(gè)獨(dú)立的大多數(shù)群體的可能性(見圖 10)。

圖 10

圖 10:直接從一種配置轉(zhuǎn)到新的配置是十分不安全的,因?yàn)楦鱾€(gè)機(jī)器可能在任何的時(shí)候進(jìn)行轉(zhuǎn)換。在這個(gè)例子中,集群配額從 3 臺(tái)機(jī)器變成了 5 臺(tái)。不幸的是,存在這樣的一個(gè)時(shí)間點(diǎn),兩個(gè)不同的領(lǐng)導(dǎo)人在同一個(gè)任期里都可以被選舉成功。一個(gè)是通過舊的配置,一個(gè)通過新的配置。

為了保證安全性,配置更改必須使用兩階段方法。目前有很多種兩階段的實(shí)現(xiàn)。例如,有些系統(tǒng)在第一階段停掉舊的配置所以集群就不能處理客戶端請(qǐng)求;然后在第二階段在啟用新的配置。在 Raft 中,集群先切換到一個(gè)過渡的配置,我們稱之為共同一致;一旦共同一致已經(jīng)被提交了,那么系統(tǒng)就切換到新的配置上。共同一致是老配置和新配置的結(jié)合:

  • 日志條目被復(fù)制給集群中新、老配置的所有服務(wù)器。
  • 新、舊配置的服務(wù)器都可以成為領(lǐng)導(dǎo)人。
  • 達(dá)成一致(針對(duì)選舉和提交)需要分別在兩種配置上獲得大多數(shù)的支持。

共同一致允許獨(dú)立的服務(wù)器在不影響安全性的前提下,在不同的時(shí)間進(jìn)行配置轉(zhuǎn)換過程。此外,共同一致可以讓集群在配置轉(zhuǎn)換的過程人依然響應(yīng)客戶端的請(qǐng)求。

集群配置在復(fù)制日志中以特殊的日志條目來存儲(chǔ)和通信;圖 11 展示了配置轉(zhuǎn)換的過程。當(dāng)一個(gè)領(lǐng)導(dǎo)人接收到一個(gè)改變配置從 C-old 到 C-new 的請(qǐng)求,他會(huì)為了共同一致存儲(chǔ)配置(圖中的 C-old,new),以前面描述的日志條目和副本的形式。一旦一個(gè)服務(wù)器將新的配置日志條目增加到它的日志中,他就會(huì)用這個(gè)配置來做出未來所有的決定(服務(wù)器總是使用最新的配置,無論他是否已經(jīng)被提交)。這意味著領(lǐng)導(dǎo)人要使用 C-old,new 的規(guī)則來決定日志條目 C-old,new 什么時(shí)候需要被提交。如果領(lǐng)導(dǎo)人崩潰了,被選出來的新領(lǐng)導(dǎo)人可能是使用 C-old 配置也可能是 C-old,new 配置,這取決于贏得選舉的候選人是否已經(jīng)接收到了 C-old,new 配置。在任何情況下, C-new 配置在這一時(shí)期都不會(huì)單方面的做出決定。

一旦 C-old,new 被提交,那么無論是 C-old 還是 C-new,在沒有經(jīng)過他人批準(zhǔn)的情況下都不可能做出決定,并且領(lǐng)導(dǎo)人完全特性保證了只有擁有 C-old,new 日志條目的服務(wù)器才有可能被選舉為領(lǐng)導(dǎo)人。這個(gè)時(shí)候,領(lǐng)導(dǎo)人創(chuàng)建一條關(guān)于 C-new 配置的日志條目并復(fù)制給集群就是安全的了。再者,每個(gè)服務(wù)器在見到新的配置的時(shí)候就會(huì)立即生效。當(dāng)新的配置在 C-new 的規(guī)則下被提交,舊的配置就變得無關(guān)緊要,同時(shí)不使用新的配置的服務(wù)器就可以被關(guān)閉了。如圖 11,C-old 和 C-new 沒有任何機(jī)會(huì)同時(shí)做出單方面的決定;這保證了安全性。

圖 11

圖 11:一個(gè)配置切換的時(shí)間線。虛線表示已經(jīng)被創(chuàng)建但是還沒有被提交的條目,實(shí)線表示最后被提交的日志條目。領(lǐng)導(dǎo)人首先創(chuàng)建了 C-old,new 的配置條目在自己的日志中,并提交到 C-old,new 中(C-old 的大多數(shù)和 C-new 的大多數(shù))。然后他創(chuàng)建 C-new 條目并提交到 C-new 中的大多數(shù)。這樣就不存在 C-new 和 C-old 可以同時(shí)做出決定的時(shí)間點(diǎn)。

在關(guān)于重新配置還有三個(gè)問題需要提出。第一個(gè)問題是,新的服務(wù)器可能初始化沒有存儲(chǔ)任何的日志條目。當(dāng)這些服務(wù)器以這種狀態(tài)加入到集群中,那么他們需要一段時(shí)間來更新追趕,這時(shí)還不能提交新的日志條目。為了避免這種可用性的間隔時(shí)間,Raft 在配置更新的時(shí)候使用了一種額外的階段,在這個(gè)階段,新的服務(wù)器以沒有投票權(quán)身份加入到集群中來(領(lǐng)導(dǎo)人復(fù)制日志給他們,但是不考慮他們是大多數(shù))。一旦新的服務(wù)器追趕上了集群中的其他機(jī)器,重新配置可以像上面描述的一樣處理。

第二個(gè)問題是,集群的領(lǐng)導(dǎo)人可能不是新配置的一員。在這種情況下,領(lǐng)導(dǎo)人就會(huì)在提交了 C-new 日志之后退位(回到跟隨者狀態(tài))。這意味著有這樣的一段時(shí)間,領(lǐng)導(dǎo)人管理著集群,但是不包括他自己;他復(fù)制日志但是不把他自己算作是大多數(shù)之一。當(dāng) C-new 被提交時(shí),會(huì)發(fā)生領(lǐng)導(dǎo)人過渡,因?yàn)檫@時(shí)是最早新的配置可以獨(dú)立工作的時(shí)間點(diǎn)(將總是能夠在 C-new 配置下選出新的領(lǐng)導(dǎo)人)。在此之前,可能只能從 C-old 中選出領(lǐng)導(dǎo)人。

第三個(gè)問題是,移除不在 C-new 中的服務(wù)器可能會(huì)擾亂集群。這些服務(wù)器將不會(huì)再接收到心跳,所以當(dāng)選舉超時(shí),他們就會(huì)進(jìn)行新的選舉過程。他們會(huì)發(fā)送擁有新的任期號(hào)的請(qǐng)求投票 RPCs,這樣會(huì)導(dǎo)致當(dāng)前的領(lǐng)導(dǎo)人回退成跟隨者狀態(tài)。新的領(lǐng)導(dǎo)人最終會(huì)被選出來,但是被移除的服務(wù)器將會(huì)再次超時(shí),然后這個(gè)過程會(huì)再次重復(fù),導(dǎo)致整體可用性大幅降低。

為了避免這個(gè)問題,當(dāng)服務(wù)器確認(rèn)當(dāng)前領(lǐng)導(dǎo)人存在時(shí),服務(wù)器會(huì)忽略請(qǐng)求投票 RPCs。特別的,當(dāng)服務(wù)器在當(dāng)前最小選舉超時(shí)時(shí)間內(nèi)收到一個(gè)請(qǐng)求投票 RPC,他不會(huì)更新當(dāng)前的任期號(hào)或者投出選票。這不會(huì)影響正常的選舉,每個(gè)服務(wù)器在開始一次選舉之前,至少等待一個(gè)最小選舉超時(shí)時(shí)間。然而,這有利于避免被移除的服務(wù)器擾亂:如果領(lǐng)導(dǎo)人能夠發(fā)送心跳給集群,那么他就不會(huì)被更大的任期號(hào)廢黜。

7 日志壓縮

Raft 的日志在正常操作中不斷的增長,但是在實(shí)際的系統(tǒng)中,日志不能無限制的增長。隨著日志不斷增長,他會(huì)占用越來越多的空間,花費(fèi)越來越多的時(shí)間來重置。如果沒有一定的機(jī)制去清除日志里積累的陳舊的信息,那么會(huì)帶來可用性問題。

快照是最簡單的壓縮方法。在快照系統(tǒng)中,整個(gè)系統(tǒng)的狀態(tài)都以快照的形式寫入到穩(wěn)定的持久化存儲(chǔ)中,然后到那個(gè)時(shí)間點(diǎn)之前的日志全部丟棄。快照技術(shù)被使用在 Chubby 和 ZooKeeper 中,接下來的章節(jié)會(huì)介紹 Raft 中的快照技術(shù)。

增量壓縮的方法,例如日志清理或者日志結(jié)構(gòu)合并樹,都是可行的。這些方法每次只對(duì)一小部分?jǐn)?shù)據(jù)進(jìn)行操作,這樣就分散了壓縮的負(fù)載壓力。首先,他們先選擇一個(gè)已經(jīng)積累的大量已經(jīng)被刪除或者被覆蓋對(duì)象的區(qū)域,然后重寫那個(gè)區(qū)域還活躍的對(duì)象,之后釋放那個(gè)區(qū)域。和簡單操作整個(gè)數(shù)據(jù)集合的快照相比,需要增加復(fù)雜的機(jī)制來實(shí)現(xiàn)。狀態(tài)機(jī)可以實(shí)現(xiàn) LSM tree 使用和快照相同的接口,但是日志清除方法就需要修改 Raft 了。

圖 12

圖 12:一個(gè)服務(wù)器用新的快照替換了從 1 到 5 的條目,快照值存儲(chǔ)了當(dāng)前的狀態(tài)。快照中包含了最后的索引位置和任期號(hào)。

圖 12 展示了 Raft 中快照的基礎(chǔ)思想。每個(gè)服務(wù)器獨(dú)立的創(chuàng)建快照,只包括已經(jīng)被提交的日志。主要的工作包括將狀態(tài)機(jī)的狀態(tài)寫入到快照中。Raft 也包含一些少量的元數(shù)據(jù)到快照中:最后被包含索引指的是被快照取代的最后的條目在日志中的索引值(狀態(tài)機(jī)最后應(yīng)用的日志),最后被包含的任期指的是該條目的任期號(hào)。保留這些數(shù)據(jù)是為了支持快照后緊接著的第一個(gè)條目的附加日志請(qǐng)求時(shí)的一致性檢查,因?yàn)檫@個(gè)條目需要前一日志條目的索引值和任期號(hào)。為了支持集群成員更新(第 6 節(jié)),快照中也將最后的一次配置作為最后一個(gè)條目存下來。一旦服務(wù)器完成一次快照,他就可以刪除最后索引位置之前的所有日志和快照了。

盡管通常服務(wù)器都是獨(dú)立的創(chuàng)建快照,但是領(lǐng)導(dǎo)人必須偶爾的發(fā)送快照給一些落后的跟隨者。這通常發(fā)生在當(dāng)領(lǐng)導(dǎo)人已經(jīng)丟棄了下一條需要發(fā)送給跟隨者的日志條目的時(shí)候。幸運(yùn)的是這種情況不是常規(guī)操作:一個(gè)與領(lǐng)導(dǎo)人保持同步的跟隨者通常都會(huì)有這個(gè)條目。然而一個(gè)運(yùn)行非常緩慢的跟隨者或者新加入集群的服務(wù)器(第 6 節(jié))將不會(huì)有這個(gè)條目。這時(shí)讓這個(gè)跟隨者更新到最新的狀態(tài)的方式就是通過網(wǎng)絡(luò)把快照發(fā)送給他們。

安裝快照 RPC

由領(lǐng)導(dǎo)人調(diào)用以將快照的分塊發(fā)送給跟隨者。領(lǐng)導(dǎo)者總是按順序發(fā)送分塊。

參數(shù) 解釋
term 領(lǐng)導(dǎo)人的任期號(hào)
leaderId 領(lǐng)導(dǎo)人的 Id,以便于跟隨者重定向請(qǐng)求
lastIncludedIndex 快照中包含的最后日志條目的索引值
lastIncludedTerm 快照中包含的最后日志條目的任期號(hào)
offset 分塊在快照中的字節(jié)偏移量
data[] 原始數(shù)據(jù)
done 如果這是最后一個(gè)分塊則為 true
結(jié)果 解釋
term 當(dāng)前任期號(hào)(currentTerm),便于領(lǐng)導(dǎo)人更新自己

接收者實(shí)現(xiàn)

  1. 如果term < currentTerm就立即回復(fù)
  2. 如果是第一個(gè)分塊(offset 為 0)就創(chuàng)建一個(gè)新的快照
  3. 在指定偏移量寫入數(shù)據(jù)
  4. 如果 done 是 false,則繼續(xù)等待更多的數(shù)據(jù)
  5. 保存快照文件,丟棄具有較小索引的任何現(xiàn)有或部分快照
  6. 如果現(xiàn)存的日志條目與快照中最后包含的日志條目具有相同的索引值和任期號(hào),則保留其后的日志條目并進(jìn)行回復(fù)
  7. 丟棄整個(gè)日志
  8. 使用快照重置狀態(tài)機(jī)(并加載快照的集群配置)
圖 13

圖 13:一個(gè)關(guān)于安裝快照的簡要概述。為了便于傳輸,快照都是被分成分塊的;每個(gè)分塊都給了跟隨者生命的跡象,所以跟隨者可以重置選舉超時(shí)計(jì)時(shí)器。

在這種情況下領(lǐng)導(dǎo)人使用一種叫做安裝快照的新的 RPC 來發(fā)送快照給太落后的跟隨者;見圖 13。當(dāng)跟隨者通過這種 RPC 接收到快照時(shí),他必須自己決定對(duì)于已經(jīng)存在的日志該如何處理。通常快照會(huì)包含沒有在接收者日志中存在的信息。在這種情況下,跟隨者丟棄其整個(gè)日志;它全部被快照取代,并且可能包含與快照沖突的未提交條目。如果接收到的快照是自己日志的前面部分(由于網(wǎng)絡(luò)重傳或者錯(cuò)誤),那么被快照包含的條目將會(huì)被全部刪除,但是快照后面的條目仍然有效,必須保留。

這種快照的方式背離了 Raft 的強(qiáng)領(lǐng)導(dǎo)人原則,因?yàn)楦S者可以在不知道領(lǐng)導(dǎo)人情況下創(chuàng)建快照。但是我們認(rèn)為這種背離是值得的。領(lǐng)導(dǎo)人的存在,是為了解決在達(dá)成一致性的時(shí)候的沖突,但是在創(chuàng)建快照的時(shí)候,一致性已經(jīng)達(dá)成,這時(shí)不存在沖突了,所以沒有領(lǐng)導(dǎo)人也是可以的。數(shù)據(jù)依然是從領(lǐng)導(dǎo)人傳給跟隨者,只是跟隨者可以重新組織他們的數(shù)據(jù)了。

我們考慮過一種替代的基于領(lǐng)導(dǎo)人的快照方案,即只有領(lǐng)導(dǎo)人創(chuàng)建快照,然后發(fā)送給所有的跟隨者。但是這樣做有兩個(gè)缺點(diǎn)。第一,發(fā)送快照會(huì)浪費(fèi)網(wǎng)絡(luò)帶寬并且延緩了快照處理的時(shí)間。每個(gè)跟隨者都已經(jīng)擁有了所有產(chǎn)生快照需要的信息,而且很顯然,自己從本地的狀態(tài)中創(chuàng)建快照比通過網(wǎng)絡(luò)接收別人發(fā)來的要經(jīng)濟(jì)。第二,領(lǐng)導(dǎo)人的實(shí)現(xiàn)會(huì)更加復(fù)雜。例如,領(lǐng)導(dǎo)人需要發(fā)送快照的同時(shí)并行的將新的日志條目發(fā)送給跟隨者,這樣才不會(huì)阻塞新的客戶端請(qǐng)求。

還有兩個(gè)問題影響了快照的性能。首先,服務(wù)器必須決定什么時(shí)候應(yīng)該創(chuàng)建快照。如果快照創(chuàng)建的過于頻繁,那么就會(huì)浪費(fèi)大量的磁盤帶寬和其他資源;如果創(chuàng)建快照頻率太低,他就要承受耗盡存儲(chǔ)容量的風(fēng)險(xiǎn),同時(shí)也增加了從日志重建的時(shí)間。一個(gè)簡單的策略就是當(dāng)日志大小達(dá)到一個(gè)固定大小的時(shí)候就創(chuàng)建一次快照。如果這個(gè)閾值設(shè)置的顯著大于期望的快照的大小,那么快照對(duì)磁盤壓力的影響就會(huì)很小了。

第二個(gè)影響性能的問題就是寫入快照需要花費(fèi)顯著的一段時(shí)間,并且我們還不希望影響到正常操作。解決方案是通過寫時(shí)復(fù)制的技術(shù),這樣新的更新就可以被接收而不影響到快照。例如,具有函數(shù)式數(shù)據(jù)結(jié)構(gòu)的狀態(tài)機(jī)天然支持這樣的功能。另外,操作系統(tǒng)的寫時(shí)復(fù)制技術(shù)的支持(如 Linux 上的 fork)可以被用來創(chuàng)建完整的狀態(tài)機(jī)的內(nèi)存快照(我們的實(shí)現(xiàn)就是這樣的)。

8 客戶端交互

這一節(jié)將介紹客戶端是如何和 Raft 進(jìn)行交互的,包括客戶端如何發(fā)現(xiàn)領(lǐng)導(dǎo)人和 Raft 是如何支持線性化語義的。這些問題對(duì)于所有基于一致性的系統(tǒng)都存在,并且 Raft 的解決方案和其他的也差不多。

Raft 中的客戶端發(fā)送所有請(qǐng)求給領(lǐng)導(dǎo)人。當(dāng)客戶端啟動(dòng)的時(shí)候,他會(huì)隨機(jī)挑選一個(gè)服務(wù)器進(jìn)行通信。如果客戶端第一次挑選的服務(wù)器不是領(lǐng)導(dǎo)人,那么那個(gè)服務(wù)器會(huì)拒絕客戶端的請(qǐng)求并且提供他最近接收到的領(lǐng)導(dǎo)人的信息(附加條目請(qǐng)求包含了領(lǐng)導(dǎo)人的網(wǎng)絡(luò)地址)。如果領(lǐng)導(dǎo)人已經(jīng)崩潰了,那么客戶端的請(qǐng)求就會(huì)超時(shí);客戶端之后會(huì)再次重試隨機(jī)挑選服務(wù)器的過程。

我們 Raft 的目標(biāo)是要實(shí)現(xiàn)線性化語義(每一次操作立即執(zhí)行,只執(zhí)行一次,在他調(diào)用和收到回復(fù)之間)。但是,如上述,Raft 是可以執(zhí)行同一條命令多次的:例如,如果領(lǐng)導(dǎo)人在提交了這條日志之后,但是在響應(yīng)客戶端之前崩潰了,那么客戶端會(huì)和新的領(lǐng)導(dǎo)人重試這條指令,導(dǎo)致這條命令就被再次執(zhí)行了。解決方案就是客戶端對(duì)于每一條指令都賦予一個(gè)唯一的序列號(hào)。然后,狀態(tài)機(jī)跟蹤每條指令最新的序列號(hào)和相應(yīng)的響應(yīng)。如果接收到一條指令,它的序列號(hào)已經(jīng)被執(zhí)行了,那么就立即返回結(jié)果,而不重新執(zhí)行指令。

只讀的操作可以直接處理而不需要記錄日志。但是,在不增加任何限制的情況下,這么做可能會(huì)冒著返回臟數(shù)據(jù)的風(fēng)險(xiǎn),因?yàn)轭I(lǐng)導(dǎo)人響應(yīng)客戶端請(qǐng)求時(shí)可能已經(jīng)被新的領(lǐng)導(dǎo)人作廢了,但是他還不知道。線性化的讀操作必須不能返回臟數(shù)據(jù),Raft 需要使用兩個(gè)額外的措施在不使用日志的情況下保證這一點(diǎn)。首先,領(lǐng)導(dǎo)人必須有關(guān)于被提交日志的最新信息。領(lǐng)導(dǎo)人完全特性保證了領(lǐng)導(dǎo)人一定擁有所有已經(jīng)被提交的日志條目,但是在他任期開始的時(shí)候,他可能不知道那些是已經(jīng)被提交的。為了知道這些信息,他需要在他的任期里提交一條日志條目。Raft 中通過領(lǐng)導(dǎo)人在任期開始的時(shí)候提交一個(gè)空白的沒有任何操作的日志條目到日志中去來實(shí)現(xiàn)。第二,領(lǐng)導(dǎo)人在處理只讀的請(qǐng)求之前必須檢查自己是否已經(jīng)被廢黜了(他自己的信息已經(jīng)變臟了如果一個(gè)更新的領(lǐng)導(dǎo)人被選舉出來)。Raft 中通過讓領(lǐng)導(dǎo)人在響應(yīng)只讀請(qǐng)求之前,先和集群中的大多數(shù)節(jié)點(diǎn)交換一次心跳信息來處理這個(gè)問題。可選的,領(lǐng)導(dǎo)人可以依賴心跳機(jī)制來實(shí)現(xiàn)一種租約的機(jī)制,但是這種方法依賴時(shí)間來保證安全性(假設(shè)時(shí)間誤差是有界的)。

9 算法實(shí)現(xiàn)和評(píng)估

我們已經(jīng)為 RAMCloud 實(shí)現(xiàn)了 Raft 算法作為存儲(chǔ)配置信息的復(fù)制狀態(tài)機(jī)的一部分,并且?guī)椭?RAMCloud 協(xié)調(diào)故障轉(zhuǎn)移。這個(gè) Raft 實(shí)現(xiàn)包含大約 2000 行 C++ 代碼,其中不包括測試、注釋和空行。這些代碼是開源的。同時(shí)也有大約 25 個(gè)其他獨(dú)立的第三方的基于這篇論文草稿的開源實(shí)現(xiàn),針對(duì)不同的開發(fā)場景。同時(shí),很多公司已經(jīng)部署了基于 Raft 的系統(tǒng)。

這一節(jié)會(huì)從三個(gè)方面來評(píng)估 Raft 算法:可理解性、正確性和性能。

9.1 可理解性

為了和 Paxos 比較 Raft 算法的可理解能力,我們針對(duì)高層次的本科生和研究生,在斯坦福大學(xué)的高級(jí)操作系統(tǒng)課程和加州大學(xué)伯克利分校的分布式計(jì)算課程上,進(jìn)行了一次學(xué)習(xí)的實(shí)驗(yàn)。我們分別拍了針對(duì) Raft 和 Paxos 的視頻課程,并準(zhǔn)備了相應(yīng)的小測驗(yàn)。Raft 的視頻講課覆蓋了這篇論文的所有內(nèi)容除了日志壓縮;Paxos 講課包含了足夠的資料來創(chuàng)建一個(gè)等價(jià)的復(fù)制狀態(tài)機(jī),包括單決策 Paxos,多決策 Paxos,重新配置和一些實(shí)際系統(tǒng)需要的性能優(yōu)化(例如領(lǐng)導(dǎo)人選舉)。小測驗(yàn)測試一些對(duì)算法的基本理解和解釋一些邊角的示例。每個(gè)學(xué)生都是看完第一個(gè)視頻,回答相應(yīng)的測試,再看第二個(gè)視頻,回答相應(yīng)的測試。大約有一半的學(xué)生先進(jìn)行 Paxos 部分,然后另一半先進(jìn)行 Raft 部分,這是為了說明兩者從第一部分的算法學(xué)習(xí)中獲得的表現(xiàn)和經(jīng)驗(yàn)的差異。我們計(jì)算參加人員的每一個(gè)小測驗(yàn)的得分來看參與者是否在 Raft 算法上更加容易理解。

我們盡可能的使得 Paxos 和 Raft 的比較更加公平。這個(gè)實(shí)驗(yàn)偏愛 Paxos 表現(xiàn)在兩個(gè)方面:43 個(gè)參加者中有 15 個(gè)人在之前有一些 Paxos 的經(jīng)驗(yàn),并且 Paxos 的視頻要長 14%。如表格 1 總結(jié)的那樣,我們采取了一些措施來減輕這種潛在的偏見。我們所有的材料都可供審查。

關(guān)心 緩和偏見采取的手段 可供查看的材料
相同的講課質(zhì)量 兩者使用同一個(gè)講師。Paxos 使用的是現(xiàn)在很多大學(xué)里經(jīng)常使用的。Paxos 會(huì)長 14%。 視頻
相同的測驗(yàn)難度 問題以難度分組,在兩個(gè)測驗(yàn)里成對(duì)出現(xiàn)。 小測驗(yàn)
公平評(píng)分 使用評(píng)價(jià)量規(guī)。隨機(jī)順序打分,兩個(gè)測驗(yàn)交替進(jìn)行。 評(píng)價(jià)量規(guī)(rubric)

表 1:考慮到可能會(huì)存在的偏見,對(duì)于每種情況的解決方法,和相應(yīng)的材料。

參加者平均在 Raft 的測驗(yàn)中比 Paxos 高 4.9 分(總分 60,那么 Raft 的平均得分是 25.7,而 Paxos 是 20.8);圖 14 展示了每個(gè)參與者的得分。配置t-檢驗(yàn)(又稱student‘s t-test)表明,在 95% 的可信度下,真實(shí)的 Raft 分?jǐn)?shù)分布至少比 Paxos 高 2.5 分。

圖 14

圖 14:一個(gè)散點(diǎn)圖表示了 43 個(gè)學(xué)生在 Paxos 和 Raft 的小測驗(yàn)中的成績。在對(duì)角線之上的點(diǎn)表示在 Raft 獲得了更高分?jǐn)?shù)的學(xué)生。

我們也建立了一個(gè)線性回歸模型來預(yù)測一個(gè)新的學(xué)生的測驗(yàn)成績,基于以下三個(gè)因素:他們使用的是哪個(gè)小測驗(yàn),之前對(duì) Paxos 的經(jīng)驗(yàn),和學(xué)習(xí)算法的順序。模型預(yù)測,對(duì)小測驗(yàn)的選擇會(huì)產(chǎn)生 12.5 分的差別。這顯著的高于之前的 4.9 分,因?yàn)楹芏鄬W(xué)生在之前都已經(jīng)有了對(duì)于 Paxos 的經(jīng)驗(yàn),這相當(dāng)明顯的幫助 Paxos,對(duì) Raft 就沒什么太大影響了。但是奇怪的是,模型預(yù)測對(duì)于先進(jìn)行 Paxos 小測驗(yàn)的人而言,Raft的得分低了6.3分; 雖然我們不知道為什么,這似乎在統(tǒng)計(jì)上是有意義的。

我們同時(shí)也在測驗(yàn)之后調(diào)查了參與者,他們認(rèn)為哪個(gè)算法更加容易實(shí)現(xiàn)和解釋;這個(gè)的結(jié)果在圖 15 上。壓倒性的結(jié)果表明 Raft 算法更加容易實(shí)現(xiàn)和解釋(41 人中的 33個(gè))。但是,這種自己報(bào)告的結(jié)果不如參與者的成績更加可信,并且參與者可能因?yàn)槲覀兊?Raft 更加易于理解的假說而產(chǎn)生偏見。

圖 15

圖 15:通過一個(gè) 5 分制的問題,參與者(左邊)被問哪個(gè)算法他們覺得在一個(gè)高效正確的系統(tǒng)里更容易實(shí)現(xiàn),右邊被問哪個(gè)更容易向?qū)W生解釋。

關(guān)于 Raft 用戶學(xué)習(xí)有一個(gè)更加詳細(xì)的討論。

9.2 正確性

在第 5 節(jié),我們已經(jīng)制定了正式的規(guī)范,和對(duì)一致性機(jī)制的安全性證明。這個(gè)正式規(guī)范使用 TLA+ 規(guī)范語言使圖 2 中總結(jié)的信息非常清晰。它長約400行,并作為證明的主題。同時(shí)對(duì)于任何想實(shí)現(xiàn) Raft 的人也是十分有用的。我們通過 TLA 證明系統(tǒng)非常機(jī)械的證明了日志完全特性。然而,這個(gè)證明依賴的約束前提還沒有被機(jī)械證明(例如,我們還沒有證明規(guī)范的類型安全)。而且,我們已經(jīng)寫了一個(gè)非正式的證明關(guān)于狀態(tài)機(jī)安全性是完備的,并且是相當(dāng)清晰的(大約 3500 個(gè)詞)。

9.3 性能

Raft 和其他一致性算法例如 Paxos 有著差不多的性能。在性能方面,最重要的關(guān)注點(diǎn)是,當(dāng)領(lǐng)導(dǎo)人被選舉成功時(shí),什么時(shí)候復(fù)制新的日志條目。Raft 通過很少數(shù)量的消息包(一輪從領(lǐng)導(dǎo)人到集群大多數(shù)機(jī)器的消息)就達(dá)成了這個(gè)目的。同時(shí),進(jìn)一步提升 Raft 的性能也是可行的。例如,很容易通過支持批量操作和管道操作來提高吞吐量和降低延遲。對(duì)于其他一致性算法已經(jīng)提出過很多性能優(yōu)化方案;其中有很多也可以應(yīng)用到 Raft 中來,但是我們暫時(shí)把這個(gè)問題放到未來的工作中去。

我們使用我們自己的 Raft 實(shí)現(xiàn)來衡量 Raft 領(lǐng)導(dǎo)人選舉的性能并且回答兩個(gè)問題。首先,領(lǐng)導(dǎo)人選舉的過程收斂是否快速?第二,在領(lǐng)導(dǎo)人宕機(jī)之后,最小的系統(tǒng)宕機(jī)時(shí)間是多久?

圖 16

圖 16:發(fā)現(xiàn)并替換一個(gè)已經(jīng)崩潰的領(lǐng)導(dǎo)人的時(shí)間。上面的圖考察了在選舉超時(shí)時(shí)間上的隨機(jī)化程度,下面的圖考察了最小選舉超時(shí)時(shí)間。每條線代表了 1000 次實(shí)驗(yàn)(除了 150-150 毫秒只試了 100 次),和相應(yīng)的確定的選舉超時(shí)時(shí)間。例如,150-155 毫秒意思是,選舉超時(shí)時(shí)間從這個(gè)區(qū)間范圍內(nèi)隨機(jī)選擇并確定下來。這個(gè)實(shí)驗(yàn)在一個(gè)擁有 5 個(gè)節(jié)點(diǎn)的集群上進(jìn)行,其廣播時(shí)延大約是 15 毫秒。對(duì)于 9 個(gè)節(jié)點(diǎn)的集群,結(jié)果也差不多。

為了衡量領(lǐng)導(dǎo)人選舉,我們反復(fù)的使一個(gè)擁有五個(gè)節(jié)點(diǎn)的服務(wù)器集群的領(lǐng)導(dǎo)人宕機(jī),并計(jì)算需要多久才能發(fā)現(xiàn)領(lǐng)導(dǎo)人已經(jīng)宕機(jī)并選出一個(gè)新的領(lǐng)導(dǎo)人(見圖 16)。為了構(gòu)建一個(gè)最壞的場景,在每一的嘗試?yán)铮?wù)器都有不同長度的日志,意味著有些候選人是沒有成為領(lǐng)導(dǎo)人的資格的。另外,為了促成選票瓜分的情況,我們的測試腳本在終止領(lǐng)導(dǎo)人之前同步的發(fā)送了一次心跳廣播(這大約和領(lǐng)導(dǎo)人在崩潰前復(fù)制一個(gè)新的日志給其他機(jī)器很像)。領(lǐng)導(dǎo)人均勻的隨機(jī)的在心跳間隔里宕機(jī),也就是最小選舉超時(shí)時(shí)間的一半。因此,最小宕機(jī)時(shí)間大約就是最小選舉超時(shí)時(shí)間的一半。

圖 16 中上面的圖表明,只需要在選舉超時(shí)時(shí)間上使用很少的隨機(jī)化就可以大大避免選票被瓜分的情況。在沒有隨機(jī)化的情況下,在我們的測試?yán)铮x舉過程往往都需要花費(fèi)超過 10 秒鐘由于太多的選票瓜分的情況。僅僅增加 5 毫秒的隨機(jī)化時(shí)間,就大大的改善了選舉過程,現(xiàn)在平均的宕機(jī)時(shí)間只有 287 毫秒。增加更多的隨機(jī)化時(shí)間可以大大改善最壞情況:通過增加 50 毫秒的隨機(jī)化時(shí)間,最壞的完成情況(1000 次嘗試)只要 513 毫秒。

圖 16 中下面的圖顯示,通過減少選舉超時(shí)時(shí)間可以減少系統(tǒng)的宕機(jī)時(shí)間。在選舉超時(shí)時(shí)間為 12-24 毫秒的情況下,只需要平均 35 毫秒就可以選舉出新的領(lǐng)導(dǎo)人(最長的一次花費(fèi)了 152 毫秒)。然而,進(jìn)一步降低選舉超時(shí)時(shí)間的話就會(huì)違反 Raft 的時(shí)間不等式需求:在選舉新領(lǐng)導(dǎo)人之前,領(lǐng)導(dǎo)人就很難發(fā)送完心跳包。這會(huì)導(dǎo)致沒有意義的領(lǐng)導(dǎo)人改變并降低了系統(tǒng)整體的可用性。我們建議使用更為保守的選舉超時(shí)時(shí)間,比如 150-300 毫秒;這樣的時(shí)間不大可能導(dǎo)致沒有意義的領(lǐng)導(dǎo)人改變,而且依然提供不錯(cuò)的可用性。

10 相關(guān)工作

已經(jīng)有很多關(guān)于一致性算法的工作被發(fā)表出來,其中很多都可以歸到下面的類別中:

  • Lamport 關(guān)于 Paxos 的原始描述,和嘗試描述的更清晰。
  • 關(guān)于 Paxos 的更詳盡的描述,補(bǔ)充遺漏的細(xì)節(jié)并修改算法,使得可以提供更加容易的實(shí)現(xiàn)基礎(chǔ)。
  • 實(shí)現(xiàn)一致性算法的系統(tǒng),例如 Chubby,ZooKeeper 和 Spanner。對(duì)于 Chubby 和 Spanner 的算法并沒有公開發(fā)表其技術(shù)細(xì)節(jié),盡管他們都聲稱是基于 Paxos 的。ZooKeeper 的算法細(xì)節(jié)已經(jīng)發(fā)表,但是和 Paxos 著實(shí)有著很大的差別。
  • Paxos 可以應(yīng)用的性能優(yōu)化。
  • Oki 和 Liskov 的 Viewstamped Replication(VR),一種和 Paxos 差不多的替代算法。原始的算法描述和分布式傳輸協(xié)議耦合在了一起,但是核心的一致性算法在最近的更新里被分離了出來。VR 使用了一種基于領(lǐng)導(dǎo)人的方法,和 Raft 有很多相似之處。

Raft 和 Paxos 最大的不同之處就在于 Raft 的強(qiáng)領(lǐng)導(dǎo)特性:Raft 使用領(lǐng)導(dǎo)人選舉作為一致性協(xié)議里必不可少的部分,并且將盡可能多的功能集中到了領(lǐng)導(dǎo)人身上。這樣就可以使得算法更加容易理解。例如,在 Paxos 中,領(lǐng)導(dǎo)人選舉和基本的一致性協(xié)議是正交的:領(lǐng)導(dǎo)人選舉僅僅是性能優(yōu)化的手段,而且不是一致性所必須要求的。但是,這樣就增加了多余的機(jī)制:Paxos 同時(shí)包含了針對(duì)基本一致性要求的兩階段提交協(xié)議和針對(duì)領(lǐng)導(dǎo)人選舉的獨(dú)立的機(jī)制。相比較而言,Raft 就直接將領(lǐng)導(dǎo)人選舉納入到一致性算法中,并作為兩階段一致性的第一步。這樣就減少了很多機(jī)制。

像 Raft 一樣,VR 和 ZooKeeper 也是基于領(lǐng)導(dǎo)人的,因此他們也擁有一些 Raft 的優(yōu)點(diǎn)。但是,Raft 比 VR 和 ZooKeeper 擁有更少的機(jī)制因?yàn)?Raft 盡可能的減少了非領(lǐng)導(dǎo)人的功能。例如,Raft 中日志條目都遵循著從領(lǐng)導(dǎo)人發(fā)送給其他人這一個(gè)方向:附加條目 RPC 是向外發(fā)送的。在 VR 中,日志條目的流動(dòng)是雙向的(領(lǐng)導(dǎo)人可以在選舉過程中接收日志);這就導(dǎo)致了額外的機(jī)制和復(fù)雜性。根據(jù) ZooKeeper 公開的資料看,它的日志條目也是雙向傳輸?shù)模撬膶?shí)現(xiàn)更像 Raft。

和上述我們提及的其他基于一致性的日志復(fù)制算法中,Raft 的消息類型更少。例如,我們數(shù)了一下 VR 和 ZooKeeper 使用的用來基本一致性需要和成員改變的消息數(shù)(排除了日志壓縮和客戶端交互,因?yàn)檫@些都比較獨(dú)立且和算法關(guān)系不大)。VR 和 ZooKeeper 都分別定義了 10 中不同的消息類型,相對(duì)的,Raft 只有 4 中消息類型(兩種 RPC 請(qǐng)求和對(duì)應(yīng)的響應(yīng))。Raft 的消息都稍微比其他算法的要信息量大,但是都很簡單。另外,VR 和 ZooKeeper 都在領(lǐng)導(dǎo)人改變時(shí)傳輸了整個(gè)日志;所以為了能夠?qū)嵺`中使用,額外的消息類型就很必要了。

Raft 的強(qiáng)領(lǐng)導(dǎo)人模型簡化了整個(gè)算法,但是同時(shí)也排斥了一些性能優(yōu)化的方法。例如,平等主義 Paxos (EPaxos)在某些沒有領(lǐng)導(dǎo)人的情況下可以達(dá)到很高的性能。平等主義 Paxos 充分發(fā)揮了在狀態(tài)機(jī)指令中的交換性。任何服務(wù)器都可以在一輪通信下就提交指令,除非其他指令同時(shí)被提出了。然而,如果指令都是并發(fā)的被提出,并且互相之間不通信溝通,那么 EPaxos 就需要額外的一輪通信。因?yàn)槿魏畏?wù)器都可以提交指令,所以 EPaxos 在服務(wù)器之間的負(fù)載均衡做的很好,并且很容易在 WAN 網(wǎng)絡(luò)環(huán)境下獲得很低的延遲。但是,他在 Paxos 上增加了非常明顯的復(fù)雜性。

一些集群成員變換的方法已經(jīng)被提出或者在其他的工作中被實(shí)現(xiàn),包括 Lamport 的原始的討論,VR 和 SMART。我們選擇使用共同一致的方法因?yàn)樗麑?duì)一致性協(xié)議的其他部分影響很小,這樣我們只需要很少的一些機(jī)制就可以實(shí)現(xiàn)成員變換。Lamport 的基于 α 的方法之所以沒有被 Raft 選擇是因?yàn)樗僭O(shè)在沒有領(lǐng)導(dǎo)人的情況下也可以達(dá)到一致性。和 VR 和 SMART 相比較,Raft 的重新配置算法可以在不限制正常請(qǐng)求處理的情況下進(jìn)行;相比較的,VR 需要停止所有的處理過程,SMART 引入了一個(gè)和 α 類似的方法,限制了請(qǐng)求處理的數(shù)量。Raft 的方法同時(shí)也需要更少的額外機(jī)制來實(shí)現(xiàn),和 VR、SMART 比較而言。

11 結(jié)論

算法的設(shè)計(jì)通常會(huì)把正確性,效率或者簡潔作為主要的目標(biāo)。盡管這些都是很有意義的目標(biāo),但是我們相信,可理解性也是一樣的重要。在開發(fā)者把算法應(yīng)用到實(shí)際的系統(tǒng)中之前,這些目標(biāo)沒有一個(gè)會(huì)被實(shí)現(xiàn),這些都會(huì)必然的偏離發(fā)表時(shí)的形式。除非開發(fā)人員對(duì)這個(gè)算法有著很深的理解并且有著直觀的感覺,否則將會(huì)對(duì)他們而言很難在實(shí)現(xiàn)的時(shí)候保持原有期望的特性。

在這篇論文中,我們嘗試解決分布式一致性問題,但是一個(gè)廣為接受但是十分令人費(fèi)解的算法 Paxos 已經(jīng)困擾了無數(shù)學(xué)生和開發(fā)者很多年了。我們創(chuàng)造了一種新的算法 Raft,顯而易見的比 Paxos 要容易理解。我們同時(shí)也相信,Raft 也可以為實(shí)際的實(shí)現(xiàn)提供堅(jiān)實(shí)的基礎(chǔ)。把可理解性作為設(shè)計(jì)的目標(biāo)改變了我們?cè)O(shè)計(jì) Raft 的方式;隨著設(shè)計(jì)的進(jìn)展,我們發(fā)現(xiàn)自己重復(fù)使用了一些技術(shù),比如分解問題和簡化狀態(tài)空間。這些技術(shù)不僅提升了 Raft 的可理解性,同時(shí)也使我們堅(jiān)信其正確性。

12 感謝

這項(xiàng)研究必須感謝以下人員的支持:Ali Ghodsi,David Mazie`res,和伯克利 CS 294-91 課程、斯坦福 CS 240 課程的學(xué)生。Scott Klemmer 幫我們?cè)O(shè)計(jì)了用戶調(diào)查,Nelson Ray 建議我們進(jìn)行統(tǒng)計(jì)學(xué)的分析。在用戶調(diào)查時(shí)使用的關(guān)于 Paxos 的幻燈片很大一部分是從 Lorenzo Alvisi 的幻燈片上借鑒過來的。特別的,非常感謝 DavidMazieres 和 Ezra Hoch,他們找到了 Raft 中一些難以發(fā)現(xiàn)的漏洞。許多人提供了關(guān)于這篇論文十分有用的反饋和用戶調(diào)查材料,包括 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 位匿名的會(huì)議審查人員(可能有重復(fù)),并且特別感謝我們的領(lǐng)導(dǎo)人 Eddie Kohler。Werner Vogels 發(fā)了一條早期草稿鏈接的推特,給 Raft 帶來了極大的關(guān)注。我們的工作由 Gigascale 系統(tǒng)研究中心和 Multiscale 系統(tǒng)研究中心給予支持,這兩個(gè)研究中心由關(guān)注中心研究程序資金支持,一個(gè)是半導(dǎo)體研究公司的程序,由 STARnet 支持,一個(gè)半導(dǎo)體研究公司的程序由 MARCO 和 DARPA 支持,在國家科學(xué)基金會(huì)的 0963859 號(hào)批準(zhǔn),并且獲得了來自 Facebook,Google,Mellanox,NEC,NetApp,SAP 和 Samsung 的支持。Diego Ongaro 由 Junglee 公司,斯坦福的畢業(yè)團(tuán)體支持。

本文經(jīng)TopJohn授權(quán)轉(zhuǎn)自TopJohn's Blog

深入淺出區(qū)塊鏈 - 系統(tǒng)學(xué)習(xí)區(qū)塊鏈,打造最好的區(qū)塊鏈技術(shù)博客。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,345評(píng)論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,494評(píng)論 3 416
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,283評(píng)論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,953評(píng)論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,714評(píng)論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,186評(píng)論 1 324
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,255評(píng)論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,410評(píng)論 0 288
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,940評(píng)論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,776評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,976評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,518評(píng)論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,210評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,642評(píng)論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,878評(píng)論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,654評(píng)論 3 391
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,958評(píng)論 2 373

推薦閱讀更多精彩內(nèi)容

  • 尋找一種易于理解的一致性算法(擴(kuò)展版) 摘要 Raft 是一種為了管理復(fù)制日志的一致性算法。它提供了和 Paxos...
    枝葉君閱讀 2,658評(píng)論 0 15
  • 尋找一種易于理解的一致性算法(擴(kuò)展版) 摘要 Raft 是一種為了管理復(fù)制日志的一致性算法。它提供了和 Paxos...
    yflau閱讀 1,022評(píng)論 0 1
  • Raft是一種為了管理日志復(fù)制的一致性算法。它提供了和Paxos算法相同的功能和性能,但是它的算法結(jié)構(gòu)和Paxos...
    WithLin閱讀 816評(píng)論 0 1
  • 很久之前研究過raft協(xié)議,最近項(xiàng)目中一直沒有使用,有些生疏了,這次重溫了一下raft,花了兩天的時(shí)間,就順便做下...
    何約什閱讀 20,573評(píng)論 18 27
  • 今天又是新的一天。加油^0^~ 晨跑的時(shí)候,決定今天讀一本書,然后做一頁讀書筆記。 我需要在除了每天的固定學(xué)習(xí)項(xiàng)目...
    Moon_star閱讀 141評(píng)論 0 0