分散式共識如何運作?

banq發表於2018-11-20

MartinFowler推薦的文章,論述區塊鏈技術的關鍵概念,以及中本共識為何如此重要?
分散式系統可能難以理解,主要是因為圍繞它們的知識也是分散式的。現在,經過多次考驗和磨難,我終於準備好向您解釋分散式系統的基礎知識。

區塊鏈迫使工程師和科學家重新審視並質疑分散式計算中根深蒂固的正規化。

我還想討論區塊鏈技術對該領域的深遠影響。區塊鏈迫使工程師和科學家重新審視並質疑分散式計算中根深蒂固的正規化。也許沒有其他技術能夠比區塊鏈更快地促進這一研究領域的進展。

分散式系統絕不是新的。科學家和工程師花費了數十年時間研究這一主題。但是區塊鏈與它們有什麼關係呢?好吧,如果分散式系統首先不存在,那麼區塊鏈所做的所有貢獻都是不可能的。

本質上,區塊鏈是一種新型的分散式系統。它始於比特幣的出現,並從此在分散式計算領域產生了持久的影響。因此,如果您想真正瞭解區塊鏈的工作原理,那麼掌握分散式系統的原理至關重要。

不幸的是,很多關於分散式計算的文獻要麼難以理解,要麼分散在太多的學術論文中。為了使問題更復雜,有數百種架構,所有架構都滿足不同的需求。將其歸結為易於理解的框架非常困難。

因為這個領域很廣,我不得不仔細選擇我可以覆蓋的東西。我還必須進行概括以掩蓋一些複雜性。請注意,我的目標不是讓你成為該領域的專家。相反,我想給你足夠的知識,以啟動你的分散式系統和共識的旅程。

閱讀完這篇文章之後,你將更加掌握:

  • 什麼是分散式系統,
  • 分散式系統的屬性,
  • 在分散式系統中達成共識意味著什麼,
  • 理解基礎共識演算法(例如DLS和PBFT),以及
  • 為什麼Nakamoto Consensus是一個大問題。

我希望你已經準備好學習,因為課程正在開課。


什麼是分散式系統?
分散式系統涉及一組不同的程式(例如,計算機)將訊息彼此傳遞且協調以實現共同目標(即,解決計算問題)。

分散式系統是一組協同工作以實現統一目標的計算機。

簡而言之,分散式系統是一組共同努力實現統一目標的計算機。雖然這些過程是分開的,但系統對終端使用者來說只是一臺計算機。

正如我所提到的,分散式系統有數百種架構。例如,單個計算機也可以被視為分散式系統:中央控制單元,儲存器單元和輸入 - 輸出通道是協作以完成目標的單獨過程。

在這篇文章中,我們將專注於分散式系統,其中程式代表的是空間分離的計算機(節點伺服器)

分散式系統的屬性
每個分散式系統都有一組特定的特徵。這些包括:

A)併發
系統中的程式同時執行,這意味著多個事件同時發生。換句話說,網路中的每臺計算機與網路中的其他計算機同時獨立地執行事件。
這需要協調。
協調就需要時間,時鐘和事件排序

B)缺乏全球時鐘
要使分散式系統工作,我們需要一種方法來確定事件的順序。但是,在一組同時執行的計算機中,有時不可能說兩個事件中的一個事先發生,因為計算機在空間上是分開的。換句話說,沒有一個全域性時鐘可以確定網路中所有計算機上發生的事件序列。
在“ 分散式系統中的時間,時鐘和事件排序”一文中,Leslie Lamport展示瞭如何透過記住以下因素來推斷一個事件是否在另一個事件之前發生:

  1. 訊息在收到之前傳送。
  2. 每臺計算機都有一系列事件。

透過確定哪個事件發生在另一個事件之前,我們可以獲得系統中事件的部分排序。Lamport的論文描述了一種演算法,該演算法要求每臺計算機都能監聽系統中每臺其他計算機。透過這種方式,可以基於該部分排序完全排序事件。
但是,如果我們將順序完全基於每臺計算機監聽到的事件,我們可能會遇到此順序與系統外部使用者所感知的不同的情況。因此,該演算法會發生異常行為。
最後,Lamport討論瞭如何透過使用正確同步的物理時鐘來防止這種異常。
但是等等 - 有一個巨大的警告:協調獨立的時鐘是一個非常複雜的電腦科學問題。即使您最初準確地設定了一堆時鐘,時鐘也會在一段時間後開始出現差異。這是由於“ 時鐘漂移”,這是一種時鐘以稍微不同的速率計算時間的現象。
從本質上講,Lamport的論文表明事件的時間和順序是在空間上分離的分散式計算機系統中的基本障礙。

C)元件的獨立故障
理解分散式系統的一個關鍵方面是承認分散式系統中的元件存在故障。這就是它被稱為“容錯分散式計算”的原因。
系統沒有故障是不可能的。真正的系統存在許多可能的缺陷或缺陷,無論這是一個程式崩潰; 訊息丟失,扭曲或重複; 延遲或丟棄訊息的網路分割槽; 甚至一個程式完全失控,並根據一些惡意計劃傳送訊息。

系統沒有故障是不可能的。

這些失敗大致可分為三類:

  • 崩潰 - 失敗:元件在沒有警告的情況下停止工作(例如,計算機崩潰)。
  • 省略:元件傳送訊息但其他節點未接收到訊息(例如,訊息被丟棄)。
  • 拜占庭:該元件表現得任意。這種型別的故障在受控環境(例如,Google或Amazon資料中心)中無關緊要,在這些環境中可能沒有惡意行為。相反,這些錯誤發生在所謂的“對抗性上下文”中。基本上,當一組分散的獨立行動者充當網路中的節點時,這些行動者可能選擇以“拜占庭”的方式行事。這意味著他們會惡意選擇更改,阻止或不傳送訊息。

考慮到這一點,目標是設計協議,允許具有故障元件的系統仍然實現共同目標並提供有用的服務。
鑑於每個系統都有故障,我們在構建分散式系統時必須考慮的核心因素是,即使其部件偏離正常行為,它是否能夠存活,無論是否由於非惡意行為(即崩潰失敗或遺漏錯誤)或惡意行為(即拜占庭故障)。
從廣義上講,製作分散式系統時需要考慮兩種型別的模型:
1)簡單的容錯
在一個簡單的容錯系統中,我們假設系統的所有部分都執行以下兩種操作之一:它們要麼完全遵循協議,要麼失敗。這種型別的系統絕對應該能夠處理離線或失敗的節點。但它不必擔心節點表現出任意或惡意行為。 

2A)拜占庭容錯
簡單的容錯系統在不受控制的環境中不是很有用。在一個分散的系統中,節點由獨立的參與者控制,在開放的,無許可權的網際網路上進行通訊,我們還需要設計選擇惡意或“拜占庭”的節點。因此,在拜占庭容錯系統中,我們假設節點可以失敗或惡意。

2B)BAR容錯
儘管大多數真實系統都設計為能夠承受拜占庭故障,但一些專家認為這些設計過於籠統,並未考慮“理性”故障,如果符合自身利益,節點可能會出現偏差。 。換句話說,取決於激勵,節點可以是誠實的和不誠實的。如果激勵措施足夠高,那麼即使是大多數節點也可能不誠實地行事。
更正式地說,這被定義為BAR模型 - 一個指定拜占庭和理性失敗的模型。BAR模型假設有三種型別的角色:
  • 拜占庭:拜占庭節點是惡意的,並試圖搞砸你。
  • 利他主義:誠實的節點總是遵循協議。
  • Rational理性: Rational節點只有在適合它們時才遵循協議。


D)訊息傳遞
如前所述,分散式系統中的計算機透過一臺或多臺其他計算機之間的“訊息傳遞”進行通訊和協調。訊息可以使用任何訊息傳遞協議傳遞,無論是HTTP,RPC還是為特定實現構建的自定義協議。訊息傳遞環境有兩種型別:
1)同步
在同步系統中,假設訊息將在某個固定的已知時間內傳送。
同步訊息傳遞在概念上不那麼複雜,因為使用者有一個保證:當他們傳送訊息時,接收元件將在特定時間範圍內獲得它。這允許使用者使用固定的上限來建模他們的協議,該上限是訊息到達其目的地所需的時間。
但是,在真實的分散式系統中,這種型別的環境並不十分實用,因為計算機可能會崩潰或離線,並且可能會丟棄,複製,延遲或無序接收訊息。 
2)非同步
非同步訊息傳遞系統中,假設網路可能無限延遲訊息,複製訊息或無序傳遞訊息。換句話說,訊息接收的時間長度沒有固定的上限。

在分散式系統中達成共識意味著什麼
到目前為止,我們已經瞭解了分散式系統的以下屬性:

  • 程式的併發性
  • 缺乏全球時鐘
  • 有問題的流程
  • 訊息傳遞

接下來,我們將專注於理解在分散式系統中實現“共識”意味著什麼。但首先,重申我們之前提到的內容非常重要:數百種用於分散式計算的硬體和軟體架構。
最常見的形式稱為複製狀態機。

複製狀態機
複製狀態機是一種確定性狀態機,它在許多計算機上覆制,但作為單個狀態機執行。這些計算機中的任何一臺都可能出現故障,但狀態機仍然可以執行。
在複製狀態機中,如果事務有效,則一組輸入將導致系統狀態轉換到下一個事務。事務是對資料庫的原子操作。這意味著操作要麼全部完成,要麼根本不完成。在複製狀態機中維護的事務集稱為“事務日誌”。
從一個有效狀態轉換到下一個有效狀態的邏輯稱為“狀態轉換邏輯”。
換句話說,複製狀態機是一組分散式計算機,它們都以相同的初始值開始。對於每個狀態轉換,每個程式決定下一個值。達到“共識”意味著所有計算機必須共同商定該值的輸出。
反過來,這在系統中的每臺計算機上維護一致的事務日誌(即,它們“實現共同的目標”)。複製的狀態機必須不斷地將新事務接受到該日誌中(即,“提供有用的服務”)。儘管如此,它必須這樣做:

  1. 有些計算機出現故障。
  2. 網路不可靠,訊息可能無法傳遞,延遲或出現故障。
  3. 沒有全域性時鐘來幫助確定事件的順序。

我的朋友們,這是任何一致性演算法的基本目標。

共識問題的定義
如果演算法滿足以下條件,則演算法達成共識:

  • 協議:所有非故障節點決定相同的輸出值。
  • 終止:所有非故障節點最終決定某些輸出值。

注意:不同的演算法具有上述條件的不同變化。例如,有些人將協議屬性劃分為Consistency和Totality。有些人有一個有效性或完整性或效率的概念。但是,這種細微差別超出了本文的範圍。

從廣義上講,共識演算法通常假定系統中有三種型別的參與者:

  1. 提議者,通常稱為領導者或協調員。
  2. 接受者,監聽提議者請求並響應值的過程。
  3. 學習者,系統中的其他過程,學習決定的最終價值

通常,我們可以透過三個步驟定義一致性演算法:

第1步:選舉
  • 程式選擇一個領導程式(即領導者)來做出決策。
  • 領導者提出下一個有效的輸出值。

第2步:投票
  • 無故障程式會監聽領導者提出的值,對其進行驗證,並將其作為下一個有效值提出。

第3步:決定
  • 無故障程式必須就單個正確的輸出值達成共識。如果它收到滿足某些標準閾值數量的相同投票,則程式將決定使用該值。
  • 否則,以上步驟重新開始。

重要的是要注意每個共識演算法都有不同:
  • 術語(例如,輪次,階段),
  • 如何處理投票的程式,以及
  • 決定最終值的標準(例如,有效性條件)。


儘管如此,如果我們可以使用這個通用過程來構建一個保證上面定義的一般條件的演算法,那麼我們就有了一個能夠達成共識的分散式系統。
很簡單吧?

FLP不可能
回想一下我們如何描述同步系統和非同步系統之間的區別:

  • 在同步環境中,訊息在固定的時間範圍內傳遞
  • 在非同步環境中,無法保證傳遞訊息。

這種區別很重要。
在同步環境中達成共識是可能的,因為我們可以假設訊息傳遞所需的最長時間。因此,在這種型別的系統中,我們可以允許系統中的不同節點輪流提出新的交易,輪詢多數投票,並且如果在最大時限內沒有提供提議,則跳過任何節點。
但是,如前所述,假設我們在同步環境中執行在訊息延遲可預測的受控環境之外是不實際的,例如具有同步原子鐘的資料中心。
實際上,大多數環境不允許我們進行同步假設。所以我們必須為非同步環境設計。
如果我們不能在非同步環境中假設最大的訊息傳遞時間,那麼即使不是不可能,實現終止也要困難得多。請記住,達成共識必須滿足的條件之一是“終止”,這意味著每個非故障節點必須決定某些輸出值。
這被正式稱為“FLP不可能性結果。” 它是如何得到這個名字的?好吧,我很高興你問這個問題!

某個發生錯誤的程式即使在確定性非同步過程中也是不可能達成共識的。

研究員Fischer,Lynch和Paterson(又名FLP)在他們1985年發表的論文“ 分裂共識與一個錯誤程式的不可能性 ”中表明上述觀點,也就是說,由於程式可能在不可預測的時間內失敗,因此它們也可能在阻止達成共識的恰當時機恰好發生錯誤失敗。

這個結果對分散式計算空間來說是一個巨大的失敗。儘管如此,科學家們還是繼續努力尋找繞過FLP不可能性的方法。
在較高的層面上,有兩種方法來規避FLP不可能性:

  1. 使用同步假設。
  2. 使用非決定論。

讓我們現在深入瞭解每一個。

方法1:使用同步假設
讓我們重新審視我們的不可能性結果。這是考慮它的另一種方式:FLP不可能性結果基本上表明,如果我們不能在系統中取得協調的進展與結果,那麼我們就無法達成共識。換句話說,如果是採取非同步傳遞訊息,則無法保證獲得最終結果。回想一下,結果如果是一個必需條件,這意味著每個非故障節點最終必須決定一些輸出值。

但是,如果我們不知道非同步網路何時會傳遞訊息,我們如何才能保證每個非故障流程都能決定一個結果值?
需要明確的是,這一發現並未表明共識無法實現。相反,由於非同步,無法在固定時間內達成共識。說共識是“不可能”只是意味著共識“並非總是可行的。”這是一個微妙但至關重要的細節。
避免這種情況的一種方法是使用超時。如果在確定下一個值時沒有進展,我們會等到超時,然後再重新開始步驟。正如我們即將看到的那樣,這就是像Paxos和Raft這樣的共識演算法。

Paxos

Paxos於20世紀90年代推出,是第一個真實的,實用的,容錯的一致性演算法。它是Leslie Lamport首次被廣泛採用的共識演算法之一,並被谷歌和亞馬遜等全球網際網路公司用於構建分散式服務。
Paxos的工作方式如下:
階段1:準備請求

  1. 提議者選擇新的提案版本號(n)並向接受者傳送“準備請求”。
  2. 如果接受者收到準備請求(“prepare”,n),其n大於他們已經回覆的任何準備請求,接受者發出(“ack",n,n,v)或(“ack", n,^,^)。
  3. 受理人回應時承諾不再接受編號小於n的任何提案。
  4. 接受者建議他們已接受的最高數量提案的值(v)(如果有的話)。否則,他們用^回應。

階段2:接受請求
  • 如果提議者收到來自大多數接受者的響應,那麼它可以發出一個接受請求(“accept”,n,v),其數量為n,值為v。
  • n是準備請求中出現的數字。
  • v是響應中編號最高的提議的值。
  • 如果接受者收到一個接受請求(“accept,”n,v),它接受該提議,除非它已經響應了一個數字大於n的準備請求。

階段3:學習階段
  • 每當接受者接受提議時,它都會響應所有學習者(“accept”,“n”,“v”)。
  • 學習者從大多數接受者接收(“accept”,n,v),決定v,並向所有其他學習者傳送(“decide”,v)。
  • 學習者接受(“decide”,v)和決定的v。

唷!困惑了嗎?我知道這是一個需要消化的大量資訊。
但是等等......還有更多!
我們現在知道,每個分散式系統都有故障。在該演算法中,如果提議者失敗(例如,因為存在遺漏錯誤),則可以延遲決策。Paxos透過從第1階段的新版本號開始處理此問題,即使之前的嘗試從未結束。
我不會詳細介紹,但在這種情況下恢復正常執行的程式非常複雜,因為預計流程會介入並推動解決流程。
Paxos難以理解的主要原因是它的許多實現細節都留給了讀者的解釋:我們如何知道提議者什麼時候失敗?我們是否使用同步時鐘來設定超時時間來決定提議者何時失敗並且我們需要繼續下一個等級?
為了提供實施的靈活性,關鍵領域的幾個規範是開放式的。領導者選舉,故障檢測和日誌管理等內容模糊或完全不明確
這種設計選擇最終成為Paxos最大的缺點之一。它不僅難以理解,而且難以實施。反過來,這使得分散式系統領域難以駕馭。
到目前為止,您可能想知道同步假設的來源。
在Paxos中,雖然演算法中沒有明確的超時,但在實際實現時,在一些超時時間之後選擇一個新的提議者是實現終止所必需的。否則,我們無法保證接受器會輸出下一個值,系統可能會停止執行。

Raft
2013年,Ongaro和Ousterhout釋出了一種名為Raft的複製狀態機的新共識演算法,其核心目標是可理解性(與Paxos不同)。
我們從Raft學到的一個重要新事物是使用共享超時來處理最終結果的概念。在Raft中,如果你崩潰並重新啟動,你需要等待至少一個超時時間才能讓自己被宣佈為領導者,並保證你取得進步。

但是等等......“拜占庭”環境怎麼樣?
雖然傳統的共識演算法(例如Paxos和Raft)能夠使用某種程度的同步假設(即超時)在非同步環境中茁壯成長,但它們不是拜占庭容錯的。它們只是崩潰容錯的。
崩潰故障更容易處理,因為我們可以將程式建模為工作或崩潰 - 0或1.程式不能惡意行事並撒謊。因此,在崩潰容錯系統中,可以構建分散式系統,其中簡單多數足以達成共識。
在開放和分散的系統(例如公共區塊鏈)中,使用者無法控制網路中的節點。相反,每個節點都會針對其各自的目標做出決策,這可能與其他節點的目標衝突。
在拜占庭系統中,節點具有不同的激勵,可以撒謊,協調或任意行動,你不能假設簡單的多數足以達成共識。半數或更多的所謂誠實節點可以相互協調以便撒謊。
例如,如果當選的領導者是拜占庭並且與其他節點保持強大的網路連線,則可能危及系統。回想一下我們如何說我們必須對我們的系統建模,以容忍簡單的故障或拜占庭故障。Raft和Paxos是簡單的容錯但不是拜占庭容錯。它們不是為容忍惡意行為而設計的。

'拜占庭將軍的問題'
試圖建立一個可以處理提供衝突資訊的程式的可靠計算機系統正式被稱為“ 拜占庭一般問題 ”。拜占庭容錯協議應該能夠實現其共同目標,即使是針對節點的惡意行為。
論文“ 拜占庭將軍問題 ”由Leslie Lamport, Robert Shostak, 和Marshall Pease提供的第一手證據,以解決拜占庭將軍的問題:它表明,一個系統X拜占庭節點必須有至少3個+ 1的總節點,以達到共識。
原因如下:
如果x節點出現故障,則系統需要在與n減x節點協調後才能正常執行(因為x節點可能有故障/拜占庭並且沒有響應)。但是,我們必須為不響應的x可能沒有錯誤做準備; 它可能是X是不回應。如果我們希望非故障節點的數量超過故障節點的數量,我們至少需要n減x減x> x。因此,n> 3x + 1是最佳的。
但是,本文中演示的演算法僅適用於同步環境。而拜占庭+非同步的環境似乎更難設計。
為什麼?
簡而言之,建立一個能夠承受非同步環境和拜占庭環境的共識演算法......好吧,這就像創造奇蹟一樣。
像Paxos和Raft這樣的演算法是眾所周知的並且被廣泛使用。但也有很多學術工作更側重於解決拜占庭+非同步設定中的共識問題。

所以扣上你的安全帶......
我們正在實地考察......
到...的土地
理論學術論文!

(見下頁)

相關文章