paxos出身算法
paxos出身名門,它爹是沒多久前得到圖靈獎的在分佈式領域大名鼎鼎的Leslie Lamport。網絡
paxos爲什麼而生併發
那麼Lamport他老人家爲何要搞這個東東呢,不是吃飽了撐的,而是爲了解決分佈式系統的大難題。分佈式系統一分佈式
般要求具備高可用性,高可用性通常又是經過冗餘也就是多副原本解決,多副本接着又帶來了一致性問題,因此分佈.net
式系統要解決的問題可簡單歸結爲多副本的一致性問題。怎麼解決一致性問題呢?搶答:用事務。何爲事務?搶答:視頻
多個操做序列的原子性。何爲原子性?搶答:還須要您本身去多看書吧。實現事務的方案有兩階段提交協議,和在這blog
個基礎上進行了加強的三階段提交協議。 這兩個方案都涉及到兩個角色,即協調者(coordinator)和參與者(cohort),協事務
調者要保證操做序列的原子性來實現事務,但它們都存在一些 問題,所以一些著名的系統如Google的Chubby和Yahooip
的Apache ZooKeeper都使用了paxos算法。get
兩階段提交協議的消息流程:
Coordinator Cohort QUERY TO COMMIT --------------------------------> VOTE YES/NO prepare*/abort* <------------------------------- commit*/abort* COMMIT/ROLLBACK --------------------------------> ACKNOWLEDGMENT commit*/abort* <-------------------------------- end
兩階段提交協議包含投票(Vote)和提交(Commit)兩個階段,它是一個阻塞的協議,若是參與者給協調者發送YES消息後協調者
永久性地掛了,那麼參與者將陷入無限等待中,而且會帶來數據不一致的問題。
三階段提交協議的消息流程:
三階段提交協議在二階段提交協議的基礎上增長了準備提交(Prepared to commit)階段,解決了協調者掛掉後參與者
無限阻塞和數據可能不一致的問題,但仍然沒法解決網絡分區的問題。
相對於上面兩個協議,因爲多數派的特性,paxos能夠在節點失效、網絡分區、網絡延遲等各類異常狀況下保證全部
節點都處於同一狀態,它的結構圖大體以下:
Basic paxos architecure. A picutre from:paxos-by-example
一個典型的paxos應用場景
分佈式系統中有多個節點,通常每一個節點都是參與者,而其中一個節點既是參與者又是協調者。可是這樣還會有單點
故障的問題,即若是協調者節點掛了,那麼將沒法進行任何事務,系統也就中止了正常運轉。如何在還存活的其它節
點中選擇一個來擔當協調者的角色,使系統能夠照常運行,達到山不轉水轉的目標呢?真的好難,可是有了paxos算
法,咱們能夠解決這個難題。若是還以爲這個問題抽象,那麼能夠換一種表述方式,即:如何在分佈式系統中肯定某
一個變量的值。在這個具體的場景中,這個變量的值指定了哪一個節點將被選出來擔當新協調者的角色。
paxos角色和規則
從上面的結構圖中,咱們看到paxos主要涉及三個角色,分別爲Acceptor、Proposer和Learner,在實踐中,每每每一個節
點都具有這三個角色,這裏爲了讓咱們大腦少些迷糊,暫且以每一個節點只具有一種角色來討論。
paxos算法主要分爲兩個階段:
1. Prepare:
Proposer 向全部Acceptor發送Prepare申請訪問權,並攜帶一個提案號(epoch),Acceptor賦予訪問權或拒絕,而且返回
該Acceptor 已經接受的值和對應的提案號。若是Proposer得到超過半數Acceptor的訪問權,那麼會進入第二階段;
2. Accept:
1) 若是全部的Acceptor返回值都爲空,則Proposer將攜帶本身預設的值v和本身的epoch號向獲取到訪問權的Acceptor發送請求;
2)若是Proposer第一階段得到某些Acceptor的返回值不爲空,則將epoch號最大的提案號對應的值f做爲本身的預設值,和本身的
提案號一塊兒向Acceptor發送請求(若是第一階段返回f的Acceptor已經超過了半數,則表示已經造成肯定性取值,此時直接返回成
功,不須要進行Accept請求了);
對於Acceptor來講,當它接收到Proposer請求時,須要應用一系列規則來決定如何響應,咱們對這些規則能夠進行以下歸納:
1)喜新厭舊
當Acceptor接收到Prepare請求時,它將當前本身發放了訪問權的epoch號和該Prepare請求攜帶的epoch進行比較,若是前者小
於後者,則將訪問權賦予新請求的這個Proposer,不然拒絕發放訪問權。這裏咱們認爲epoch值越大的越新。
2) 一視同仁
當Acceptor接收到Accept請求時,它 將當前本身發放了訪問權的epoch號和該Prepare請求攜帶的epoch進行比較,若是前者大於
後者,則拒絕該請求。若是這兩個epoch號相等, 而且Acceptor當前接受的取值爲空,則接受該Acceptor請求,同時將該Accept
請求的值設置爲接受值。若是以後又更大的epoch號申請 到訪問權,併發出Accept請求,該值也不會改變,即Acceptor在肯定了
值以後再也不改變,誰先設置就用誰的值。雖然在發放訪問權時是喜新厭舊,但 在取值這個問題上一視同仁,不會由於新epoch號
大而改變取值。這就像某些人,其餘女人能夠訪問他,但老婆只要定了就不會變。
paxos正確性
假 設有N個Acceptor,多數派個數至少爲N/2+1。若是有一個以上的Proposer獲取到超過半數Acceptor的訪問權,那麼至少有一個
Acceptor是相同的。具體來講,假設Proposer A在Prepare階段獲取到J個Acceptor的訪問權,Proposer B在Prepare階段獲取到K個Acceptor的訪問權,J>=N/2+1,K>=N/2+1,那麼必然有這樣一個Acceptor C,C既屬於J又屬於K,這種狀況就是在C給某個Proposer發放訪問權後,接着被另外一個Proposer搶佔到了訪問權時發生。 咱們假設Proposer A的取值爲V1,Proposer B的取值爲V2。在Accept階段,對於Acceptor C來講,它根據訪問權來決定接受誰的Accept請求,若是當前是B得到了訪問權,則接受B的取值V2,這樣A在Accept階段將失敗,失敗以後它可能 會繼續生成新的epoch值從新進入Prepare階段,可是這回它拿到了返回值V2,這樣它以後進入Accept階段時,會將V2做爲它的取值向 Acceptor發送申請,最終Proposer A和Proposer B都達成了一致,即V2爲最終取值。
以上是本人目前對paxos算法的一點理解,還將繼續深刻和不斷糾正.......
感受不錯的資料,推薦參考:
前百度牛人李海磊的課程:
http://www.tudou.com/programs/view/e8zM8dAL6hM/
這個視頻裏還講到了活鎖,我看了啓發不小:
https://www.youtube.com/watch?v=JEpsBg0AO
http://angus.nyc/2012/paxos-by-example/