Paxos算法是萊斯利-蘭伯特在1990年提出的一種基於消息傳遞的、具備容錯性的一致性算法,Google Chubb(分佈式鎖服務)的做者Mike Burrwos說過,世上只有一種一致性算法,那就是Paxos算法,其餘一致性算法都是Paxos的不完整版,Paxos算法是一種公認的晦澀難懂的算法,而且工程實現上也具備很大的難度,出名的實現好比Google Chubby/ZAB/微信的PhxPaxos等算法
Paxos算法要解決的問題就是在分佈式系統中如何就某一個協議達成一致安全
這個問題是由Paxos的做者提出的點對點通訊中的基本問題,該問題說的就是"在存在消息丟失的不可靠信道上試圖經過信息傳遞的方式達到一致性是不可能的"服務器
Paxos算法的前提就是不存在拜占庭將軍問題,即信道是安全、可靠的,集羣節點間傳遞的消息是不會被篡改的,在工程實踐中,大多數系統都是部署在一個局域網內,所以被篡改的狀況不多,另外一方面,因爲硬件和網絡緣由形成的消息不完整問題,如今已經再也不是問題,只須要一套簡單的校驗算法便可,所以,在實現工程中各個服務間消息傳遞過程能夠認爲不存在拜占庭將軍問題微信
通常狀況下,分佈式系統中各個節點間採用兩種通信模型:"共享內存","消息傳遞",而Paxos是基於消息傳遞通信模型的網絡
在Paxos算法中有三個角色,分別具備三種不一樣的行爲,更多時候,一個進程可能同時充當着多種角色分佈式
Proposer:提案(Proposal)的提議者;學習
Acceptor:提案的(accept)表決者,便是否認可、接受該提案,超過半數接受,該提案被認定爲"選定";spa
Learners:提案的學習者,當提案被選定後,其會同步並執行提案,說白一點,他就是那個沒有接受提案,但提案最後經過被迫接受的那個;server
一個提案的表決者會存在多個,但在一個集羣中,提議者是可能存在多個的,不一樣的提議者給提出不一樣的提案,而一致性算法則能夠保證如下幾點blog
沒有提案被提出則不會有提案被選定
每一個提案者在提出提案時都會爲該提案指定一個具備全局惟一性的、遞增的提案編號N,在整個集羣中時惟一的
每一個表決者在表決某提案後,會將該提案的編號N記錄在本地,這樣每一個表決者中保存的以及被表決的提案中會存在一個編號最大的提案,其編號架設爲maxN,每一個表決者僅會表決接受編號大於本身本地maxN的提案
在衆多提案中,最終只有一個提案被選定
一旦一個提案被選定,則其餘服務器會主動同步該提案到本地
Paxos算法的執行過程劃分爲兩個階段:"準備階段","接受階段"
1、準備(prepare)階段
提議者準備提交一個編號爲N的提案,其首先向全部的表決者發起 prepare(N)請求,用於試探集羣是否支持該編號的提議
每一個表決者Acceptor中都保存着本身曾經accept(表決,接受)過的提議中的最大編號maxN,當一個表決者接收到其餘主機發送來的prepare(N)請求時,其會比較N與maxN的值,若N的值小於等於maxN,則說明該提議已通過時,當前表決者採用不迴應或者回應Error的方式來拒絕該prepare請求,若N大於maxN.則說明該提議是能夠接受的,當前表決者會將其曾經接受的編號最大的提案Proposal(mid,manN,value)反饋給提議者,以向提議者展現本身支持的提案意願,其中第一個參數mid表示該決策者Acceptor的標識id,第二個參數表示期曾接受提案的最大編號maxN,第三個參數表示該提案的真正內容value,固然,若當前表決者還不曾表決、接受過任何提議,則會將Proposal(mid,null,null)反饋給提議者
2、表決(accept)階段
當提議者發出prepare(N)請求後,若收到超過半數的表決者的接受(Acceptor)的反饋,那麼該提議者就會將其真正的提案Proposal(N,value)發送給全部的表決者
當表決者(accpetor)接受接受到提議者發送的Proposal(N,value)提案後,會再次拿出本身曾經接受(accept)過的提議的最大編號maxN,以及曾經反饋過的prepare的最大編號,讓N與它們進行比較,若N大於這兩個編號,則當前表決者接受(accept)這個提案,並反饋給提議者,若N不大於這兩個編號,則表決者採起不迴應或者回應Error的方式來拒絕該提議
假設咱們有三臺主機,他們要從中間選取一個Leader,這三臺主機在不一樣的時間分別充當提案的提議者Proposer、表決者Acceptor、以及學習者Learnor三種不一樣的角色
這裏首先咱們介紹一下高舉列的前提:
每一個tiyizheProposer都想提議本身當Leader,假設三個Proposer-一、Proposer-二、Proposer-3提議的提案初始編號分別爲20、十、30,每一個提議者都要將提案發送給全部的表決者Acceptor,爲了便於理解,由於咱們只有三個主機,假設咱們就發送給兩個表決者便可(已經超過半數),
Proposer-1 發送給Acceptor-1和Acceptor-二、
Proposer-2 發送給Accrptor-2 和Acceptor-三、
Proposer-3 發送給Acceptor-2 和Acceptor-3
因而就有下面這一幕出現了 :
歷經下面兩個階段,選出Leader:(這裏咱們以金龜婿上門提親爲列)
假設 Acceptor-1:哥哥、Acceptor-2:爸爸、Acceptor-3:爺爺
圖中,金龜婿1第一個對女友家的三個具備決定權的人物的發起了請求:Proposer-1
因爲以前沒人來上門提親,也不清楚行情,哥哥和爸爸直接就響應了,收下了金龜婿的10W禮金,並作了禮物響應
(Acceptor-1和Acceptor-2分別返回(server1-id,null,null),(server2-id,null,null),並將提議編號20記錄)
多是女孩太漂亮,緊接着第二個追求者也上門提親了:Proposer-2
此次哥哥出門約妹去了,金龜婿分別拜訪了爸爸和爺爺,好傢伙,爺爺也是不知道行情怎麼樣,10W就把孫女給賣了,好在爸爸在以前已經有了這方面的經驗,內心想到,老子手裏捏着一個20W的禮金,會卵你這個10W的,選擇了不予理會,金龜婿2吃了爸爸的閉門羹,只收到了爺爺一我的的響應,悶悶不樂的離開了女方家
Proposer-2發來提案,Acceptor-2查詢發現本地提案號大於請求的提案號不作響應,可是因爲Acceptor3沒有接受過任何提案,因此直接接受了請求,並返回(server3-id,nill,null),而後將提案號記錄在了本地,Proposer2只收到了一個反饋,沒有超過半數
多是從衆,也多是那個女孩是真的乖巧,第三個金龜婿如約而至的上門提親:Proposer-3
哥哥因爲比較年輕,約的妹兒有點多,仍是沒在家,此次仍是爸爸和爺爺分別接待的,第三個金龜婿人雖然醜了點,可是口氣就不得了了啊,張口就承諾了30W禮金,爸爸聽的眼睛都瞪大了,漸漸的發現面前的這個面目全非的男人的面容也變的俊俏了起來,想把以前收下的20W禮金退了的想法開始在腦海中浮現,加之酒一喝菜一吃,牙齒一咬,便一口答應把以前的禮金都退了,和麪前這個俊俏的男人結爲親家,爺爺那邊,如法炮製般的手段便獲得了爺爺的響應,金龜婿3收到了兩個響應,興高采烈的踏出女方家門
Proposer3發來提案,因爲受理的兩個決策者發現本地的提案號均小於請求的提案號,故而接受了請求,並用請求的提案號覆蓋了本地的提案號,並分別返回了((server2-id,null,null),(server3-id,null,null))
Proposer2因爲沒有得到超過半數的反饋,因而對自身的提案號進行遞增,再次對ACceptor-2/-3發起請求,直到提案號大於Acceptor-2/-3的提案號,收到超過半數的反饋(兩個),兩個表決者接受了請求,並用請求的提案號覆蓋了本地的提案號,並分別返回了((server2-id,null,null),(server3-id,null,null))
因爲Acceptor-2/-3已經經過了Proposer-2的提案,並超過了半數,server2立馬成爲了Leader,選舉狀態結束,server2會發布廣播給全部的Learner,通知他們來同步數據,同步完成後集羣進入服務狀態