一致性協議總覽

一致性模型

一致性模型本質上是進程與數據存儲的約定,主要是用於解決分佈式系統中數據複製時保持一致性的問題

 

一致性協議

一致性模型就像是接口,而一致性協議就像是接口的具體實現

一致性協議根據是否允許數據分歧可以分爲兩種:

單主協議(不允許數據分歧):整個分佈式系統就像一個單體系統,所有寫操作都由主節點處理並且同步給其他副本。例如主備同步、2PC、Paxos 都屬於這類協議(zab和raft屬於paxos的簡化版)

 

多主協議(允許數據分歧):所有寫操作可以由不同節點發起,並且同步給其他副本。例如 Gossip、POW。

它們的核心區別在於是否允許多個節點發起寫操作,單主協議只允許由主節點發起寫操作,因此它可以保證操作有序性,一致性更強。而多主協議允許多個節點發起寫操作,因此它不能保證操作的有序性,只能做到弱一致性

 

單主協議

單主協議的共同點在於都會用一個主節點來負責寫操作,這樣能夠保證全局寫的順序一致性,它有另一個名字叫定序器,非常的形象

(1)主備複製--最終一致性

主備複製可以說是最常用的數據複製方法,也是最基礎的方法,很多其他協議都是基於它的變種。 主備複製要求所有的寫操作都在主節點上進行,然後將操作的日誌發送給其他副本。可以發現由於主備複製是有延遲的,所以它實現的是最終一致性

主備複製的實現方式:主節點處理完寫操作之後立即返回結果給客戶端,寫操作的日誌異步同步給其他副本。這樣的好處是性能高,客戶端不需要等待數據同步,缺點是如果主節點同步數據給副本之前數據缺失了,那麼這些數據就永久丟失了。MySQL 的主備同步就是典型的異步複製。

 

(2)兩階段提交--順序一致性

兩階段提交(2PC)是關係型數據庫常用的保持分佈式事務一致性的協議,它也屬於同步複製協議,即數據都同步完成之後才返回客戶端結果。可以發現 2PC 保證所有節點數據一致之後才返回給客戶端,實現了順序一致性

2PC特點:有一個參與者執行失敗,協調者會讓所有參與者回滾

 

2PC 把數據複製分爲兩步:

表決階段:主節點將數據發送給所有副本,每個副本都要響應提交或者回滾,如果副本投票提交,那麼它會將數據放到暫存區域,等待最終提交

提交階段:主節點收到其他副本的響應,如果副本都認爲可以提交,那麼就發送確認提交給所有副本讓它們提交更新,數據就會從暫存區域移到永久區域。只要有一個副本返回回滾就整體回滾

可以發現 2PC 是典型的 CA 系統,爲了保證一致性和可用性,2PC 一旦出現網絡分區或者節點不可用就會被拒絕寫操作,把系統變成只讀的。由於 2PC 容易出現節點宕機導致一直阻塞的情況,所以在數據複製的場景中不常用,一般多用於分佈式事務中(注:實際應用過程中會有很多優化,例如3PC)

(3)分區容忍的一致性協議 -- 順序一致性

分區容忍的一致性協議跟所有的單主協議一樣,它也是隻有一個主節點負責寫入(提供順序一致性),但它跟 2PC 的區別在於它只需要保證大多數節點(一般是超過半數)達成一致就可以返回客戶端結果,這樣可以提高了性能,同時也能容忍網絡分區(少數節點分區不會導致整個系統無法運行)

我們熟知的 Paxos、ZAB、Raft 等分區容忍的一致性協議的核心思想:一致性的保證不一定非要所有節點都保持一致,只要大多數節點更新了,對於整個分佈式系統來說數據也是一致性的

 

分區容忍的一致性協議如 Paxos 是典型的 CP 系統,爲了保證一致性和分區容忍,在網絡分區的情況下,允許大多數節點的寫入,通過大多數節點的一致性實現整個系統的一致性,同時讓少數節點停止服務(不能讀寫),放棄整體系統的可用性,也就是說客戶端訪問到少數節點時會失敗

繞過不可用節點

值得注意的是,根據 CAP 理論,假設有三個節點 A、B、C,當 C 被網絡分區時,有查詢請求過來,此時 C 因爲不能和其他節點通信,所以 C 無法對查詢做出響應,也就不具備可用性。但在工程實現上,這個問題是可以被繞過的,當客戶端訪問 C 無法得到響應時,它可以去訪問 A、B,實際上對於整個系統來說還是部分可用性的,並不是說 CP 的系統一定就失去可用性

 

不同的協議有不同的應用場景,例如:

對於數據庫來說由於數據安全比較重要,因此數據庫事務常用2PC來實現順序一致性

而對於註冊中心這種並不需要追求強一致性,就可以使用最終一致性,例如Eureka

 

多主協議--最終一致性

相比單主協議爲了實現順序一致性,不允許多個節點併發寫,多主協議恰恰相反,只保證最終一致性,允許多個節點併發寫,能夠顯著提升系統性能。由於多主協議一般提供的都是最終一致性,所以常用在對數據一致性要求不高的場景中

Gossip 協議 -- 多主協議

Gossip 協議就是一種典型的多主協議,很多分佈式系統都使用它來做數據複製,例如比特幣,作爲一條去中心化的公鏈,所有節點的數據同步都用的是 Gossip 協議。此外,Gossip 協議也在一些分佈式數據庫中如 Dynamo 中被用來做分佈式故障檢測的狀態同步,當有節點故障離開集羣時,其他節點可以快速檢測到

Gossip 協議的核心思想就是:每個節點都可以對其他節點發送消息,接收到消息的節點隨機選擇其他節點發送消息,接收到消息的節點也做同樣的事情

 

併發寫的問題

多主協議允許運行多個節點併發寫,就一定會出現對一個數據併發寫導致數據衝突的情況,因此這類協議都需要解決併發寫的問題。單主協議通過主節點控制寫入,保證不會出現併發寫的情況,因爲所有寫操作最終都會通過主節點排序

性能:

從某種意義上講,使用單主協議的系統對於寫入實際上是串行的,因此其性能是有瓶頸的

而多主協議允許多節點併發寫,提搞了寫入的性能,但是實際上它是把數據合併的操作延遲了,因此讀取數據的時候如果出現數據衝突的時候,就需要對數據進行合併,保證全局一致性

爲什麼比特幣的性能那麼差?

前面我們提到比特幣使用的是 Gossip 協議做數據複製,那麼問題來了,不是說多主協議性能會比較高嗎,爲什麼比特幣的性能那麼差?實際上,雖然比特幣是去中心化的,但是它的支付功能需要保證全局數據一致性,因此它用了一種一致性算法 POW

 

一致性算法 POW

一致性算法 POW:所有節點都做一道數學題,誰先算出答案誰有權利將交易寫到鏈上,然後利用 Gossip 協議傳播它的答案和交易,其他節點驗證它的答案正確就將數據保存起來

那麼POW 作爲多主協議爲什麼性能這麼低?

任何協議都有它適用的場景。在比特幣這個場景中,它對於數據一致性是有強需求的,理論上用單主協議是最優的選擇。但是比特幣作爲去中心化的數字貨幣是不會使用單主協議的,否則又變成中心化的系統了。因此比特幣只能選擇多主協議,通過 POW 協議將比特幣整條鏈操作進行了近似串行化,這樣才能降低出現雙花的概率(併發寫的時候一個比特幣被消費多次),魚與熊掌不可兼得,既然要強一致性,那麼只能犧牲性能來換取

由於多主協議允許了數據分歧,那麼就需要有解決數據衝突的策略來保證最終一致性。如果要嚴格區分的話,比特幣實際上應用了兩個一致性協議:

POW:

決定節點的記賬權,起到類似單主協議中定序器的作用。注意 POW 也是多主協議,儘管概率很低,但是它有可能出現多個節點同時算出答案,一起出塊(併發寫)的情況,此時我們稱比特幣出現了分叉,即出現了數據衝突

 

Gossip:

用於將出塊的交易同步到全球所有節點。由於 POW 會出現併發寫的情況,當一個節點同時接受到多個節點寫入請求時,就需要解決數據衝突的問題。比特幣解決數據衝突的方式就是當出現分叉時,選取最長的那條鏈作爲主鏈,其他分叉的鏈上的交易會被回滾,等待重新打包出塊

總結

本文主要從是否允許數據分歧的角度將分佈式一致性協議分爲兩種:單主協議和多主協議。其中單主協議會用一個主節點來負責寫操作,這樣能夠保證全局寫的順序一致性,但因此也犧牲了一部分性能。而多主協議則允許寫操作可以由不同節點發起,並且同步給其他副本,只能保證最終一致性,但因此也提升了系統併發寫入的性能

對數據一致性要求高的場景例如分佈式數據庫,主要會使用單主協議,對數據一致性要求不高例如故障檢測,主要會使用多主協議來提高性能,當然也有特例,像比特幣爲了去中心化使用 POW 和 Gossip 結合進行數據複製

 

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