Paxos算法

Paxos是什么

Paxos算法是基于消息傳遞且具有高度容錯特性的一致性算法,是目前公認的解決分布式一致性問題最有效的算法之一。

問題產生的背景

在常見的分布式系統(tǒng)中,總會發(fā)生諸如機器宕機或網絡異常(包括消息的延遲、丟失、重復、亂序,還有網絡分區(qū))等情況。Paxos算法需要解決的問題就是如何在一個可能發(fā)生上述異常的分布式系統(tǒng)中,快速且正確地在集群內部對某個數據的值達成一致,并且保證不論發(fā)生以上任何異常,都不會破壞整個系統(tǒng)的一致性。

相關概念

在Paxos算法中,有三種角色:

  • Proposer
  • Acceptor
  • Learners
    在具體的實現中,一個進程可能同時充當多種角色。比如一個進程可能既是Proposer又是Acceptor又是Learner。

提案(Proposal)

最終要達成一致的value就在提案里。

注: - 暫且認為『提案=value』,即提案只包含value。在我們接下來的推導過程中會發(fā)現如果提案只包含value,會有問題,于是我們再對提案重新設計。

Proposer可以提出(propose)提案;Acceptor可以接受(accept)提案;如果某個提案被選定(chosen),那么該提案里的value就被選定了。
回到剛剛說的『對某個數據的值達成一致』,指的是Proposer、Acceptor、Learner都認為同一個value被選定(chosen)。那么,Proposer、Acceptor、Learner分別在什么情況下才能認為某個value被選定呢?
Proposer:只要Proposer發(fā)的提案被Acceptor接受(剛開始先認為只需要一個Acceptor接受即可,在推導過程中會發(fā)現需要半數以上的Acceptor同意才行),Proposer就認為該提案里的value被選定了。Acceptor:只要Acceptor接受了某個提案,Acceptor就任務該提案里的value被選定了。Learner:Acceptor告訴Learner哪個value被選定,Learner就認為那個value被選定。

  • Proposer:只要Proposer發(fā)的提案被Acceptor接受(剛開始先認為只需要一個Acceptor接受即可,在推導過程中會發(fā)現需要半數以上的Acceptor同意才行),Proposer就認為該提案里的value被選定了。
  • Acceptor:只要Acceptor接受了某個提案,Acceptor就任務該提案里的value被選定了。
  • Learner:Acceptor告訴Learner哪個value被選定,Learner就認為那個value被選定。

問題描述

假設有一組可以提出(propose)value(value在提案Proposal里)的進程集合。

  • 一個一致性算法需要保證提出的這么多value中,只有一個value被選定(chosen)。
  • 如果沒有value被提出,就不應該有value被選定。
  • 如果一個value被選定,那么所有進程都應該能學習(learn)到這個被選定的value。

對于一致性算法,安全性(safaty)要求如下:

  • 只有被提出的value才能被選定。
  • 只有一個value被選定,并且
  • 如果某個進程認為某個value被選定了,那么這個value必須是真的被選定的那個。

Paxos的目標:提出多個value,保證最終有一個value會被選定,當value被選定后,進程最終也能獲取到被選定的value。

假設不同角色之間可以通過發(fā)送消息來進行通信,那么:

  • 每個角色以任意的速度執(zhí)行,可能因出錯而停止,也可能會重啟。一個value被選定后,所有的角色可能失敗然后重啟,除非那些失敗后重啟的角色能記錄某些信息,否則等他們重啟后無法確定被選定的值。
  • 消息在傳遞過程中可能出現任意時長的延遲,可能會重復,也可能丟失。但是消息不會被損壞,即消息內容不會被篡改(拜占庭將軍問題)

推導過程

最簡單的方案——只有一個Acceptor

假設只有一個Acceptor(可以有多個Proposer),只要Acceptor接受它收到的第一個提案,則該提案被選定,該提案里的value就是被選定的value。這樣就保證只有一個value會被選定。
但是,如果這個唯一的Acceptor宕機了,那么整個系統(tǒng)就無法工作了!
因此,必須要有多個Acceptor!

多個Acceptor

多個Acceptor的情況如下圖。那么,如何保證在多個Proposer和多個Acceptor的情況下選定一個value呢?

下面開始尋找解決方案。

如果我們希望即使只有一個Proposer提出了一個value,該value也最終被選定。

那么,就得到下面的約束:

P1:一個Acceptor必須接受它收到的第一個提案。

但是,這又會引出另一個問題:如果每個Proposer分別提出不同的value,發(fā)給不同的Acceptor。
根據P1,Acceptor分別接受自己收到的value,就導致不同的value被選定。出現了不一致。如下圖:

剛剛是因為『一個提案只要被一個Acceptor接受,則該提案的value就被選定了』才導致了出現上面不一致的問題。因此,我們需要加一個規(guī)定:

規(guī)定:一個提案被選定需要被半數以上的Acceptor接受

這個規(guī)定又暗示了:『一個Acceptor必須能夠接受不止一個提案!』不然可能導致最終沒有value被選定。比如上圖的情況。v1、v2、v3都沒有被選定,因為它們都只被一個Acceptor的接受。

最開始講的『提案=value』已經不能滿足需求了,于是重新設計提案,給每個提案加上一個提案編號,表示提案被提出的順序。令『提案=提案編號+value』。

雖然允許多個提案被選定,但必須保證所有被選定的提案都具有相同的value值。否則又會出現不一致。

于是有了下面的約束:

P2:如果某個value為v的提案被選定了,那么每個編號更高的被選定提案的value必須也是v。

一個提案只有被Acceptor接受才可能被選定,因此我們可以把P2約束改寫成對Acceptor接受的提案的約束P2a。

P2a:如果某個value為v的提案被選定了,那么每個編號更高的被Acceptor接受的提案的value必須也是v。

只要滿足了P2a,就能滿足P2。

但是,考慮如下的情況:假設總共有5個Acceptor。Proposer2提出[M1,V1]的提案,Acceptor25(半數以上)均接受了該提案,于是對于Acceptor25和Proposer2來講,它們都認為V1被選定。Acceptor1剛剛從宕機狀態(tài)恢復過來(之前Acceptor1沒有收到過任何提案),此時Proposer1向Acceptor1發(fā)送了[M2,V2]的提案(V2≠V1且M2>M1),對于Acceptor1來講,這是它收到的第一個提案。根據P1(一個Acceptor必須接受它收到的第一個提案。),Acceptor1必須接受該提案!同時Acceptor1認為V2被選定。這就出現了兩個問題:

  • Acceptor1認為V2被選定,Acceptor2~5和Proposer2認為V1被選定。出現了不一致。
  • V1被選定了,但是編號更高的被Acceptor1接受的提案[M2,V2]的value為V2,且V2≠V1。這就跟P2a(如果某個value為v的提案被選定了,那么每個編號更高的被Acceptor接受的提案的value必須也是v)矛盾。

所以我們要對P2a約束進行強化!

P2a是對Acceptor接受的提案約束,但其實提案是Proposer提出來的,所以我們可以對Proposer提出的提案進行約束。得到P2b:

P2b:如果某個value為v的提案被選定了,那么之后任何Proposer提出的編號更高的提案的value必須也是v。

由P2b可以推出P2a進而推出P2。

那么,如何確保在某個value為v的提案被選定后,Proposer提出的編號更高的提案的value都是v呢?

只要滿足P2c即可(Proposer的提出,用Acceptor集合做了約束):

對于任意的N和V,如果提案[N, V]被提出,那么存在一個半數以上的Acceptor組成的集合S,滿足以下兩個條件中的任意一個:

  • S中每個Acceptor都沒有接受過編號小于N的提案。
  • S中Acceptor接受過的最大編號的提案的value為V。

Proposer生成提案

為了滿足P2b,這里有個比較重要的思想:

  • Proposer生成提案之前,應該先去『學習』已經被選定或者可能被選定的value,然后以該value作為自己提出的提案的value。
  • 如果沒有value被選定,Proposer才可以自己決定value的值。這樣才能達成一致。
    這個學習的階段是通過一個『Prepare請求』實現的。

提案生成算法:

Proposer選擇一個新的提案編號N,然后向某個Acceptor集合(半數以上)發(fā)送請求,要求該集合中的每個Acceptor做出如下響應(response)。
(a) 向Proposer承諾保證不再接受任何編號小于N的提案。
(b) 如果Acceptor已經接受過提案,那么就向Proposer響應已經接受過的編號小于N的最大編號的提案。

我們將該請求稱為編號為N的Prepare請求。

  • 如果Proposer收到了半數以上的Acceptor的響應,那么它就可以生成編號為N,Value為V的提案[N,V]。這里的V是所有的響應中編號最大的提案的Value。如果所有的響應中都沒有提案,那 么此時V就可以由Proposer自己選擇。
  • 生成提案后,Proposer將該提案發(fā)送給半數以上的Acceptor集合,并期望這些Acceptor能接受該提案。我們稱該請求為Accept請求。(注意:此時接受Accept請求的Acceptor集合不一定是之前響應Prepare請求的Acceptor集合)

Acceptor接受提案

Acceptor可以忽略任何請求(包括Prepare請求和Accept請求)而不用擔心破壞算法的安全性。因此,我們這里要討論的是什么時候Acceptor可以響應一個請求。

我們對Acceptor接受提案給出如下約束:

P1a:一個Acceptor只要尚未響應過任何編號大于N的Prepare請求,那么他就可以接受這個編號為N的提案。

*如果Acceptor收到一個編號為N的Prepare請求,在此之前它已經響應過編號大于N的Prepare請求。根據P1a,該Acceptor不可能接受編號為N的提案。因此,該Acceptor可以忽略編號為N的Prepare請求。當然,也可以回復一個error,讓Proposer盡早知道自己的提案不會被接受。

因此,一個Acceptor只需記住:1. 已接受的編號最大的提案 2. 已響應的請求的最大編號。

Paxos算法描述

經過上面的推導,我們總結下Paxos算法的流程。

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

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

中文版:

Learner學習被選定的value

Learner學習被選定的value
Learner學習(獲?。┍贿x定的value有如下三種方案:

如何保證Paxos算法的活性


通過選取主Proposer,就可以保證Paxos算法的活性。至此,我們得到一個既能保證安全性,又能保證活性的分布式一致性算法——Paxos算法。

Q&A

Paxos協議數據同步方式相對于基于傳統(tǒng)1主N備的同步方式有啥區(qū)別?

一般情況下,傳統(tǒng)數據庫的高可用都是基于主備來實現,1主1備2個副本,主庫crash后,通過HA工具來進行切換,提升備庫為主庫。在強一致場景下,復制可以開啟強同步,Oracle和Mysql都是類似的復制模式。但是如果備庫網絡抖動,或者crash,都會導致日志同步失敗,服務不可用。為此,可以引入1主N備的多副本形式,我們對比都是3副本的情況,一個是基于傳統(tǒng)的1主2備,另一種基于paxos的1主2備。傳統(tǒng)的1主兩備,進行日志同步時,只要有一個副本接收到日志并就持久化成功,就可以返回,在一定程度上解決了網絡抖動和備庫crash問題。但如果主庫出問題后,還是要借助于HA工具來進行切換,那么HA切換工具的可用性如何來保證又成為一個問題?;赑axos的多副本同步其實是在1主N備的基礎上引入了一致性協議,這樣整個系統(tǒng)的可用性完全有3個副本控制,不需要額外的HA工具。而實際上,很多系統(tǒng)為了保證多節(jié)點HA工具獲取主備信息的一致性,采用了zookeeper等第三方接口來實現分布式鎖,其實本質也是基于Paxos來實現的。

以MySQL的主備復制一套體系為例來具體說明傳統(tǒng)的主備保持強一致性的一些問題。整個系統(tǒng)中主要包含以下幾種角色:Master,Slave,Zookeeper-Service(zk),HA-Console(HA),Zookeeper-Agent(Agent)
Master,Slave:分別表示主節(jié)點和備節(jié)點,主節(jié)點提供讀寫服務,備節(jié)點可以提供讀服務,或者完全用于容災。
Zookeeper-Service(zk):分布式一致性服務,負責管理Master/Slave節(jié)點的存活信息和切換信息。zk基于zab協議,zab協議是一種一致性協議,與paxos,raft協議類似,它主要有兩種模式,包括恢復模式(選主)和廣播模式(同步)。一般zk包含N個節(jié)點(zk-node),只要有超過半數的zk-node存活且相互連通,則zk可以對外提供一致性服務。
HA-Console:切換工具,負責具體的切換流程
Zookeeper-Agent(Agent):Master/Slave實例上的監(jiān)聽進程,與監(jiān)聽的實例保持心跳,維護
Master/Slave的狀態(tài),每個實例有一個對應的Agent。大概工作流程如下:

  • (1).Master/Slave正常啟動并搭建好了復制關系,對應的Agent會調用zk接口去注冊alive節(jié)點信息,假設分別為A和B。
  • (2).如果此時Master Crash,則實例對應的Agent發(fā)現心跳失敗,如果重試幾次后仍然失敗,則將調用zk接口注銷掉A節(jié)點信息。
  • (3).HA工具通過zk接口比較兩次的節(jié)點信息,發(fā)現少了A節(jié)點,表示A可能不存在了,需要切換,嘗試連接A,如果仍然不通,注冊A的dead節(jié)點,并開始切換流程。
  • (4).HA工具讀取配置信息,找到對應的Slave節(jié)點B,(更改讀寫比配置信息,設置B提供寫),打開寫。
  • (5).應用程序通過拉取最新的配置信息,得知新主B,新的寫入會寫入B。
    前面幾部基本介紹了MySQL借助zk實現高可用的流程,由于zk-node可以多地部署,HA無狀態(tài),因此可以很容易實現同城或者是異地的高可用系統(tǒng),并且動態(tài)可擴展,一個HA節(jié)點可以同時管理多個Master/Slave的切換。那么能保證一致性嗎?前面提到的Agent除了做監(jiān)聽,還有一個作用是盡可能保持主備一致,并且不丟數據。
  • (6).假設此時A節(jié)點重啟,Agent檢測到,通過zk接口發(fā)現A節(jié)點在dead目錄下,表示被切換過,需要kill上面的所有連接,并回滾crash時A比B多的binlog,為了盡可能的少丟數據,然后再開啟binlog后,將這部分數據重做。這里要注意rollback和replay都在old-Master上面進行,rollback時需要關閉binlog,而replay需要開啟binlog,保證這部分數據能流向new-Master。
  • (7).從第6步來看,可以一定程度上保證主備一致性,但是進行rollback和replay時,實際上是往new-Slave上寫數據,這一定程度上造成了雙寫,如果此時new—Master也在寫同一條記錄,可能會導致寫覆蓋等問題。
  • (8).如果開啟半同步呢?old-Master crash時,仍然可能比old-Slave多一個group的binlog,所以仍然需要借助于rollback和replay,依然避免不了雙寫,所以也不能做到嚴格意義上的強一致。

分布式事務與Paxos協議的關系?

Paxos協議與分布式事務并不是同一層面的東西。
分布式事務的作用是保證跨節(jié)點事務的原子性,涉及事務的節(jié)點要么都提交(執(zhí)行成功),要么都不提交(回滾)。
分布式事務的一致性通常通過2PC來保證(Two-Phase Commit, 2PC),這里面涉及到一個協調者和若干個參與者。
第一階段,協調者詢問參與者事務是否可以執(zhí)行,參與者回復同意(本地執(zhí)行成功),回復取消(本地執(zhí)行失敗)。
第二階段,協調者根據第一階段的投票結果進行決策,當且僅當所有的參與者同意提交事務時才能提交,否則回滾。
2PC的最大問題是,協調者是單點(需要有一個備用節(jié)點),另外協議是阻塞協議,任何一個參與者故障,都需要等待(可以通過加入超時機制)。

Paxos協議用于解決多個副本之間的一致性問題。比如日志同步,保證各個節(jié)點的日志一致性,或者選主(主故障情況下),保證投票達成一致,選主的唯一性。
簡而言之,2PC用于保證多個數據分片上事務的原子性,Paxos協議用于保證同一個數據分片在多個副本的一致性,所以兩者可以是互補的關系,絕不是替代關系。對于2PC協調者單點問題,可以利用Paxos協議解決,當協調者出問題時,選一個新的協調者繼續(xù)提供服務。工程實踐中,Google Spanner,Google Chubby就是利用Paxos來實現多副本日志同步。

如何將Paxos應用于傳統(tǒng)的數據庫復制協議中?

復制協議相當于是對Paxos的定制應用,通過對一系列日志進行投票確認達成多數派,就相當于日志已經在多數派持久化成功。副本通過應用已經持久化的日志,實現與Master節(jié)點同步。由于數據庫ACID特性,本質是由一個一致的狀態(tài)到另外一個一致的狀態(tài),每次事務操作都是對應數據庫狀態(tài)的變更,并生成一條日志。由于client操作有先后順序,因此需要保證日志的先后的順序,在任何副本中,不僅僅要保證所有日志都持久化了,而且要保證順序。對于每條日志,通過一個logID標示,logID嚴格遞增(標示順序),由leader對每個日志進行投票達成多數派,如果中途發(fā)生了leader切換,對于新leader中l(wèi)ogID的“空洞”,需要重新投票,確認日志的有效性。

Multi-Paxos的非leader節(jié)點可以提供服務嗎?

Multi-Paxos協議中只有l(wèi)eader確保包含了所有已經已經持久化的日志,當然本地已經持久化的日志不一定達成了多數派,因此對于沒有confirm的日志,需要再進行一次投票,然后將最新的結果返回給client。而非leader節(jié)點不一定有所有最新的數據,需要通過leader確認,所以一般工程實現中,所有的讀寫服務都由leader提供。

Ref:
http://www.cnblogs.com/RedHandLM/p/6780698.html?utm_source=itdadao&utm_medium=referral
來自《從Paxos到Zookeeper分布式一致性原理與實踐》
http://www.cnblogs.com/cchust/p/5617989.html

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,967評論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現死者居然都...
    沈念sama閱讀 98,273評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 175,870評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,742評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,527評論 6 407
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,010評論 1 322
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,108評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,250評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發(fā)現了一具尸體,經...
    沈念sama閱讀 48,769評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,656評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,853評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,371評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,103評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,472評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,717評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,487評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,815評論 2 372

推薦閱讀更多精彩內容

  • Paxos算法在分布式領域具有非常重要的地位。但是Paxos算法有兩個比較明顯的缺點:1.難以理解 2.工程實現更...
    Jeffbond閱讀 17,378評論 25 87
  • 持續(xù)更新 如何淺顯易懂地解說 Paxos 的算法? 參考資料 #8:知行學社的分布式系統(tǒng)與Paxos算法視頻課程,...
    xiewen閱讀 16,765評論 0 44
  • 引言 有人說分布式系統(tǒng)里面就是可用性,可擴展性,可靠性,一致性,性能等各種特性之間的trade off,沒有一個功...
    ssdutzs閱讀 1,729評論 2 3
  • 能把彎路走直的是聰明的人,因為他找到了捷徑; 能把直路走彎的是豁達的人,因為他可以多欣賞幾道風景。 讓自己和他人同...
    醫(yī)成道人閱讀 416評論 0 0
  • 豬實在是很值得敬畏,來點風價格就飛漲啊,哪次通漲少了豬的身影?而且最近豬跟VR都扯上關系了,國外有人制作了一個VR...
    黑丸閱讀 375評論 0 1