一:學習分佈式-paxos算法

這段時間因爲工做須要用到zookeeper,因而就看了一下大名鼎鼎的Paxos算法。算法

Paxos算法是分佈式經典算法之一,在Leslie Lamport的論文《Paxos made simple》一文中,做者逐步增強最初一致性問題的約束條件,最終得出了一個能夠實現的模型。文章中不少東西借鑑大神的博客,在最下面有連接。該文章只是本身加深印象,作個總結。安全

一:基本語義異步

在Paxos算法中有一下幾種角色:分佈式

Proposer:議案的提議者學習

Acceptor:議案的決議者優化

Client:發出議案者spa

Learner:最終議案的學習者.net

以上四種角色,議案的提議者和決策者最重要,Proposer通俗一點就是Client的使者,Client提出一個議案,而後交於Proposer,Proposer再拿着這個議案去向Acceptor申請。還有一個名詞就是最終決議,稍後再介紹。blog

還有一下幾種關鍵字:資源

Proposal:議案,由proposer提出,最終被acceptor批准或者否決

Value:決議,他是議案的內容,一個議案就是一個{編號,決議}對

Accept:批准,表示議案被Acceptor批准

Choose:選擇,表示議案被選擇,也就是被多數Acceptor批准

算法一致性的基本語義:

1):決議(value)只有在被Proposer提出以後才能被批准成爲議案(議案是Proposal)

2):再一次Poaxs算法執行示例中,有且僅有一個value被choosen

3):Learner只能學習最終被批准的value

以上三個語義能夠轉化爲四個約束條件:

P1:一個Acceptor必須接受(accpet)第一次收到的議案

        可是該需求可能會致使一個問題,若是多個Proposer分別提出幾個不一樣的提議,從而致使每一個Acceptor 分 別批註了幾個不一樣的提議,可是沒有一個提議被多數派接受。即便只有兩個決議,可是有可能有這種情 況,就是在單個Acceptor失效的狀況下,每一個議案都被半數的Acceptor接受,那麼仍是沒有辦法提出最終的議案。

        一個決議要通過多數派的批准猜中最終被choose,這個需求和P1暗示了咱們Acceptor必須可以批准多個議案,所以咱們爲每一個不一樣的議案分配不一樣的編號(若是隻有三個Proposer,咱們能夠給他們編號0,1,2,那麼他們的議案編號就能夠是3*i+j,其中i能夠用來跟蹤提出議案的次數,j是他們開始的編號,這樣就能夠作到惟一遞增,同理,多個也是),所以每個議案由編號和決議構成,也就是【議案={編號,決議}】,若是一個議案被多數派Accept,那麼他就被choose,咱們容許選擇多個議案,可是必須保證全部選擇的議案都包括相同的決議,概括以下:

P2. 若是一個議案{n, v}被選擇,那麼全部被選擇的議案(編號更高)包含的決議都是v。 

由於編號是全序的,P2保證了「有且僅有一個決議被選擇」這一關鍵屬性,議案必須被至少一個Acceptor批准才能被選擇,所以只要知足一下條件,就能知足P2:

P2A:一旦一個編號n,value v({n,v})的議案被choose, 那麼以後任何Acceptor再次接受的議案(編號更高)必須具備value v

依然根據P1來確認選擇了某些議案。由於通訊是異步的,因此可能在有些狀況下,某些Acceptor可能沒有接受過一些議案,他們可能會錯誤的批准一個議案,試想一下,加入某個Proposer之內某些緣由down了,可是後續本身又啓動了,他提出了一個編號更高的議案,那麼根據P21,Acceptor應該去批准這個議案,可是又違背了P2A,因此咱們要去增強P2A:

P2B:一旦一個編號n,value v({n,v})的議案被choose,那麼以後任何Proposer提出的議案(編號更高)必須具備value v

由於一個議案只有在被Proposer提出以後纔有可能被批准,所以P2B包含了P2A,進而包含了P2

可是如何才能證實P2B,假設某個議案{m,v}被選擇,而後咱們能夠去證實任何n>m的議案的決議都是v,對n能夠簡化證實:根據條件,每一個提出的議案(編號m到n-1)他的決議都是v,咱們能夠證實編號爲n的決議是v,對於選擇的議案m,必然存在一個集合c(Acceptor的多數派)中的多數Acceptor已經批准了該議案,綜合假設概括,m被選擇這一前提意味着:

C中的每一個Acceptor都批准了一個一個編號m到n-1範圍內的議案,而且議案的決議都是v

由於任何多數派組成的集合都包括至少C中的一員,那麼咱們能夠得出結論,若是下面的不變性成立,那麼議案n的決議就是v

P2C:對於任意的v和m,若是議案{n,v}被提出,那麼存在一個有多數派構成的結合s(或者a,s中沒有沒有acceptor批准太小於編號n的議案,或者b)在s中的acceptor批准的因此議案(編號小於n)中,v編號小於n的提案的最大決議

經過保持P2C,咱們就能知足P2B,爲了保持P2C,準備提出提案(編號爲n)的Proposer必須知道全部編號小於n的議案中編號最大的那個,若是存在的話,他可能已經或者將要被Acceptor多數派批准,獲取已經批准的議案是簡單的,可是預測將要批准的議案確實困難的,Proposer並不預測,它假設不會有這種狀況,所以他會硬性規定Acceptor不準批准任何編號小於n的議案,這就引發了下面的基本算法也就是咱們說的兩階段提交。

1):Proposer選擇了一個新的編號n,準備向Acceptor集合中全部成員發送請求(Prepare階段,n是Prepare請求的編號,也是下面accept迴應議案的編號),而且要求迴應:

    a、一個永不批准編號小於n的議案的承諾

    b、在他已經批准的編號小於n的議案中,編號最大的議案,若是存在的話,咱們把這樣的請求叫作prepare請求n

2):若是Proposer收到多數Acceptor的迴應,那麼他就能夠提出議案{n,v}其中v是全部迴應中編號最高的議案的決議,或者是Proposer選擇的任意值,前提是Acceptor從未批准過任何議案

一個Proposer發出一個Acceptor集合發送已經被批准的議案,咱們稱之爲Accept請求

換言之:就是

P1A:Acceptor能夠批准一個編號爲n的議案,當且僅當他沒有迴應過一個編號大於n的Prepare請求

P1A包含了P1,如今咱們獲得了一個一致性算法,假設知足安全性,假設議案的編號惟一,咱們就能夠經過簡單的優化,獲得下面一致性算法:

假設一個Acceptor接收到一個編號爲n的Prepare請求,可是他已經迴應了一個編號大於n的Prepare請求,因而Acceptor就沒有必要回應這個Prepare請求了,由於他不會這個批准這個編號爲n的議案,他還能夠忽略已經批准過的議案的Prepare請求。

有了這些優化,Acceptor只須要保存它已經批准過的最高編號的議案(議案的編號和決議),以及他已經迴應過得全部Prepare請求的最高編號,由於任何狀況下,都須要保證P2C,Acceptor都須要保存這些信息,包括重啓以後,注意,Proposer能夠隨意拋棄一個提案,可是他不會用相同的編號來提出另外一個議案。

二:基本算法

其中通訊模型咱們採用異步的非拜占庭模型【拜占庭模型下,消息會丟失,重複,也有可能會損壞,換言之:咱們認爲消息可能會丟失,也可能會重複,可是消息不會出現損壞的現象】

下面簡單介紹下Paxos算法的一些行爲,基本分爲兩段提交過程:

1)Prepare階段:

        (1):當Proposer但願提出一個議案V1,首先發送Prepare請求到大多數的Acceptor,Prepare請求的序列號爲<SN1>;

         (2):當Acceptor接收到編號爲<SN1>的Prepare請求的時候,他首先回去檢查自身上次回覆過得Prepare請求<SN2>

                a):若是SN2>SN1,忽略該請求,而且告知提出<SN1>議案的Proposer,他已經回覆過一個編號大於SN1的Prepare請求,

                b):不然去檢查上次批准的Prepare請求<SNx,Vx>,而且回覆<SNx,Vx>;若是該Acceptor以前沒有回覆過,那麼直接回復<OK>

2)Accept階段 :

         (1):   由於通信是異步的,因此咱們能夠在通過一段時間後,Proposer收到Acceptor的請求,回覆能夠分爲幾種:

            a):回覆的數量知足多數派,並且回覆的都是<OK>,那麼Proposer發起Accept請求,內容就是<SN1,V1>

            b):回覆的數量知足多數派,可是有的回覆<SN2,V2>,<SN3,V3>.....則,Proposer找到全部回覆中超過半數的那個,假如是<SNx,Vx>,則發出Accept請求,內容爲<SN1,Vx>,此時他的編號不變,可是議案的決議變成Acceptor回覆中超過半數議案的決議Vx

            c):回覆的數量不知足多數派,那麼Proposer會嘗試編號+1再次發出Prepare請求,

         (2):在不違背本身向其餘Proposer的承諾前提下,acceptor收到accpet請求後既接受並回復這個請求。

三:算法優化

可是在應用場景下,很容易出現活鎖的狀況,例如當三個或三個以上的Proposer在發送Prepare請求,很難有一個Proposer收到超過半數的回覆而不停的執行第一階段協議,這就陷入了一個怪圈,所以爲了不競爭,加快收斂速度,在算法中引入了一個Leader的角色,在正常狀況下有且僅有一個參與者扮演leader角色,除非leader down掉或者是他丟掉了半數之上的Acceptor,纔會從新選舉leader。並且他角色扮演Acceptor,同時又扮演Learner角色。

在這種優化算法中,只有Leader才能提出議案,從而避免了競爭使得算法快速收斂而趨於一致,此時的Paxos算法在本質上退變爲兩階段提交協議。可是在異常狀況下,可能出現了多個leader,此時算法有變成了原始的Paxos算法。

Leader的選舉也是用到了兩階段提交協議。

此時Leader的工做流程主要分爲如下三部分:

一、學習階段 向其餘參與者學習本身不知道的數據(決議)

當一個參與者通過選舉後成爲了leader,他應該知道絕大多數的Paxos的實例,所以他會立刻啓動一個主動學習的過程。假設當前的新Leader早就知道1-134,138和139的Paxos實例,那麼他就會執行137-137以及大於139的paxos。若是隻檢測到135和140的Poxas實例有肯定的值,那他最後就會知道1-135,138-140的paxos的實例。

二、同步階段 讓絕大多數的參與者保持數據(決議)的一致性

此時的Leader已經知道1-134和138-140的poxas實例,那麼他會從新執行1-135的實例,以保證絕大多數參與者在1-135的paxos實例上保持一致。對於138-140的實例,他不會立刻去執行,而是等到服務階段填充了136,137的paxos實例後在執行。這裏之因此要填充這些實例,是爲了防止之後Leader老是去學習這些間隔的實例,可是這些實例有沒有肯定的值,就會形成必定程度的資源浪費。

三、服務階段 爲客戶端服務,提議案

 Leader將用戶的請求轉化爲Paxos實例,固然,他能夠去執行多個Paxos實例,可是若是當前leader出現異常,就有可能出現Paxos實例間斷的問題,或者在異常狀況下,出現了多個leader,此時Paxos算法就有可能出現活鎖的現象。

連接:http://blog.csdn.net/sparkliang/article/details/5740882

連接:http://blog.csdn.net/xhh198781/article/details/10949697

連接:http://shuofenglxy.iteye.com/blog/1188422

相關文章
相關標籤/搜索