作者:nolanyang,騰訊 PCG 后臺開發工程師
分布式共識算法中,raft 主打的就是易理解性,近年來隨著業界對算法的開發,raft 算法的應用也被大大拓展。raft 的論文,先描述了算法協議,再用反證法為主的多種證明方法證明其正確性,并沒有給出完整的算法推導過程,因此很多同學多次閱讀論文后,對算法的掌握心里還是沒什么底,而閉著眼睛用組件總是有點發虛的。本文從一個故事開始,給大家模擬推導一遍 raft 協議中的核心規則是怎么構建出來的,希望能讓更多的同學有動力去理解和應用分布式共識算法。感謝 raft 論文翻譯項目為我們高效閱讀論文提供了很大幫助。
項目地址:https://github.com/maemual/raft-zh_cn
一、故事緣起
故事要從一次具有歷史意義的時空之旅開始,5 個家學淵源的家庭,以更準確的記錄下 3000 多年的文明興衰史為目標,穿越到華夏文明的起點,他們要各自建立起以自己家族為中心的村落,通過自己的歷史小村一代一代將發生的歷史事件記錄并傳承下去。出發前 5 個歷史小村的第一代村長進行了一次擬定這個宏偉計劃的會議。會前他們先隨手在白紙上貼上了一張古代地圖,標注了自己村子的起始地點。白紙如圖:
圖1 5村起始位置(圖片來源于網絡)
準確記錄歷史在很多時代都是一件危險的事情,這也是為什么 5 個村莊需要分散在天南地北的主要原因,司馬村長提出了他們的第一個目標,任何時代只要還有三個村落能正常運作,就要能夠準確一致的記錄下這個時代的事情。5 個村長彼此間都無比信任,也堅信他們各自的歷史小村無論何時都不會在規則之外篡改記錄下來的信息。
記錄歷史事件自然需要紙張什么的,遠古時代編年歷法不一定統一,各村落通信周期也不穩定,村長們很快商量出了一個方案,統一使用編好頁碼的記事本進行記錄,1 件事情記錄在 1 頁上,這樣至少事情的先后順序不會輕易搞錯了。然后左村長提出一個關鍵問題,紙質材料和油墨雖然修改方便,但是不易保存,就算在歷史長河中不被損毀,千年過去最早的記事本也沒法再看了,根據他看過一部科幻小說,左村長提出,記事本上的事情只要村落之間“達成一致”了,就可以把事情按順序刻在石碑上埋到地底下,這就是人類目前最有效的保存信息的方法了,這樣做的缺點就是刻在石碑的內容就不好更改了。大家紛紛表示同意,司馬村長把這些信息記錄在他的大白紙上:
圖2 記錄歷史的主要工具:記事本和石碑
二、前提條件的制定
講完這些,大家都把注意力集中到了剛才左村長無意間提出來的“達成一致”這四個關鍵字上。班村長首先提出來,如果每個時期只有一個村落負責把發生的事件記錄下來,而且保持所有村落都是 1 頁上面只記錄 1 個事件,其他村落只負責接收這個村落的消息,把接收到的消息記錄在記事本對應的頁碼上,那記事本上每一頁上的事件保持一致的難度就小很多了。如果多個村落同時記錄歷史事件,然后通過互通消息來協調一致,難度就會大很多,處理每一頁上的記錄沖突也會需要很多時間。
大家一商量,雖然有一點爭議,但最終還是認同了這個提議,多點記錄確實比較難,最終效率也不一定高。左村長接著就拋出了兩個名詞作為約定,“主家”即當前負責記錄的村子,“分家”即當前接收主家消息的村子。左村就主動承擔第一期的主家任務了。接下來就是司馬村長發話了,前面他也說過,目標是任何時代即使有兩個村落被滅,記錄也要準確的傳下去,左村長的方案里面,每個時代負責記錄的村子發生意外的時候,如果他們記在石碑上的事件,別的村子還沒收到,那記錄的事件就會出現不一致了,以后之前被滅村子的石碑被后人挖出來以后,歷史事件可能出現矛盾,當然這還是最簡單的情況了,更復雜的這一類情況還能一口氣說出很多。
大家開始繼續思考這個問題,顧村長第一個發表觀點,一件事情只要有 3 個村落記錄下來,那之后任何時刻失去任意兩個村子,這件事情都不會丟,因為最差也是還有一個村落記下了這件事。所以說一件事情只要有 3 個村落在記事本上記下來了,那這件事情就可以被放心的刻到石碑上了,一個事件確認可以被記錄在石碑上了,就稱這個事件安全了。至于誰來統計有幾個村莊記錄了某一件事情,那自然是主家了。左村長的方案里面只有主家負責發出消息,其他從家都只能在主家發來消息以后做相應記錄,再讓信使把記錄的情況發回給主家,主家根據回來的信使的消息自然可以統計有多少村落記記錄下了這個事件了,主家在后面的通信中再把哪些事件可以刻到石碑上了,帶給各村,那就很穩妥了,所以主家要統計一份各村已經記錄下的事件列表。
司馬村長一聽立刻就說這還不夠:要是左村長記錄下來的第一頁上的事情,簡稱事件 1,同步給了顧村和歐陽村,但沒傳給另外兩個村子,然后左村記錄的事件 2,又只同步給了司馬村和班村,這時候左村長是可以大大方方刻石碑了,但要是刻完石碑就被滅村,那剩下 4 家選誰做主家,都沒有兩件事情完整的記錄,要把剩下 4 家手上的記錄合起來又要非常復雜的通信規則了。情況就像圖上這樣(填了藍色代表這頁記錄了事件):
圖3 可能出現的記事本有空頁的情況
左村長這時也提出一個問題,就算主家一直沒出什么問題,過了一千年,那主家記錄各個事件在各村的記錄情況的列表也是長的看不懂了,給各家補齊少記錄的事件也是不知從何下手啊。一時間與會眾人難以定出個結論來,這時候歐陽村長終于發言了:太復雜的事情不好分析,我們就簡單點處理吧,每次同步事件的時候,有 3 個以上村落都有著從開始到當前頁碼都相同的記錄時,才算安全,才可以把這件事刻到石碑上,這樣任意 2 個村被滅,都會至少有一個村保留所有可以被刻到石碑上的事件,下一輪只要能把滿足這樣條件的村莊選出來做主家,那這個新的主家就能帶領剩下的分家把之前的記錄傳承下去了。
另外這樣做了以后,任何分家接收到主家傳來的消息,如果發現前面有缺漏的事件,那也不用再跳過前面的頁碼來記錄當前事件了,因為記下來了也不能作為當前事件的確認方被統計計數,也就是說記事本中間再也不會有空洞了,而主家也不用保留超級復雜的統計列表了,只要記一下各個分家最后記錄下來的事情是第幾頁的事情就能掌握全局情況。其實這時候還得出了一個階段性成果:因為記錄事件的時候,要確認前面的事件是不是都一樣,只有都一樣才能記錄下來,只要一個時期只有一個村莊做主家,那么兩個和主家正常通信的分家的記事本上,只要在任意一頁上“相同”,那這頁之前的內容肯定是“相同”的了,任意分家和主家之間也滿足這個結論。
這一下大家都開心了,這個辦法簡單易懂,司馬村長立刻把剛才討論的結果記錄到大白紙上:(到這里大家討論出來的兩個最關鍵的前提條件:只有一個主家負責記錄事件,其他分家只負責接收主家的消息;記事本不能有空洞。這兩個前提條件并不是靠推理得出的,而是大家希望簡化后面的規則提出的假設,如果沒有這兩個條件,那大家后面可能會推導出別的分布式共識算法哦)
圖4 最初提出的復制事件的規則
三、解釋解釋什么叫做“相同”
但是很快大家就發現了新的問題,確認過往所有的記錄事件是不是都“相同”,這可不容易做啊,先不說確認“相同”是不是就是比較記錄的每一個字都一樣,只要持續記錄很多年,比較一次也要花上太多時間了吧,每次有新的事件都要從頭開始比較,這誰受得了?司馬村長立刻發表了高論:用我小學二年級學過的最簡單的數學歸納法就可以破這個問題了,對于在區間(0,N]的任意 n, 都滿足元素 S1(n)== S2(n)且 S2(n-1)== S1(n-1),那么在[0,N]區間內,S1 和 S2 這兩個數組每個位置上的元素都是相等的。
在我們這個問題里,說人話就是每一個新事件記錄的時候,主家在同步消息的時候除了當前事件還要帶上前一頁記錄的事件,收到消息的分家要比較一下前一頁上的事件和自己記錄的是不是“相同”,只有前一頁的事件“相同”才記錄新一頁的事件,只要從頭一開始就這么做,那么每次能順利記錄下新事件的村落,前面記錄的事件和主家肯定是都“相同”的。大家紛紛拍案叫絕,只有顧村長問了一聲,要是分家接到消息的時候,發現主家傳來的前一頁事件和自己這里記錄的不一樣或者根本還沒記錄過這一頁的事情,那可怎么辦呢?
歐陽村長立刻發話,還是用簡單的方法,上面的情況,分家直接回復主家現在不能記錄這一頁上的事件,主家接到失敗的消息就把前一頁的事件作為這個分家下次要同步的事件在下次發消息的時候發前一頁的事件,而下次發消息附帶的也就是前前頁的事件了,要是這次同步能成功,那就繼續嘗試同步新的事件,反之,就以此類推,繼續往前嘗試更靠前的頁碼上的事情,主家再單獨保存一份要給各分家下次嘗試同步哪一頁的列表就能輕松做好這個事情了。這一波討論完,大家一下子都安心了,最重要的主家怎么把自己記錄下來的事件復制給分家的主要機制都討論出來了,司馬村長開心的在白紙上開始了記錄。他先畫了一張草稿說明以后主家怎么同步消息給分家:
圖5 主家發送同步事件的基本規則
司馬村長剛畫完示意圖,左村長就發現了問題:就算只比較前一頁的事件一樣不一樣,也沒有百分百的把握啊,遠古時期年歷容易出現偏差,地名也不一定對齊,傳遞消息時間又長,萬一不同的地方連續出現類似的天災一類的事件,說不定記錄都差不多,前面反復說到的事件“相同”的這個“相同”要有明確的判斷標準才行啊。
大家再次陷入沉思,大概五分鐘之后,又是歐陽村長說話了:要簡單判斷事件是不是“相同”,要把我們之前一個沒用上的關鍵信息給用起來了。按照我們之前的設定,理想情況下一個時期只會有一個主家負責記錄事件,如果主家出事了,分家都收不到主家的信息了,可能選出一個新的村落做主家,每一個主家上任后負責記錄的這段時間就叫主家的任期好了,我們給每一個任期遍一個號,叫任期號,任期號從 1 開始,每次新上任的主家的任期號就是上一個任期號加 1,這樣每段任期就有唯一的任期號了。
每一個主家記錄事件的時候,給每個事件都記上自己當時的任期號并在同步事件的時候都帶著事件對應的任期號,分家收到事件的時候,記錄的時候也把對應的任期號記錄在那一頁上,這樣下來,只要所有主家保證不修改自己之前記錄下的任何一頁上的事件,那可以簡單推導出來:同一頁上標注的任期號相同,這一頁的記錄就一定相同。這時候顧村長表示這通操作不太理解了,這時不怎么說話的班村長拿起記事本給他演示了一下:
圖6 記事本每一頁記錄事件的樣式
正常情況下任何時期我們里面的主家只有一個,對應的任期號 T 也只有一個,主家在第 N 頁上記下事件的時候帶上了自己的任期號 T,相當于告知大家這頁的事件是我寫的,只要主家保證自己記錄下來的事件,自己在這一個任期內絕對不會改,那分發出去的任何一頁上的事件,只要任期號相同就代表是同一個主家在同一個任期記錄下來的,這個主家在這個任期里又絕不可能回去改這個事件,那這頁上的事件也就是相同的了。
所以我們以后表示一個事件只要用 S(N,T)這種形式就可以了,頁碼 N 和任期 T 都相等,事件一定“相同”,以后這就是事件“相同”的定義了,事件相同也就再也不用打引號了。順帶一提,主家每次同步過來的事件里的任期號,分家也要找個地方記下來,這樣下次分家被選為主家的時候,才能正確的把任期加 1 哦。說到這里,大家都懂了,主家向分家同步記錄下來的事件的步驟都差不多出來了,司馬村長也飛快的完成了這階段的記錄。(圖片請雙擊放大瀏覽)
圖7 初步完成了復制事件機制的設計
司馬村長記錄的同時還補上了主家怎么確認一頁上記錄的事件是不是可以被安全送去刻到石碑上的相關操作規則,還把主家已經確認的最大安全頁碼加在了主家傳給分家的消息里,這樣分家也能結合自己的情況確定自己可以刻到石板上的最大頁碼了。為了方便刻石碑,還規定了每個村落把已經刻好的最大頁碼以及可以安全刻下來的最大頁碼分別記錄一下。
最后他還提出來,可能以后有些人會向村落爆料一些事件,如果這時候這個村落不是主家,又不知道主家現在是誰,那還挺尷尬的,所以每次主家傳消息的時候記得報一下自己是誰,這樣就可以引導爆料群眾直接去主家那里直接爆料了。這些設定都很容易理解,大家紛紛直呼內行。不過班村長還是指出了筆記上幾處語句不通順以及字寫錯的地方。
四、選舉爭霸
討論到這里,大家都挺累的了,司馬村長和歐陽村長相視一笑,有了這些設定,是時候短兵相接,快速討論一下選舉主家的規則了吧。
司馬:穿越過去以后,要是我們一段時間沒收到左村長的消息,我們是不是就可以開始選新的主家了,但是萬一這段時間其實是左村長覺得沒發生什么值得記錄的事件,那就不太好了,我們到時候搞出兩個主家來,前面的規則都破了。
歐陽:簡單處理,主家的人,就算沒有要記錄的事件發生,也最少每個月給所有分家發個消息,就算消息里面沒有要記錄的事件也要發,算是報個平安吧。哪個分家連續三個月沒收到主家的消息,再發起選舉不遲。
司馬:發起選舉是容易,我們收到選舉要按什么規則投票呢?按照前面的思路,我們可是要選出一個擁有前任主家進行過安全確認的所有事件的村落出來傳承的哦。
歐陽:簡單處理,任期號代表時代只增不減,記事本上有記錄事件的最大頁碼上的任期號誰大,誰的記事本就內容更全,如果任期號一樣大,那最大頁碼大的記事本就更全,要是頁碼和任期號都一樣,那記事本就一樣全。每個村莊只投票給記事本最少和自己一樣全的村莊不就可以了么。
司馬:那得了幾票,就可以做主家了呢?
歐陽:簡單處理,就是包括自己在內的 3 票啊,前面我們設定過了,最后一個被確認安全的事件,包括主家最少有 3 個村莊已經記下來了。記錄下最新事件的村子就是有最全內容的村子,包括主家在內有 3 個這樣的村子。就算剩余其他 2 個村莊還沒來得及記下最新的事件的時候,主家被滅了,記下最新事件的 2 個村莊里面不管誰參與選舉,誰就能得到包括自己在內的 4 票,反之,沒記下最新事件的 2 個村子參與選舉,最多只能得 2 票。我們設定的最壞情況也就是同時再被滅掉一個記錄事件最全的村子,那這時候剩下唯一一個記錄最全的村子還是能夠得到包括自己在內的 3 票支持,成功當選新的主家。
總結起來說就是不管被滅幾家,只要能贏得 3 票,上一個任期的主家能確認安全的事件,在新選出來的主家記事本里面肯定有。我圖都給你畫出來了:
圖8 記錄“最新”事件的村莊能贏得競選
司馬:不對啊,你的圖里面,我只要拿到你和班村的票就能做主家了,萬一顧村沒給我投票,而是也發起了選舉,他也能贏得你和班村的選票,也是 3 票也能成為主家,那不就 2 個主家了嗎?
歐陽:這個問題連簡單處理都不需要了,你們發起選舉的時候,先把自己的任期號增加一下,變成自己當選以后要用的任期號發出去,每個村子在一個任期號里最多投一次票,記錄下來每個任期號是投票給了哪個村子。這樣你拿到 3 票時候,顧村長再開始發起投票,他的任期號最多和你一樣,他是拿不到其他已經投過票的村子的支持的。除非再過三個月,期間顧村長都沒收到過你同步的任何消息,他再次增加任期號發起選舉才有機會再當主家。而如果這三個月里面,你真的什么事都沒記下來,那顧村才可能當選,但是任期號也增加了,他用的還是唯一任期號,我們的機制也繼續維持著,沒什么影響。
司馬:還有問題啊,你剛才說的是我先拿到 3 票的情況,問題是我和顧村可能是同時發起選舉的,萬一我們一個得到了你的支持,一個得到了班村的支持,那我們豈不是這一輪不分勝負,到下一輪我們再同時發起,又是各得兩票,豈不是沒完沒了,我們時間都花在選舉上了,怎么好好記錄歷史啊。
歐陽:這個也是可以簡單處理的,我們每家每次發起選舉的時間不要那么固定嘛。比如說你有時候是 3 個月零 7 天收不到任何消息發起選舉,有時候是 4 個月發起選舉,顧村他們有時候是 3 個月零 14 天收不到消息發起選舉,有時候是 4 個月零 7 天發起選舉,你們發起選舉沖突的概率不就低了?
左村長:你們別太過分了,萬一上面那個情況里面,我們村不是被滅了,只是信使都被攔截了,我可是一直都在辛苦的記錄著各種事件,只是沒法同步給你們,我自己也沒法確認新記錄的事件是不是可以被刻到石碑上。那三年后我龍王歸來,哦不是,我找回信使,把我這隱忍三年記錄下來的事件傳遞給你們,你們認還是不認?
歐陽:簡單起見,不管你是修羅還是什么神醫,我們都不認,因為你的內容合進來,我們還要要保持一致太復雜了,而且你那三年記下來的內容又沒被安全確認過,你也不敢刻在石碑上,你回來以后乖乖接收我們補給你的安全的事件,去刻你的石碑就完事了。哪一頁開始,你記錄事件的任期號和新主家不一樣了,你就從這一頁開始把后面的內容都劃掉啊。
左村長:我 TM 什么時候說過修羅、神醫什么的了?而且我們之前定的規則里面,也沒說我這個歸來龍王,哦不,我這個歸來主家不能繼續同步記錄的事件給你們啊!
歐陽:簡單處理,我補個通用規則,反正同步事件和發起選舉兩種消息里面都帶有任期號這個信息了,任期號只增不減,更大的任期號代表更新的時代,所以我宣布收到的消息里面,任期號小于自己之前記錄下來的,一律拒絕,任期號大于自己之前的,一律把自己記錄的任期號更新為接收到的任期號,然后再根據之前的設定操作,誰贊成,誰反對?
左村長:我之前是主家,我收到你們的消息里面的任期號比我自己的大,我也要聽你們的嗎?
歐陽:簡單處理啊,不管你是主家,還是你發起選舉做了候選人,收到的消息里面的任期號比你們自己的大,就自覺一點,主動把自己村的地位降到分家,不就可以了嗎?因為你們都錯過了至少一個時代了,還想繼續做主家,別人豈不是都要配合你們,這時候說不定別人好多你們錯過的事件都刻到石碑上了。順便說一下啊,剛才我已經設定了每家等待個一定范圍內的隨機時間再發起選舉的規則,選舉沖突不容易發生了,我們剛穿越回去那會兒,也不用提前指定誰做第一個主家了,也用這種選舉機制來選吧,這樣左老師你壓力也不用那么大了哈。
左村長:。。。
大家停下來消化了一下前面對話的內容,發覺歐陽村長說的這一套還真是能解決很多問題,司馬村長開始整理筆記了。
圖9 根據針對選舉的討論完善出來的全套機制
這次因為新增的內容比較多了,司馬村長把新增的內容都用紅色筆來記了,還修復一些班村長之前吐槽的不通順的語句,還補充了投票過程中容易想出來的一些細節。寫完以后大家看了一會,司馬村長覺得十分滿意了,最后達成的成果(5)就是大家的終極目標了,但是這時候顧村長又看出問題來了。
顧村長:前面那個圖 8 里面,要是通信方式全部被卡斷的,不是作為主家的左村,而是作為分家的我們顧村的話,就有問題了。我們顧村收不到任何消息,3 個月以后自己成為候選村,增大自己的任期號,發出去的選舉消息你們也收不到,然后我們顧村繼續提升自己的任期號,不斷發起新的選舉。要是三年后,通信恢復了,我的任期號最大,你們收到我的選舉請求,都要參見龍王了。
歐陽:三年后我們收到你的選舉消息,確實主家也要自認任期號不夠看,自降為分家,但只要這三年里有新事件被主家安全確認過,你也不可能被投成新的主家。因為我們投票還要看你最后的記錄事件有沒有我們的新。你自己這三年記錄不了任何事件,主家只要有新事件安全確認過,那至少有 3 家記錄了這個新事件,這 3 家都不會投票給你,你最多 2 票,怎么當選主家呢?所以說,最后當主家的,一定還是記下了所有事件的村子。反過來說,要是三年里面沒新事件被安全確認,那你當上主家,也沒什么問題,因為你也是記錄了所有事件的,你當主家就當唄。
當然了,你這樣冒出來,打斷本來干的好好的主家的工作,確實影響了大家對歷史的記錄,投票這段時間,都沒有主家正常工作了,所以這點我們可以補一些限制規則,比如正式投票前讓你發個民意調查什么的,要是你民意調查都過不了,就不要發什么選舉來浪費大家時間了,當然這個規則可以以后補充清楚,因為民意調查也可能拖慢了正常需要發起選舉的節奏。
五、龍王歸來
歐陽村長說完以后,大家都很佩服其深謀遠慮,這時候班村長拿出來一份打印材料,大家都瞥了一眼,居然是洋文的,標題很長:“In Search of an Understandable Consensus Algorithm”。然后班村長發話了,今天晚上大家能制定出這樣一個計劃來,很了不起了,不過還有兩個點大家是沒想到的,一個是主家新上任的時候,主家已經確認安全的最大頁碼,不一定比分家都大,傳遞記錄事件消息的時候,要特別注意,司馬你記得筆記里復制規則那里其實是憑直覺蒙對的。這一點我提示你們以后,你們仔細想想,應該都能想到的。不過還有一種情況就不容易想到啦,你們過來看看這張圖:
圖10 超級復雜的輪流做主家(論文原文圖8)
班村長開始解釋了,我這個圖上不同顏色的小方塊代表不同任期記錄下來的事件,小方塊里的數字代表事件記錄里的任期號是多少,abcd(e)代表順序的4 個時間點,每個時間點上,誰的記錄外面的框輪廓粗,誰就是當時的主家,比如(a)時期 S1 就是主家,(d)時期 S5 就是主家。我們來看一下發生了什么啊,(a)這個時間點呢,S1 是主家,把他記錄的第 2 頁上的事件(黃色)同步給了 S2,然后他們村連同還在路上的信使都被滅了。
到了(b)這個時間呢,S5 因為在選舉中,得到 S3,S4 的支持當上了主家,并且他在第 2 頁上記錄了一個新事件(藍色)。這里都好理解吧,S5 贏得選舉的時候,因為只有 S2 一個村有更新的事件,所以只要 S5 先發起選舉,S5 就可以得到 3 票了,反正黃色事件之前也不可能被任何村子確認為安全,所以這個結果也合理嘛。
到了(c)時期,S5 這個村子連同信使都被滅了,他們記錄下來的事件一個村子都沒傳遞到,而 S1 那邊出現了幸存者,憑著記錄的黃色事件,在連續將任期號提升到 4 以后,贏得了選舉,并且在第 3 頁上記錄下來了新的事件(粉色)。在將新事件傳遞給 S3 的時候,因為被拒絕所以退而求其次將將第 2 頁上的黃色事件同步給了 S3,這樣 S3 在第 2 頁上也記錄下了黃色事件,黃色事件也就有 3 個村子記錄下來了,按照你們前面的討論,S1 就要對黃色事件做安全確認了。
要是 S1 確認黃色事件安全,將其刻到石碑上,之后再次被滅村,S5 那邊的幸存者,憑借自己在第二頁上記錄下來的藍色事件,至少可以在連續提升自己任期號到 5 以后,在選舉中得到 S3 和 S4 的支持。因為 S3 雖然記錄了黃色事件,但黃色事件的任期號是 2,藍色事件的任期號是 3,藍色事件在規則中是更新的。S5 贏得選舉做了主家以后,在(d)這個時候,是可以把第 2 頁上的藍色事件復制到其他所有村子記事本的第 2 頁上的,藍色事件在第 2 頁上被確認安全的話,和之前在第 2 頁上已經被 S1 確認甚至被刻到石碑上的黃色事件就沖突了。
所以說你們前面討論的規則里面還是有一個關鍵漏洞的。不過你們也別那么痛苦的一副表情了,你們繼續看圖吧。如果 S1 沒有那么快被屠村,沒有(d)這個時刻的事情,而是到了(e)這個時間點上,完成了復制粉色事件給 S2,S3 的任務,這時候 S1 確認粉色事件是安全的并刻到石碑上。之后不管發生什么事情,S5 的藍色事件在選舉中都是不如 S1,S2,S3 最后記錄的粉色事件新的(任期號直接分勝負),也就再也選不上主家了。
總結一下呢,就是主家只能確認自己當前任期內的事件是否安全,而不能確認之前任何一個任期內的事件是否安全,而根據你們最早就得出的成果(1),一頁上的事件被確認安全了,那這一頁之前所有頁上記錄的事件也就安全了,所以過往任期中的事件是可以通過當前任期的事件安全性被確認的。司馬你的紙給我,我來修改一下吧。
圖11 集中大家的智慧討論出來的最終方案
班村長寫完以后繼續說到,我把改動都用藍色標記出來了,復制記錄事件的規則里面,司馬剛才是憑直覺寫對了“要確認主家的安全頁碼大于自己的”這類規則的,所以這個我也標出來了。最重要的,就是最后達成的成果,我改了一下,可不是隨便一頁上的事件有超過 3 個村子記錄了,就可以確認安全哦。切記切記。我在這里隱忍了三個小時了,聽你們說了這么多,現在我要回去睡覺了。
剩下的村長沉思了大半個小時,然后對著班村長離去的方向拱手作揖,“參見龍王”。
六、推廣總結
到這里呢,這個穿越時空的小故事就差不多結束了。之前看過 raft 論文或者現在再去看的同學,應該都可以輕松的把故事里面的名詞和論文中的對應起來了,多多少少對論文中一開始就出現的協議規則是怎么來的能有一些新的理解了。寫這個故事的時候,通過好友之間討論的形式來構造的情節,希望通過這種方式能讓更多同學對分布式共識算法產生興趣,消除恐懼,在自己業務里面合適的場景中用上這種能力來提升服務的質量,當然因為水平有限出現的一些錯誤也請大家多多包涵指正。
感謝所有不吝三連支持的同學。最后把這篇文章送給這些年來在一線研發崗位上一起奮斗戰友,過去和你們每一次為了更完美的解決方案的討論,都讓我受益良多,很多場面我會永遠記得,以這個故事向純粹的你們致敬。
后記
司馬:左老師,除了我給你們的筆記上提到的那些東西,你還準備帶些什么寶貝一起穿越啊?
左村長:我要帶上我最喜歡的憤怒的小鳥周邊,哈哈哈!