一致性協議和paxos算法

集中式和分佈式的架構

所謂的集中式系統就是由由一臺或多臺主計算機組成中心節點,數據集中存儲於這個中心節點,整個系統的所有業務單元都集中部署在這個中心節點上,系統的所有功能均由其集中處理。集中式系統最大的特點就是部署結構簡單。由於集中式系統往往基於底層性能卓越的大型主機,因此無須考慮如何對服務進行多個節點的部署,也就不用考慮多個節點之間的分佈式協作問題。

分佈式系統是一個硬件活軟件組件分佈在不同的網絡計算機上,彼此之間僅僅通過消息傳遞進行通信和協調的系統,嚴格的說,一個分佈式系統的計算機在空間部署上可以任意分佈,可以在不同的機櫃,不同的機房甚至不同的城市。

 

分佈式環境面臨的問題

通信異常:分佈式系統需要在各個節點之間進行網絡通信,因此會伴隨網絡不可用的風險,包括網絡光纖,路由器或是DNS等硬件設備等風險故障,即使分佈式各節點之間的網絡通信正常,其延遲也會大於單機的操作數百倍,消息丟失和延遲變得非常普遍

網絡分區:由於各節點之間的網絡延遲不斷增大,最終可能導致組成分佈式系統的部分節點無法正常通行,稱之“網絡分區”,俗稱“腦裂”,並由此引發各種數據一致性的問題。數據超時等問題

節點故障:分佈式系統中的部分服務節點出現宕機等問題,導致系統不可用。

分佈式事務:分佈式事務指的是事務的參與者,支持事務的服務器、資源服務器以及事務管理器分別位於分佈式系統的不同節點上,通常一個分佈式事務中會涉及多個數據源或業務系統的操作,在單機服務中我們很容易實現一套滿足ACID特性的事務處理系統,在但分佈式數據服務中,由於數據節點可能分佈在不同的機器上,各個子事務的執行就是分佈式的,實現一種能夠保證ACID的分佈式事務處理系統顯得格外複雜

 

CAP和BASE理論

CAP理論

2000 年 7 月,來自加州大學伯克利分校的 Eric Brewe 教授在 ACM PODC會議上,首次提出著名的 CAP 猜想,2 年後,來自麻省理工學院的Seth Gilbert 和 Nancy Lynch 從理論上證明了 Brewer 教授 CAP 猜想的可行性, CAP 理論正式在學術上成爲了分佈式計算領域的公認定理,並深深地影響了分佈式計算的發展

CAP 理論:一個分佈式系統不可能同時滿足一致性(Consistency )、可用性 ( Availability )和分區容錯性(Partition Tolerance)這三個基本需求,最多隻能同時滿足其中2項

一致性Consistency :

在分佈式環境中,一致性是指數據在多個副本之間能夠保持一致的特定,在一致性的需求下,當一個系統在數據一致的狀態下執行更新操作後,應該保證系統的數據仍然處於一致的狀態(如對第一個節點對數據進行更新操作並且更新成功,卻沒有對第二個節點的數據更新導致第二個節點在讀取數據時候讀取的是髒數據,這就是典型的分佈式數據不一致情況),在分佈式系統中如果能夠做到針對一個數據的更新執行成功後所有用戶都可以讀取最新的數據,那麼認爲這樣的系統具有強一致性

可用性Availability :

可用性指系統提供的服務必須一致處於可用的狀態,對於用戶的每個操作都會在有限的時間內返回結果

分區容錯性Partition Tolerance:

分區容錯性指分佈式系統在遇到任何網絡分區故障時候,仍然需要能夠對外提供滿足一致性和可用性的服務,除非整個網絡環境都發生故障(網絡分區指分佈式系統中不同節點由於分佈在不同的子網絡,由於特殊原因而導致子網絡之間出現網絡不通的狀態,但是各個子網絡內部網絡是正常的,從而導致整個系統的網絡環境被切分若干個孤立的區域)

CAP理論的應用

序號 放棄CAP 說明
1 放棄P,滿足AC 如果希望能夠避免系統出現分區容錯性問題,可以將數據和服務都放在一個節點上(或僅僅是哪些與事務有關的數據),可以避免因網絡引起的負面影響,充分保證系統的可用性和一致性。但放棄P意味着放棄了系統的可擴展性
2 放棄A,滿足PC 當節點故障或者網絡故障時,受到影響的服務需要等待一定的時間,因此在等待時間裏,系統無法對外提供正常服務,即是不可用的
3 放棄C,滿足AP 這裏的放棄一致性是指數據的強一致性,而保留系統的最終一致性,系統無法保證數據的實時一致性,但是承諾數據最終會保證一致性。因此存在數據不一致的窗口期,至於窗口期的長短取決於系統的設計,主要包括數據副本在不同節點之間複製時間的長短

從CAP理論中,我們可以看出一個分佈式系統不可能同事滿足一致性、可用性和分區容錯性,另一方面,需要明確的是,對於一個分佈式系統而言,分區容錯性可以說是一個基本的要求,因爲分佈式系統中的組件必然會被部署到不同的節點,否則就無所謂什麼分佈式系統了,也就必然出現子網絡和網絡問題,因此分區容錯性成了分佈式系統必然需要面對解決的問題,而需要根據業務特點在C(一致性)和A(可用性)之間尋求平衡,所以一般分佈式系統是滿足AP或者CP的。

 

BASE理論

BASE是Basically Available (基本可用)、Soft state(軟狀態)和Eventually consistent(最終一致性)三個短語的縮寫,是由eBay的架構師Dan Pritchett提出,BASE理論是對CAP中一致性和可用性權衡的結果,來源於大規模互聯網系統分佈式實踐的總結,基於CAP演化而來,核心思想是:即使無法做到強一致性(Strong consistency),但每次應用都可以根據自身業務特點,採用適當的方式使系統達到最終一致性(Event consistency)。

基本可用

基本可用指分佈式系統出現不可預知的故障時候,允許損失部分可用性(這不等價系統不可用,而是比如:響應時間的損失,原來0.5s返回響應,現在需要1-2s,或功能的損失,在大併發請求下部分用戶被引導到降級頁面)

軟狀態

允許系統中數據存在中間狀態,中間狀態的存在不影響系統整體的可用性,即允許系統在不同節點的數據副本之間進行同步的過程存在延時

最終一致性

最終一致性強調的是系統中的所有數據副本,在經過一段時間的同步後,最終能夠達到一個一致的狀態,因此最終一致性的本質是需要系統保證數據最終一致而不是實時一致的強一致性

總的來說,BASE理論面向的是大型高可用可擴展的分佈式系統,和傳統事務的ACID特性是想法的,不同於ACID的強一致性模型,而是通過犧牲強一致性來保證可用性,允許數據一段時間內不一致,而保證最終的一致性。

 

一致性協議

對一個分佈式系統進行架構設計的過程中,在系統的可用性和數據一致性之間需要進行反覆的權衡,爲了解決分佈式一致性的問題,出現許多經典的一致性協議和算法,主要有:二階段提交協議、三階段提交協議和Paxos算法等

 

2PC和3PC協議 

在分佈式系統中,每一個機器節點雖然都能夠明確地知道自己在進行事務操作過程中的結果是成功或失敗,但卻無法直接獲取到其他分佈式節點的操作結果。因此,當一個事務操作需要跨越多個分佈式節點的時候,爲了保持事務處理的 ACIO 特性,就需要引入一個稱爲“協調者”( Coordinator) 的組件來統一調度所有分佈式節點的執行邏輯,這些披調度的分佈式節點則被稱爲“參與者” ( Participant )。協調者負責調度參與者的行爲,並最終決定這些參與者是否要把事務真正進行提交。基於這個思想,衍生出了二階段提交和三階段提交兩種協議

2PC

2PC是Two-Phase Commit的縮寫,即二階段提交,通常二階段提交協議被認爲是一種一致性協議,用來保證分佈式系統數據的一致性,目前絕大多數關係型數據庫都採用的是二階段提交協議來完成分佈式事務處理的,該協議可以方便的完成分佈式事務參與者的協調統一決定事務的提交或回滾,有效的保證分佈式數據一致性,廣泛的應用於分佈式系統,主要分爲二階段來處理,流程如下

階段一:提交事務請求(投票階段)

事務詢問:協調者向所有的參與者發送事務內容,詢問是否可以執行事務提交操作,並等待參與者響應;

執行事務:各參與者執行事務操作,記錄Undo和Redo信息到事務日誌;

反饋事務詢問的響應:如果參與者成功執行事務操作,反饋YES響應,表示事務可以執行,否則返回NO表示事務不可以執行

 

階段二:執行事務的提交(根據參與者的響應決定是否執行事務提交)

情況一:執行事務提交,即所有參與者反饋YES響應,則執行事務提交

發送提交請求:協調者向所有參與者節點發送Commit請求

事務提交:收到Commit請求後,執行事務提交操作,提交完成後釋放事務資源

反饋事務提交結果:事務提交後,向協調者發送ACK消息

完成事務:協調者接收到所有參與者反饋的ACK消息後,完成事務

 

情況二:中斷事務,即存在任何一個參與者向協調者反饋了NO響應,或等待超時後還未收到所有參與者的反饋響應

發送回滾請求:協調者向所有參與者節點發出Rollback請求

事務回滾:參與者收到Rollback請求後,利用一階段記錄的Undo信息執行事務回滾操作,完成回滾後釋放資源

反饋事務回滾結果:回滾完成後,向協調者發送ACK消息

中斷事務:收到所有參與者返回的ACK消息後,完成事務中斷

 

二階段“事務提交”示意圖如下:

二階段“事務回滾”示意圖

2PC的優缺點

優點:原理簡單,實現方便

缺點:同步阻塞,單點問題,腦裂,過於保守

同步阻塞

二階段提交過程中,所有參與該事務操作的邏輯都處理阻塞狀態,各個參與者在等待其他參與者的響應過程中無法進行其他的任何操作,極大的限制分佈式系統的性能

單點問題

協調者在二階段提交過程中起到非常重要的左右,一旦協調者出現問題,二階段流程無法運轉,並且其他參與者將會一直處於鎖定事務資源的狀態無法繼續完成事務操作

數據不一致

在二階段提交的階段二,協調者向所有的參與者發送Commit請求後,發生局部網絡異常或者尚未發送完Commit請求自身發生崩潰,導致只有部分參與者收到Commit請求,從而導致部分事務提交部分事務無法提交,繼而引起數據不一致的現象

太過保守

對於參與者出現故障而無法響應,協調者只有利用超時來決定是否中斷事務,這種策略顯得比較保守,換句話說二階段提交沒有完善的容錯機制,任何一個節點的失敗都導致整個事務的失敗。

 

3PC協議

3PC是Three-Phase Commit的縮寫,即三階段提交,它是二階段提交的改進版,將二階段提交協議的“提交事務請求”過程一分爲二,形成了由CanCommit、PreCommit和DoCommit三個階段組成的事務處理協議

階段一:CanCommit

事務詢問:協調者向所有參與者發送一個包含事務內容的canCommit請求,詢問是否可以執行事務提交操作,並等待各參與者的響應

反饋詢問響應:參與者接收來自協調者的canCommit請求後,正常情況下,如果認爲可以順利執行事務則反饋YES響應並進入預備狀態,否則反饋NO狀態

 

階段二:PreCommit

協調者會根據參與者的反饋情況來決定是否可以進行事務的PreCommit操作,正常情況下,包含2種可能

執行事務預提交(協調者得到所以參與者的反饋都是YES)

發送預提交請求:協調者向所有參與者節點發送preCommit的請求,並進入Prepared階段

事務預提交:參與者收到preCommit請求後,會執行事務操作,並將Undo和Redo信息記錄到事務日誌中

反饋事務執行:參與者成功執行事務操作,反饋ACK響應給協調者,等待最終的提交或者中止指令

 

中斷事務(協調者得到任何一個參與者反饋的NO響應或者等待超時沒有收到所有參與者的反饋)

發送中斷請求:協調者向所有參與者節點發出abort請求

中斷事務:無論收到協調者的abort請求還是等待協調者請求過程中出現超時,參與者都會中斷事務

 

階段三:doCommit

執行提交

 

發送提交請求:協調者正常工作且收到所有參與者的ACK,從預提交狀態轉換到提交狀態,向所有參與者發送doCommit請求

事務提交:參與者收到doCommit請求後,執行事務提交操作,完成後釋放事務資源

反饋事務提交結果:參與者在完成事務提交後,向協調者發送ACK消息

完成事務:協調者接收到所有參與者反饋的ACK後,完成事務

 

中斷事務

協調者正常工作且收到任意一個參與者反饋的NO,或者等待超時後且無法接收到所有參與者反饋的響應,則會中斷事務

發送中斷請求:協調者向所有參與者節點發送abort請求

事務回滾:參與者接收到abort請求後,利用階段二中記錄的Undo信息執行回滾操作,回滾後釋放整個事務佔用的資源

反饋事務回滾結果:參與者完成回滾後,向協調者發送ACK響應

中斷事務:協調者接收到所有的ACK消息後,中斷事務

注意:進入階段三,如果出現以下兩種故障:

  • 協調者出現問題
  • 協調者和參與者網絡出現問題

都會導致參與者無法及時收到來自協調者的doCommit或者abort請求,參與者都會在等待超時後,繼續進行事務提交

3PC的優缺點

相較於二階段的提交協議,三階段的提交協議最大的優點就是降低了參與者的阻塞範圍,並且能夠在出現單點故障後繼續達成一致

缺點就是去除阻塞的同時引入了新的問題,那就是在參與者接收到preCommit消息後,如果網絡出現分區,協調者參與者無法通信,此時參與者依然會進行事務提交,從而導致數據不一致

 

Paxos算法

Paxos算法是有Leslie Lamport於1990年提出的一種基於消息傳遞且具有高度容錯特性的一致性算法,是目前公認的解決分佈式一致性問題最有效的算法之一

一個分佈式算法最重要的2個屬性:安全性(Safely)和活性(liveness),簡單來說,Safely是指那些需要保證永遠都不會發生的事情,liveness是指那些最終一定會發生的事情

要解決的問題及應用場景

解決的問題:

在常見的分佈式系統中,總會發生諸如機器宕機或者網絡異常等情況,Paxos算法需要解決的就是如何在一個可能發生上述異常的分佈式系統中,保證集羣內部對某個數據的值達成一致,並且保證不論發生以上任何異常,都不會破壞整個系統的一致性
其典型應用場景爲:

在一個分佈式系統中,如果各節點初始狀態一致,而且每個節點執行相同的命令序列,那麼最後就可以得到一個一致的狀態。爲了保證每個節點執行相同的命令序列,即需要在每一條指令上執行一致性算法(如Paxos算法),來保證每個節點指令一致。
 

Paxos中的角色和約定   

Paxos算法的目標是爲了保證最終有一個提案會被選定,且當提案選定後,進程最終也能獲取到被選定的提案,在該一致性算法中,有以下3參與個角色:
Proposer:提案發起者,爲了就某一個值達成一致,Proposer可以以任意速度、發起任意數量的提案,可以停止或重啓。
Acceptor:提案批准者,負責處理接收到的提案,響應、作出承諾、或批准提案。
Learner:提案學習者,可以從Acceptor處獲取已被批准的提案。

Proposal:爲了就某一個值達成一致而發起的提案,包括提案編號和提案的值。

Paxos需要遵循如下約定:
1、一個Acceptor必須批准它收到的第一個提案。
2、如果編號爲M0、value值爲V0的提案(即[ M0,V0])的提案被批准了,那麼所有比編號M0更高的,且被選定的提案,其value值必須也是V0

 

提案的選定

Proposer向一個Acceptor集合發送提案,當有足夠多的的Acceptor批准這個提案時,就認定提案被選定,此外還規定每個Acceptor最多隻能批准一個提案,這樣就可以保證只有一個提案被選定了。(這裏的足夠多的Acceptor是整個Acceptor的子集,這個子集包含Acceptor集合中的大多數,又因爲任意兩個包含大多數Acceptor的子集至少有一個公共成員,所以這裏的足夠多至少是超過一半數量的Acceptor)

Proposer生成提案

Proposer在產生一個編號爲Mn的提案時,必須要知道當前某一個將要或者已經被半數以上Acceptor批准的編號小於Mn但爲最大編號的提案,並且Proposer會要求所有的Acceptor都不再要批准任何編號小於Mn的提案,提案生成算法如下:

1、Proposer選擇一個新的提案編號Mn,然後向某個Acceptor集合成員發送請求,要求該集合中的Acceptor做出如下回應

  • 向Proposer承諾,保證不再批准任何編號小於Mn的提案
  • 如果Acceptor已經批准過了任何提案,就向Proposer反饋當前該Acceptor已經批准的編號小於Mn但爲最大編號的那個提案的Value值

2、如果Proposer收到來自半數以上的Acceptor的響應結果,那麼它就可以產生編號爲Mn、Value值爲Vn的提案了,這裏的Vn是所有響應中編號最大的提案的Value值,當然如果半數以上的Acceptor都沒有批准過任何的提案,即響應中不包含任何提案,此時的Vn的值可以由Proposer任意選擇

在確認提案之後,Proposer就會將該提案再次發送給某個Accpetor集合,獲取批准,稱此次請求爲Accpect請求,需要注意的是:接收Acceptor請求的Acceptor集合不一定是之前相應Prepare請求的Acceptor集合

Acceptor批准提案

一個Acceptor可能會收到自來Proposer的兩種請求:分別是Prepare請求和Accept請求,並對兩類請求作出相應的條件如下

  • Prepare請求:Acceptor可以在任何時候相應一個Prepare請求
  • Accept請求:在不違背Acceptor現有的承諾前提下,可以任意響應Accept請求,一個Acceptor只要尚未響應過任何編號大於Mn的Prepare請求,那麼它就可以接受這個編號爲Mn的提案(這個提案的值可能是Acceptor反饋的或者是Proposer任意選擇的)

假設一個Acceptor收到一個編號爲Mn的Prepare請求,但此時該Acceptor已經對編號大於Mn的Prepare請求做出了響應,因此他不會在批准編號爲Mn的提案了,Acceptor也沒有必要對這個Prepare請求做出響應,所以Acceptor選擇忽略這個Prepare請求,同時Acceptor也忽略掉哪些它已經批准過的提案的Prepare請求。這樣的話,每個Acceptor只需要記住它已經批准的提案的最大編號以及它已經做出Prepare請求響應的提案的最大編號即可。

算法描述

階段一

  1. Proposer選擇一個提案編號Mn,然後向Acceptor的某個超過半數的子集成員發送編號爲Mn的Prepare請求
  2. 如果一個Acceptor收到一個編號爲Mn的Prepare請求,且編號Mn大於該Acceptor已經響應的所有Prepare請求的編號,那麼Acceptor會將它已批准過的最大編號的提案作爲響應反饋給Proposer,同時該Accpetor會承諾不會在批准任何編號小於Mn的提案了

demo:假如一個Acceptor已經響應過提案編號爲1,2,3,4,5,7的Prepare請求,該Acceptor在接受到一個編號爲8的Prepare請求後,就會將編號爲7的提案最爲響應反饋給Proposer

階段二

  1. 如果Proposer收到來自半數以上的Acceptor對於其發出的編號爲Mn的的Prepare請求的響應,那麼該Proposer就會發送一個針對 [ Mn,Vn ]提案的Accept請求給Acceptor,注意Vn的值就是收到的所有響應中編號最大的提案的值,如果響應中不包含任何提案,那麼它就是任意值
  2. 如果Acceptor收到這個針對[ Mn,Vn ]提案的Accept請求,只要該Acceptor尚未對編號大於Mn的Prepare請求做出響應,它就會通過該提案

當然,在實際運行過程中,每一個Proposer都有可能產生多個提案,每個Proposer都可以在任意時刻丟棄一個提案,哪怕該提案的請求和響應馬上就會達到;此外Acceptor在收到更大編號的Prepare請求也會忽略編號更小的Prepare或Accept請求,並且通知其對應的Proposer,以便Proposer也能夠對該提案就行丟棄。

提案的獲取

上面已經知道如何選定一個提案,那麼Learner如何獲取提案呢?主要有以下幾種方案:

方案一:

Learner獲取已經被選定方案的前提是該提案被半數以上的Acceptor批准,因此最簡單的方案就是一旦一個Acceptor批准了一個提案,就把該提案發送給所有Learner,該方案可以快速獲取選定的方案,但是每個Acceptor和所有的Learner逐個通信,通信次數至少爲二者的乘積。

方案二:

所有的Acceptor將他們對提案的批准情況統一發送給特定的Learner(主Learner),在不考慮消息篡改的前提下,各個Learner之間可以通過消息通信感知提案選定情況,該提案雖然比方案一多了一個步驟,但是通信次數減少了,通信次數是Acceptor和Learner的總和,同時引入新問題就是:主Learner的單點問題

方案三:

基於方案二的單點問題,可以把主Learner替換成特定的Learner集合,集合中的每個Learner都可以在提案被選定後通知其他Learner,集合的Learner個數越多,可靠性越好,通信複雜度越高

保證算法活性

通過選取主Proposer來保證算法活性,假設存在一種極端情況,兩個Proposer依次提出一系列編號遞增的議案,但是最終都無法被選定,流程如下:

Proposer1提出一個 編號爲M1的提案,完成階段1流程,與此同時,Proposer2提出一個編號爲M2(M2>M1)的提案,同樣完成階段一的流程,因此當P1進入階段二的時候,發出的Accept請求將被Acceptor忽略,於是P1再次進入階段一併提出一個編號爲M3(M3>M2)的提案,而這導致P2的第二階段的Accpet請求被忽略,以次類推,提案的選定陷入死循環

爲了保證Paxos算法的可持續性,必須選擇一個主Proposer,並規定只有主Proposer才能提出議案,這樣只要主Proposer和過半的Proposer能夠正常通信,那麼凡是主Proposer提出一個編號更高的提案,該提案將會被批准,並且丟棄編號較小的提案,並最終選擇編號足夠大的提案,因此通過選擇一個主Proposer可以使Paxos算法流程保持活性

 

一致性協議的總結

二階段提交協議解決了分佈式一書務的原子性問題,保證了分佈式事務的多個參與者要麼都執行成功,要麼都執行失敗。但是,在二階段解決部分分佈式事務問題的同時,依然存在一些難以解決的諸如同步阻塞、無限期等待和“腦裂”等問題。三階段提交協議則是在二階段提交協議的基礎上,添加了 PreCommit 過程,從而避免了二階段提交協議中的無限期等待問題。而 Paxos 算法引入了“過半”的理念,通俗地講就是少數服從多數的原則。 同時, Paxos 算法支持分佈式節點角色之間的輪換,這極大地避免了分佈式單點的出現,因此 Paxos 算法既解決了無限期等待問題,也解決了“腦裂”問題,可以說是最優秀的分佈式一致性協議之一

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