1. 程式人生 > >分散式資料一致性演算法paxos的幾個問題,收斂(含參考文獻)

分散式資料一致性演算法paxos的幾個問題,收斂(含參考文獻)

paxos 用來幹嘛的,解決分散式環境下的決議問題.

然後是multi-paxos

可以基於此基礎上優化

paxos分散式演算法的幾個問題.

演算法就是流程+實體(屬性). 並且能最終得到結果. (面向不是人的產品)

關鍵字,選舉投票.

1. 為什麼要有兩階段提交?

2. 怎麼證明當諮詢者(proposor)知道半數的人認可某觀點後(accepted),就可以認為該觀點就是最終觀點,自己不用再重新下一輪提出議案了,不會被後面的人改變?

3. 怎麼證明paxos是會收斂的.

答案:

1. 為什麼要有兩階段提交?

     提交提案的人和決定者分開時.

     可能有新的提案者會冒出來. 那麼他需要先問下決定者是不是已經有觀點了. 當超過半數都是同一個觀點時他就不需要再提新的議案了. 這就是prepare階段.

     這個是 paxos 演算法最創新的部分, 原有加鎖表面上是一步, 本質上是兩步. 1. 加鎖 2.選舉..

    分散式下.

            1.  先 預加鎖

            2.  返回加鎖結果,如果超過半數的法官都認可加鎖才能繼續提交3, 否則重新走1 ,如果法官告知的結果有一個結果超過半數. 走到4

            3.  提交自己的議案

            4.  結束,接受結果

   在multi paxos的過程中, zk 和raft 根本上都利用了這個兩階段概念,實現了最終演算法. 所有的paxos instance共用同一個prepare 階段.[1 ]

2. 怎麼證明當諮詢者(proposor)知道半數的人認可某觀點(accpted)後,就可以認為該觀點就是最終觀點,不會被後面的人改變?

     反證法. 如果還能被修改,說明被別人半數預加鎖(prepare階段)成功了. 如果被別人半數預加鎖(prepare階段)成功 ,那麼就不可能被被半數accpted

    材料:  promiseIndex用來try鎖,每次promise時變更;accpetedIndex用來收斂value,在每次接受時更改.

                           promise階段半數原則結合acccpted階段超半數原則用來證明此結論.

                      半數的作用是對叢集的一種變相鎖. 由於是叢集的非原子的,用兩次鎖的模式來實現類似與鎖單機的原理. 這是proxy精妙的地方.

    promise

    commit (獲取最新的accptedIndex的value)

    接受accpted訊息.

      當一個人接受到超過半數的accpted訊息時,說明promise時的try鎖至少成功維持了半數. 說明

      2.1. 這個accpetedIndex肯定是當前最新最大的. (因為已經鎖住了半數的鎖,能證明別人在這個promise和accpeted過程中沒有commit過);

      2.2. 所以當其他人想再次promise的時候,拿到超過半數的提交許可,這裡面肯定有上次最新的accpetedIndex和value(就是上面這個value),最終收斂到這個value上.

   反例說明: 1 A ,2A ,3B .某個人得到A,B. 認為沒有超過半數票. 就重新發起了投票B,將A,B改成了B,B。

        上面例子裡有個問題。因為一旦B的acceptN肯定小於A的acceptN。

       因為超過半數的已經接受了A,說明之前已經鎖定了。後面不可能把3的acceptN更改為比1,2的更新

3. paxos演算法的收斂怎麼證明理解?

   因為最終commit都需要從已接受的value中選擇一個promiseIndex最大的. 所以肯定是不會越來越多.通過幾次偶然性就會收斂到某一個值.

我原本想的改進(其實是錯誤的): 可以在短期內不再接受新的promise,不再更改promisedIndex. (錯誤原因:這個會導致所有人都無法獲得半數以上的index.)

附錄:

http://blog.csdn.net/liu251/article/details/51944905

http://www.udpwork.com/item/13394.html

比較通俗易懂的視訊:知行學社 paxos


(from http://codemacro.com/2014/10/15/explain-poxos/ )

每個節點擁有的三個關鍵值,各個階段的讀寫. 演算法就是流程+實體(屬性). 並且能最終得到輸出.

   -----

附錄:

維基的簡介:Paxos演算法是萊斯利·蘭伯特(Leslie Lamport,就是 LaTeX 中的"La",此人現在在微軟研究院)於1990年提出的一種基於訊息傳遞且具有高度容錯特性的一致性演算法。

Paxos演算法目前在Google的Chubby、MegaStore、Spanner等系統中得到了應用,Hadoop中的ZooKeeper也使用了Paxos演算法,在上面的各個系統中,使用的演算法與Lamport提出的原始Paxos並不完全一樣,這個以後再慢慢分析。本博文的目的是,如何讓一個小白在半個小時之內理解Paxos演算法的思想。小白可能對數學不感興趣,對分散式的複雜理論不熟悉,只是一個入門級程式設計師。之所以想寫這篇博文,是因為自己看了網上很多介紹Paxos演算法的文章,以及部落格,包括Lamport的論文,感覺還是難以理解,大多過於複雜,本人一直認為,複雜高深的理論背後一定基於一些通用的規律,而這些通用的規律在生活中其實我們早就遇到過,甚至用過。所以,我們先忽略Paxos演算法本身,從生活中的小事開始談起。

 假如有一群驢友要決定中秋節去旅遊,這群驢友分佈在全國各地,假定一共25個人,分別在不同的省,要決定到底去拉薩、昆明、三亞等等哪個地點(會合時間中秋節已經定了,此時需要決定旅遊地)。最直接的方式當然就是建一個QQ群,大家都在裡面投票,按照少數服從多數的原則。這種方式類似於“共享記憶體”實現的一致性,實現起來簡單,但Paxos演算法不是這種場景,因為Paxos演算法認為這種方式有一個很大的問題,就是QQ伺服器掛掉怎麼辦?Paxos的原則是容錯性一定要很強。所以,Paxos的場景類似於這25個人相互之間只能發簡訊,需要解決的核心問題是,哪怕任意的一部分人(Paxos的目的其實是少於半數的人)“失聯”了,其它人也能夠在會合地點上達成一致。好了,怎麼設計呢?

這25個人找了另外的5個人(當然這5個人可以從25個人中選,這裡為了描述方便,就單拿出另外5個人),比如北京、上海、廣州、深圳、成都的5個人,25個人都給他們發簡訊,告訴自己傾向的旅遊地。這5個人相互之間可以並不通訊,只接受25個人發過來的簡訊。這25個人我們稱為驢友,那5個人稱為隊長。

先來看驢友的邏輯。驢友可以給任意5個隊長都發簡訊,發簡訊的過程分為兩個步驟:

第一步(申請階段):詢問5個隊長,試圖與隊長溝通旅遊地。因為每個隊長一直會收到不同驢友的簡訊,不能跟多個驢友一起溝通,在任何時刻只能跟一個驢友溝通,按照什麼原則才能做到公平公正公開呢?這些簡訊都帶有傳送時間,隊長採用的原則是同意與簡訊傳送時間最新的驢友溝通,如果出現了更新的簡訊,則與簡訊更新的驢友溝通。總之,作為一個有話語權的人,只有時刻保持傾聽最新的呼聲,才能做出最明智的選擇。在驢友發出簡訊後,等著隊長回覆。某些隊長可能會回覆說,你這條簡訊太老了,我不與你溝通;有些隊長則可能返回說,你的簡訊是我收到的最新的,我同意跟你溝通。對於後面這些隊長,還得返回自己決定的旅遊地。關於隊長是怎麼決定旅遊地的,後面再說。

對於驢友來說,第一步必須至少有半數以上隊長都同意溝通了,才能進入下一步。否則,你連溝通的資格都沒有,一直在那兒狂發吧。你發的簡訊更新,你獲得溝通權的可能性才更大。。。。。。

因為至少有半數以上隊長(也就是3個隊長以上)同意,你才能與隊長們進行實質性的溝通,也就是進入第二步;而隊長在任何時候只能跟1個驢友溝通,所以,在任何時候,不可能出現兩個驢友都達到了這個狀態。。。當然,你可以通過狂發簡訊把溝通權搶了。。。。

對於獲得溝通權的那個驢友(稱為A),那些隊長會給他傳送他們自己決定的旅遊地(也可能都還沒有決定)。可以看出,各個隊長是自己決定旅遊地的,隊長之間無需溝通。

第二步(溝通階段):這個幸運的驢友收到了隊長們給他發的旅遊地,可能有幾種情況:

第一種情況:跟A溝通的隊長們(不一定是全部5個隊長,但是半數以上)全部都還沒有決定到底去那兒旅遊,此時驢友A心花怒放,給這些隊長髮第二條簡訊,告訴他們自己希望的旅遊地(比如馬爾地夫);

可能會收到兩種結果:一是半數以上隊長都同意了,於是表明A建議的馬爾地夫被半數以上隊長都同意了,整個決定過程完畢了,其它驢友遲早會知道這個訊息的,A先去收拾東西準備去馬爾地夫;除此之外,表明失敗。可能隊長出故障了,比如某個隊長在跟女朋友打電話等等,也可能被其它驢友搶佔溝通權了(因為隊長喜新厭舊嘛,只有要更新的驢友給自己發簡訊,自己就與新人溝通,A的建議隊長不同意)等等。不管怎麼說,苦逼的A還得重新從第一步開始,重新給隊長們發簡訊申請。

第二種情況:至少有一個隊長已經決定旅遊地了,A可能會收到來自不同隊長決定的多個旅遊地,這些旅遊地是不同隊長跟不同驢友在不同時間上做出的決定,那麼,A會先看一下,是不是有的旅遊地已經被半數以上隊長同意了(比如3個隊長都同意去三亞,1個同意去昆明,另外一個沒搭理A),如果出現了這種情況,那就別扯了,說明整個決定過程已經達成一致了,收拾收拾準備去三亞吧,結束了;如果都沒有達到半數以上(比如1個同意去昆明,1個同意去三亞,2個同意去拉薩,1個沒搭理我),A作為一個高素質驢友,也不按照自己的意願亂來了(Paxos的關鍵所在,後者認同前者,否則整個決定過程永無止境),雖然自己原來可能想去馬爾地夫等等。就給隊長們發第二條簡訊的時候,告訴他們自己希望的旅遊地,就是自己收到的那堆旅遊地中最新決定的那個。(比如,去昆明那個是北京那個隊長前1分鐘決定的,去三亞的決定是上海那個隊長1個小時之前做出來的,於是頂昆明)。驢友A的想法是,既然有隊長已經做決定了,那我就乾脆頂最新那個決定。

從上面的邏輯可以看出,一旦某個時刻有半數以上隊長同意了某個地點比如昆明,緊跟著後面的驢友B繼續發簡訊時,如果獲得溝通權,因為半數以上隊長都同意與B溝通了,說明B收到了來自半數以上隊長髮過來的訊息,B必然會收到至少一個隊長給他發的昆明這個結果(否則說明半數以上隊長都沒有同意昆明這個結果,這顯然與前面的假設矛盾),B於是會頂這個最新地點,不會更改,因為後面的驢友都會頂昆明,因此同意昆明的隊長越來越多,最終必然達成一致。

看完了驢友的邏輯,那麼隊長的邏輯是什麼呢?

隊長的邏輯比較簡單。

在申請階段,隊長只會選擇與最新發申請簡訊的驢友溝通,隊長知道自己接收到最新簡訊的時間,對於更老的簡訊,隊長不會搭理;隊長同意溝通了的話,會把自己決定的旅遊地(或者還沒決定這一資訊)發給驢友。

在溝通階段,驢友C會把自己希望的旅遊地發過來(同時會附加上自己申請簡訊的時間,比如3分鐘前),所以隊長要檢查一下,如果這個時間(3分鐘前)確實是當前自己最新接收到申請簡訊的時間(說明這段時間沒有驢友要跟自己溝通),那麼,隊長就同意驢友C的這個旅遊地了(比如昆明,哪怕自己1個小時前已經做過去三亞的決定,誰讓C更新呢,於是更新為昆明);如果不是最新的,說明這3分鐘內又有其它驢友D跟自己申請了,因為自己是個喜新厭舊的傢伙,同意與D溝通了,所以驢友C的決定自己不會同意,等著D一會兒要發過來的決定吧。

Paxos的基本思想大致就是上面的過程。可以看出,其實驢友的策略才是Paxos的關鍵。讓我們來跟理論對應一下。

[1 ] Multi Paxos http://www.cnblogs.com/fei33423/p/7990190.html