分布式一致性協議

gossip協議

我們的辦公室八卦一般都是從一次交談開始,只要一個人八卦一下,在有限的時間內辦公室的的人都會知道該八卦的信息,這種方式也與病毒傳播類似。因此 Gossip也有“病毒感染算法”、“謠言傳播算法”之稱。

Cassandra,amazon s3,等在使用gossip協議

一般情況是這樣的,集群中的節點P隨機選擇另一個節點Q,兩個節點互相交換信息,如果Q有消息需要更新的話,那么Q繼續去集群中尋找其他的節點,再次進行信息的交換,就這樣一次次的交換,知道所有的節點消息都為最新的位置.

在Q和P的信息交換,一般有以下3種方式:

  1. push:P講信息推送給Q,Q判斷是否比本地信息新,如果是的話,更新本地信息
    if P.value.time>Q..value.time
    Q..value = P.value
  2. pull: P從Q那拉取信息,如果Q的消息比P新,則更新P的消息
    if P.value.time>Q..value.time
    P.value = Q..value
  3. push-pull: P和Q同時進行Push和pull
    if P.value.time>Q..value.time
    Q..value = P.value
    else
    P.value = Q..value

push剛開始傳播快,后來慢,pull相反。push-pull模式是最快的

PAXOS協議

Paxos算法分為兩個階段。具體如下:

  • 階段一:
    (a) Proposer選擇一個提案編號N,然后向半數以上的Acceptor發送編號為N的Prepare請求。
    (b) 如果一個Acceptor收到一個編號為N的Prepare請求,且N大于該Acceptor已經響應過的所有Prepare請求的編號,那么它就會將它已經接受過的編號最大的提案(如果有的話)作為響應反饋給Proposer,同時該Acceptor承諾不再接受任何編號小于N的提案。

  • 階段二:
    (a) 如果Proposer收到半數以上Acceptor對其發出的編號為N的Prepare請求的響應,那么它就會發送一個針對[N,V]提案的Accept請求給半數以上的Acceptor。注意:V就是收到的響應中編號最大的提案的value,如果響應中不包含任何提案,那么V就由Proposer自己決定。
    (b) 如果Acceptor收到一個針對編號為N的提案的Accept請求,只要該Acceptor沒有對編號大于N的Prepare請求做出過響應,它就接受該提案。

ZAB協議

設計目標

  • 一致性
  • 有序性:有序性是 Zab 協議與 Paxos 協議的一個核心區別。Zab 的有序性主要表現在兩個方面:
    a. 全局有序:如果消息 a 在消息 b 之前被投遞,那么在任何一臺服務器,消息 a都會在消息 b 之前被投遞。
    b. 因果有序:如果消息 a 在消息 b 之前發生(a 導致了 b),并被一起發送,則 a 始終在 b 之前被執行。
  • 容錯性:有 2f+1 臺服務器,只要有大于等于 f+1 臺的服務器正常工作,就能完全正常工作。

協議內容

Zab 協議分為兩大塊:

  • 廣播(boardcast):Zab 協議中,所有的寫請求都由 leader 來處理。正常工作狀態下,leader 接收請求并通過廣播協議來處理。
  • 恢復(recovery):當服務初次啟動,或者 leader 節點掛了,系統就會進入恢復模式,直到選出了有合法數量 follower 的新 leader,然后新 leader 負責將整個系統同步到最新狀態。

raft協議

leader選舉:

leader周期性地heartbeat到所有的follower。follower如果能收到leader發來的消息,那么就保持follower狀態。如果follower一段時間收到不消息了,則開始新的選主。

首先當前term計數加1,然后給自己投票并向其它結點發投票請求。直到以下三種情況:

  • 它贏得選舉
  • 另一個服務器成為leader
  • 持續一段時間沒有主機勝出
    在選主期間,candidate可能收到來自其它自稱為leader的寫請求,如果該leader的term不小于candidate的當前term,那么candidate承認它是一個合法的leader并回到follower狀態,否則拒絕請求。
    如果出現兩個candidate得票一樣多,則它們都無法獲取超過半數投票。這種情況會持續到超時。然后進行新一輪的選舉。
    使用隨機的選舉超時,這樣不容易發生上面情況。

日志復制

leader收到client寫請求后,先寫自己的log,然后發到所有服務器,當確認記錄已安全復制后,回應client。
每條日志記錄會存命令以及term編號,term編號用于檢測日志的不一致。
每個提交的記錄都是持久的,并且是最終一致的。當log記錄成功復投票請求中包含了這個限制:請求中有關于candidate的log信息制到大多數服務器時,記錄被提交。如果投票者的log比它新,則拒絕請求。
沖突解決,leader通過強制follower復制自己的log來處理不一致。

安全

舉個例子,一個follower可能一段時間不可用,期間leader持續提交了多次log,然后這個follower被選為leader了,那么它會覆蓋掉提交的記錄。
所以要限制哪些服務器可以被選為leader。使用投票過程阻止candidate選舉中獲勝,除非它的log包含了所有已提交的記錄。
因為要獲得超過半數的投票,那么candidate至少要跟大多數的log一樣新。這樣它擁有所有提交的記錄。投票請求中包含了這個限制:請求中有關于candidate的log信息,如果投票者的log比它新,則拒絕請求。
如果follower或candidate崩潰了,那么發給它的請求會失敗,raft將無限次的重試。當它恢復后,會繼續收到未完成的請求。如果一個服務器完成了請求但尚未回復,接著crash了,那么它重啟后會收到相同的請求。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容