分佈式共識問題

在講述分佈式的共識問題之前,我們先了解下什麼是拜占庭將軍問題, 其次從拜占庭將軍問題來認識什麼是分佈式共識問題,與分佈式一致性的區分在哪裏?然後推演分佈式共識問題產生的原因以及解決共識問題的策略算法有哪些,對應的適用場景有哪些?接下來我們可以帶着疑問來逐步揭開上述問題的本質.另外這裏要先說明一點,這裏講述的服務節點不可用包含網絡超時/服務節點出現故障/網絡通信被僞造等情況.

拜占庭將軍問題

拜占庭一般性問題

  • 拜占庭軍隊中的每一個師都有自己的將軍,並且由該將軍負責指揮作戰
  • 現在拜占庭軍隊中的將軍存在一些叛徒,將軍們可以通過信使進行相互溝通作戰方案
  • 現在對拜占庭軍隊要求是:
  1. 所有忠實的將軍都能夠採取相同的作戰計劃.
  2. 少數叛徒不會使忠誠的將軍們採取錯誤的計劃從而導致最終的作戰失敗.

問題重述

  • 所有忠誠的將軍都得到同樣的信息,他們將以某種方式得到同樣的決定
  • 一個忠誠的將軍發出的信息應該被所有其他忠誠的將軍所採用

什麼是拜占庭將軍問題

基於上述的問題的理解,假設現在拜占庭軍隊中有三個師,每個師都有自己的將軍,現在要準備開始作戰計劃攻打城池,現在需要滿足上述講到的要求,即保證每個師的忠誠將軍都能夠採取相同的作戰計劃以防止被叛徒信息誤導採取錯誤的決定.此時需要每個師派發行使進行通信協商,同時爲了保證協商存在可靠性,即下面的半數投票的可靠性.

少數服從多數的投票可靠性
  • 每個師的將軍可以發表自己對作戰方案的計劃,並通過信使通知其他師的將軍們
  • 其次,每個師的將軍接收到其他師的將軍們的作戰方案時候,採取默認少數服從多數的方案作爲作戰方案執行.

這個時候我們可以看到,每一個師的將軍都能夠提供方案,說明是具備作戰的指揮權的,相對地,其他師的將軍就作爲副官,負責執行作戰方案.於是對於一個拜占庭將軍問題可以進行以下歸納.

拜占庭將軍問題

我們可以將問題進行簡化爲一系列由一個指揮官和多個副官組成的問題,即拜占庭將軍問題:

  • 如果所有的副官都是忠誠的,那麼他們必然遵循相同的作戰命令
  • 如果指揮官是忠誠的,那麼所有忠實的副官也都會遵循其所發出的命令

簡而言之,拜占庭將軍問題就是如何在可能存在有叛徒的情況下,採取合適的通信機制來保證忠誠的將軍能夠達成共識採取一致的作戰計劃.

不可能的結果

如果忠實於將軍的將軍少於或等於2/3,則不存在解決方案.

分佈式共識問題

什麼是分佈式共識問題

基於拜占庭將軍問題的分析,我們將其翻譯爲分佈式系統相關的術語,並對其進行闡述如下:

  • 拜占庭將軍: 即分佈式系統的服務節點
  • 忠誠的拜占庭將軍: 即分佈式系統服務正常運作的服務節點
  • 叛變的拜占庭將軍: 出現故障併發送誤導信息的服務節點
  • 信使被殺: 服務節點之間出現通信故障,導致信息丟失
  • 信使被間諜替換: 服務節點進行網絡通信過程中信息被黑客攻擊,通信存在劫持以及信息僞造

而分佈式共識問題就是在分佈式系統中,我們要如何保證系統服務節點之間的通信接收到的消息指令都是可靠且一致的.

分佈式共識與一致性區分

在這裏插入圖片描述
在講述分佈式的共識與一致性之前,我們先來看下上述的圖解,用戶發起請求向分佈式系統集羣服務請求資源然後服務資源給予響應,這個時候我們考慮以下的場景:

  • 首先,用戶A先發起一個事務操作的請求到集羣服務,這個時候集羣服務接收到事務操作請求,這個時候問題來了,集羣服務存儲節點誰來負責處理事務請求的操作,進行事務操作之後數據如何同步到各個服務節點上,即集羣服務節點如何對事務請求操作達成共識.
  • 其次,用戶B發起一個非事務的讀取請求到集羣服務中,此時讀取到數據應當是A進行事務操作之後最新的數據,也就是集羣服務節點需要保證給到用戶B的數據是最新修改的數據,即服務節點的一致性問題.

從上述可以看到,對於分佈式系統的共識與一致性問題其實關注的點不一樣的,即:

  • 分佈式共識問題:迴歸到事務請求操作的思考層面,就拿扣減庫存的分佈式事務爲例,它必須保證併發的原子性操作,那麼此時我們就需要對共享資源進行加鎖互斥保證集羣中只有一個節點能夠進行事務操作;其次當服務節點完成事務操作之後,還需要進行數據同步到冗餘服務節點上,那麼進行事務操作的服務節點必須向集羣其他節點發起數據同步操作並等待響應(是不是類似於上述的拜占庭將軍問題);另外關於分佈式共識還包含通過原子組播的方式處理進程對消息傳遞的順序一致性.
  • 分佈式一致性: 通過上述的查詢請求操作,即對於集羣冗餘服務的數據副本之間對外表現的數據是一致的,類似於JDK中的valotile機制,保證在多核CPU處理器上讀取到數據是最新修改的.(後續再單獨說明分佈式的一致性)

分佈式共識問題,即爲了達到共識,每個進程都提出自己的提議(propose),最終通過共識算法,所有正確運行的進程決定(decide)相同的值,如下圖所示:
在這裏插入圖片描述
在上面的圖示可以看出,不同的進程p0,p1,p2以及p3分別輸入一個數據值,然後通過執行程序來處理並交換輸入值,保證最終輸出的數據值都是一致的.即不同進程的輸入值通過自身相同的一套程序進行交換處理輸入數據並最終都輸出一致的數據v.

分佈式共識特性

摘錄分佈式共識的英文闡述如下:

1.Termination: Every non-faulty process must eventually decide
2.Agreement: The final decision of every non-faulty process must be identical
3.Validity: If every non-faulty process begins with the same initial value v, then their final decision must be v

  • 終止: 每個非故障的進程最終必須作出提案的決策
  • 協議: 每一個非故障的進程最終作出的提案決策都必須是一致的
  • 有效性: 如果每一個非故障的進程均以相同的初始化值v作爲提案的輸入,那麼最終提案決策的輸出都必須爲v.

對於分佈式共識應用場景有:

  • 集羣服務節點的Master/Leader選舉策略
  • 集羣服務節點進程加鎖資源互斥
  • 集羣中某一個服務節點故障的判定策略
  • 時鐘相位同步問題
  • ATC服務(Air Traffic Control): 空中交管控制系統,即所有的在空飛機都看到畫面都是一致的(Air traffic control system: all aircrafts must have the same view)

關於ATC可以參考:https://science.howstuffworks.com/transport/flight/modern/air-traffic-control.htm

共識問題推演

問題推演

基於拜占庭將軍問題,現假設有三個軍隊的將軍,現在準備擬定攻城的計劃,三個將軍對此進行各自擬定計劃(進攻或者是撤退的策略)並由信使負責消息的傳遞,最終通過“少數服從多數”原則來決定最終的決策方案.

正常情況
  • 三個軍的將軍都是忠誠的,那麼對於發出進攻或者是撤退的策略最終應當是一致的

在這裏插入圖片描述
A將軍此時發起決策提案爲進攻,對於B和C正常接收到的信息是進攻;B將軍發起的決策提案爲撤退,對於A和C正常接收到的信息爲撤退,C將軍發起的決策提案爲進攻,那麼這個時候對於A和B看到的提案爲進攻,這個時候我們分別思考A,B,C三位將軍接收到的提案爲:

A將軍: 自己進攻的提案 + B將軍的撤退提案 + C將軍的攻擊提案,因此最終決定進攻.

B將軍:自己撤退的提案 + A將軍的進攻提案 + C將軍的進攻提案,因此最終決定也是進攻.

C將軍: 自己進攻的提案 + B將軍的撤退提案 + A將軍的進攻提案,因此最終決定也是進攻.

但是這個時候我們需要看到上述決策成功需要滿足要求:

1.所有的將軍都是忠誠的
2.在上述的半數投票過程中,需要滿足參與投票的將軍個數爲2n+1,不然無法決定投票結果.

二忠一叛問題

如果三個將軍中有一個將軍出現問題,那麼此時的情況又被變成如下的情況:

1.其中一個將軍爲叛徒
2.其中一個將軍的信使被間諜替換
3.其中一個將軍的信使中途被殺

  • 如果其中一個將軍爲叛徒抑或是C將軍的信使被間諜替換,假設爲C將軍叛變,那麼此時產生的情況如下:

在這裏插入圖片描述
A將軍: 自己進攻的提案 + B將軍的撤退提案 + C將軍的攻擊提案,因此最終決定進攻.

B將軍:自己撤退的提案 + A將軍的進攻提案 + C將軍的撤退提案,因此最終決定是撤退.

C將軍: 因爲自己本身是叛軍,當然在戰場上肯定也是撤退

這個時候三位將軍採取最終方案是不一致的,這樣會導致A將軍直接受到伏擊被敵軍殲滅;

  • 如果C將軍的信是中途被截殺,那麼此時產生的情況如下:

在這裏插入圖片描述

A將軍: 只接收到B將軍的撤退提案 + 自己攻擊的提案, 這個時候是無法進行決策

B將軍: 只接收到A將軍的攻擊提案 + 自己撤退的提案, 這個時候也無法進行決策

C將軍: 接收到A將軍的攻擊提案 + 自己的攻擊提案 + B將軍的撤退提案,採取攻擊提案.

這個時候可以看到A,B,C三位將軍最後做決策的時候將無法保證最終的提案一致性而採取相同的行動.

問題小結

通過上述的分析,我們將其轉化爲分佈式系統集羣三個服務節點A,B,C之間可能存在的問題如下:

當向分佈式系統集羣服務發起事務操作請求的時候,如果這個時候存在服務節點發生故障(信使被截殺)抑或是服務節點在消息通信過程被劫持,整個集羣服務節點將無法對當前的事務請求操作採取一致性的行動.

口頭消息的解決方案

無簽名的口頭消息要求以及含義
  • A1:每個服務節點發送的每條消息都能夠被正確接收

1.連接兩個服務節點之間的通信介質的故障與服務節點發生的故障是無法區分的.如超時網絡不通/服務節點宕機均爲不可用等均視爲服務節點不可用
2.如果出現線路故障表示分佈式系統中的集羣服務節點多了一個不可用的服務節點.

  • A2:集羣服務節點知道消息發送者的信息

不需要通過網絡交換就能知道消息發送者的信息

  • A3:能夠檢測到集羣其他服務節點的心跳

需要有超時機制

口頭消息的算法

算法定義

基於上述的假設,現有一個算法函數major滿足fn=(V1,V2,…Vn-1),該函數表示集羣服務節點中每個節點一個提案值vi,fn表示集羣中vi佔過半投票對應的提案值v,而口頭消息解決算法有一個前提條件,那就是必須是集羣服務節點不可用的個數m必須滿足m<n/3,(n爲當前集羣服務節點的總數),也就是集羣服務節點總數n最小值爲n=3m+1.而對於算法的描述存在兩種選擇如下:

  • 如果v的提案值存在那麼就執行提案值v的動作,否則採取默認的行爲(撤退)
  • 其次,假設vi 爲上述(V1,V2,…Vn-1)一系列有序的集合數據的中位數,那麼就執行vi的提案

算法描述

現對於3m+1的集羣服務節點選舉一個具備指揮權的服務節點作爲leader,其他節點作爲replicate,這個時候存在以下兩種情況

當m=0時,即不存在服務節點不可用時,其算法執行的策略爲:

  • leader節點向每個replicate節點發送其提案指令v
  • 所有replicate節點接收到其提案指令v的消息時執行,如果沒有收到執行默認的“撤退”行爲.

當m>0時,其執行的算法如下:

  • leader節點向每個replicate節點發送其提案指令v
  • 所有replicate節點接收到提案指令v的消息時作爲執行命令的提案vi,如果沒有收到消息則把默認的“撤退”行爲作爲其執行的提案vi,並此時的服務節點作爲一個新的leader向其他n-2個服務節點(自己節點以及上一個leader節點)發起提案vi
  • 對於replicate節點(V1,V2,…Vn-1),假設當前服務節點爲V1,那麼V1節點在經過上述步驟2的操作之後,也會接收到其他服務節點(V2,V3,…Vn-1)節點的消息提案,分別設置對應值爲v2,v3,…vn-1,其中每一個節點發送過來的提案值都是採取上一步的動作,除了其中的不可用的服務節點.

經過上述的算法,對於存在m個不可用或者是不可靠的服務節點,需要經過m+1次的遞歸發起提案請求,同時可以遞歸推導得出O(m)調用(n-1)次遞歸獨立執行O(m-1).

口頭消息解決方案分析

基於上述的分析,如果僅有上述的集羣服務的3個節點,基於口信消息的方案是無法解決拜占庭將軍問題的,現分析如下:

  • 現在我們從服務集羣中選舉一個節點作爲具備指揮權的服務節點,比如服務節點A

在這裏插入圖片描述

對於上述集羣服務節點A,B,C節點中,對於B而言不論A是叛變還是C是叛變的,都無法作出決策,說明信消息要達到交互的一致性在集羣中只有3個服務節點要是無法做到.

基於此,我們需要將軍隊多劃出一個獨立軍隊,產生一個新的指揮官,而A,B,C作爲副官,負責執行提案策略.這個時候基於上述的算法就有以下情況.

在這裏插入圖片描述

從上述可以看出:

  • 如果是C將軍爲叛變將,最後不論結果如何,指揮官以及A和B將軍會採取進攻的策略;
  • 如果是指揮官是叛變的話,那麼對於A,B,C三位將軍最終得出的結果是採取撤退的策略

不論是哪種結果對於忠誠的將士而言最終採取的行動是一致的.

小結

對於我們分佈式互聯網而言,一般在企業內部的集羣機器而言,由於對外存在防火牆以及安全的網關校驗,因此對於企業服務內部都是採取當前的算法策略來解決我們集羣服務選舉,進程互斥以及分佈式事務等問題提供解決方案的思路.對於口信消息的算法,一般用於系統容錯故障但不存在惡意攻擊的服務節點,即CFT算法,這個場景可能會丟失消息,或者有消息重複,或者是順序一致性處理等場景,其對應的常用算法有Paxos算法、Raft算法、ZAB協議.

簽名消息的解決方案

這個時候我們發現上述的解決方案需要在原有的集羣服務中增加一個leader節點作爲整個集羣具備指揮權的服務節點.那麼是否可以考慮不需要進行加服務節點就能夠解決服務節點之間的共識問題呢?這個時候就需要運用到我們的簽名消息解決方案.

實現簽名消息的要求以及含義
  • A4: 基於上述無簽名消息的要求以及含義基礎上,需要滿足以下條件:

1.集羣服務節點之間的消息通信無法被僞造,任何被僞造的消息都能夠被檢測出來
2.每一個服務節點都能夠覈實消息簽名的真實身份.

消息簽名的算法

算法要求

基於上述A1-A4的假設要求,如果存在m個不可用的服務節點,那麼整個集羣的服務節點必須是不少於m+2,否則無法得到問題的解決.該算法爲空洞.

算法的定義

我們定義一個函數fn=choice(V)表示有序的集合中存在簽名的消息元素v,如果集合中只有一條消息元素v,那麼fn=v.

  • 如果集合V中僅包含一個元素v,則choice(V)=v
  • 如果集合爲空,那麼執行默認的“撤退”行爲,即choice(V)=RETREAT.

算法描述

在該算法中,指揮權的服務節點向其他服務節點發送一個按照一定規則簽名的消息到其他服務節點中,其他服務節點接收到消息之後將其簽名添加到有序的簽名消息中並進行發送到其他服務節點中,其他服務節點以此類推.如果存在服務節點“叛變”,必須有效地接收簽名的消息,並對簽名消息生成多份副本,然後再將這些副本進行簽名然後發送到其他節點中.最後不論副本是如何得到,其中單條簽名的消息要麼是被通過副本拷貝要麼是與單條簽名一致並正確分發過來的消息.

  • 指揮權的服務節點對消息進行簽名併發送到各個服務節點
  • 對於每一個接收簽名消息的服務節點
    • 如果服務節點從指揮節點接收以v:0的簽名消息並且還沒有接收到其他簽名消息的時候,那麼對於當前節點i設置選擇提案值爲choice(V)=v,並且以消息v:0:i的形式發送到其他非指揮權的服務節點上.
    • 如果服務節點接收到消息形如v:0:j1...:jk並且v並不在集合V中,那麼對於當前的服務節點將會把v添加到集合V中並當k<m的時候將以消息爲v:0j1…:jk:i的形式發送到其他服務節點,否則將以消息爲`v:0:j1…:jk的形式發送到其他服務節點上.
  • 最後對於每一個服務節點i,如果沒有接收到更多簽名消息的時候,服務節點將會遵循選舉從有序的集合V中獲取提案v並執行.
消息簽名算法分析

基於上述的算法,我們仍然用拜占庭將軍爲例子進行分析如下:

在這裏插入圖片描述

  • 在左側圖中,由A將軍發起進攻指令,B和C將軍均收到A將軍發出的指令,如果C將軍爲叛軍,那麼必然會篡改消息並進行簽名發送給B將軍,B將軍識別到C將軍發送的消息是僞造的,於是直接丟棄C將軍的指令,最後執行進攻指令.
  • 如果A將軍爲叛軍,此時分別向B和C發送不同的指令,B和C將軍接收到消息並存儲在一個有序的集合中,即B存儲[進攻, 撤退],C存儲[撤退,進攻],根據上述的算法,集合中是有序的,那麼對於B和C存儲的集合指令也應當是有序且一致的,即均爲[進攻,撤退]或者是[撤退,進攻]這樣的有序集合,然後按照一定的選舉策略(比如選舉中間值)執行對應的指令,這樣也保證了B和C交互的一致性.
小結

最後關於消息簽名的算法,從上面我們可以看到是去中心化的一個分佈式系統架構服務,因此對於公網環境下執行事務型操作可以考慮使用消息簽名的算法,最大優勢在於去中心化.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章