1. 程式人生 > >講一個關於paxos的故事...

講一個關於paxos的故事...

先講一個故事。

從前,在國王Leslie Lamport的統治下,有個黑暗的希臘城邦叫paxos。城邦裡有3類人,

  • 決策者
  • 提議者
  • 群眾

雖然這是一個黑暗的城邦但是很民主,按照議會民主制的政治模式制訂法律,群眾有什麼建議和意見都可以寫提案交給提議者,提議者會把提案交給決策者來決策,決策者有奇數個,為什麼要奇數個?很簡單因為決策的方式很無腦,少數服從多數。最後決策者把剛出爐的決策昭告天下,群眾得知決策結果。

等一下,那哪裡黑暗呢?問題就出在“提議者會把提案交給決策者來決策”,那麼多提案決策者先決策誰的?誰給的錢多就決策誰的。

那這樣會有幾個問題,決策者那麼多,怎麼保證最後決策的是同一個提案,以及怎麼保證拿到所有提議者中最高的報價。

聰明又貪婪的決策者想到了一個辦法:分兩階段報價

第一階段

  1. 決策者接受所有比他當前持有報價高的報價,且不會通知之前報價的人
  2. 提議者給所有決策者報價,若有人比自己報價高就加價,有半數以上決策者接受自己報價就停止報價。

第一階段結束的狀態

每個提議者都覺得有半數以上的大佬接受了自己的提案,很開心。而決策者集團此刻的狀態是一致的,半數以上同意的提案只有一個,這個就是報價最高的(因為高的總是可以覆蓋低的),具體是誰提的who care,一致就行。

第二階段

提議者去找收過自己錢的大佬籤合同,這裡有3種情況:

  1. 大佬都收了別人更高的價,回去拿錢繼續賄賂,回到第一階段重新升級;
  2. 大佬收到的最高報價是自己的,美滋滋,半數以上成功籤合同,提案成功;
  3. 提議者回去拿錢回來繼續賄賂的時候發現合同已經被簽了且半數以上都簽了這個提案,不幹了,趕快把自己的提案換成已經簽了的提案,再去提給所有大佬,看看能不能分一杯羹遇見還沒簽的大佬。

第二階段結束的狀態

所有提議者手頭的提案都是一樣的,因為有“趕快把自己的提案換成已經簽了的提案”這一步;決策者集團所有成員最終接受的提案是一樣的。

好的目的已經達到了,把這個提案昭告天下,讓所有群眾知道這件事。

故事說完了,用正確的姿勢再簡單介紹下paxos

分散式系統中的節點通訊存在兩種模型:共享記憶體(Shared memory)和訊息傳遞(Messages passing)。

paxos作為基於訊息傳遞通訊模型的分散式系統,不可避免的會發生以下錯誤:程序可能會慢、被殺死或者重啟,訊息可能會延遲、丟失、重複,在基礎 Paxos 場景中,先不考慮可能出現訊息篡改即拜占庭錯誤的情況。

Paxos演算法解決的問題是在一個可能發生上述異常的分散式系統中如何就某個值達成一致,保證不論發生以上任何異常,都不會破壞決議的一致性。一個典型的場景是,在一個分散式資料庫系統中,如果各節點的初始狀態一致,每個節點都執行相同的操作序列,那麼他們最後能得到一個一致的狀態。

為保證每個節點執行相同的命令序列,需要在每一條指令上執行一個“一致性演算法”以保證每個節點看到的指令一致。一個通用的一致性演算法可以應用在許多場景中,是分散式計算中的重要問題。

Paxos用於解決分散式系統中一致性問題,在一個Paxos過程只批准一個value,只有被prepare的value且被多數Acceptor接受才能被批准,被批准的value才能被learner。在paxos演算法中,分為4種角色:

  • Acceptor:決策者
  • Proposer :提議者
  • Client:產生議題者(群眾)
  • Learner:最終決策學習者(群眾)

階段一

  1. Proposer向半數以上的Acceptor傳送Prepare請求並附上編號N。
  2. 若Acceptor收到一個編號為N的Prepare請求,且N大於該Acceptor已經響應過的所有Prepare請求的編號,那麼它就會將它已經接受過的編號最大的提案(如果有的話)作為響應反饋給Proposer,同時該Acceptor承諾不再接受任何編號小於N的提案。
  3. Proposer若沒有得到半數以上Acceptor的響應,則編號+1繼續發起請求。

階段二

  1. 如果Proposer收到半數以上Acceptor對其發出的編號為N的Prepare請求的響應,那麼它就會發送一個[N,提案]Accept請求給半數以上的Acceptor。
  2. 如果Acceptor收到一個針對編號為N的提案的Accept請求,只要該Acceptor沒有對編號大於N的Prepare請求做出過響應,它就接受該提案

看故事的時候不知道大家有沒有疑問,我是有的。

決策者Acceptor為什麼要多個?

若只有一個acceptor多個proposer,acceptor可以選任意一個提案,很美好,但是有單點問題。

為什麼要用“半數以上通過”這個辦法來決策?

一個集合不可能同時存在兩個半數以上的子集,過半的思想保證提交的value在同一時刻在分散式系統中是唯一的一致的。這種提交方式不管proposer接受到的訊息是接受了誰的提議過半,只保證是有提議過半了的。然後再在第二階段確定這個過半了的提議,讓所有節點知道這件事。因此演算法如果能保證value被半數acceptor接受,則意味這此時被認定的value是唯一的。

為什麼acceptor要接受多個提案?

如果acceptor只能夠接受一個提案,則可能發生所有proposer提出的提案都無法達到多數,決策者接收一個就結束了,狀態無法一致。

當Proposer有很多個的時候,會有什麼問題?

很難有一個proposer收到半數以上的回覆,進而不斷地執行第一階段的協議,決策收斂速度慢,很久都不能做出一個決策。

提案為什麼要帶上編號(即故事中用來賄賂的錢)?

帶上編號是為了決策者可以在自身接受到的提案的對比中做出最終的唯一決策。

試想如果按照提案到達時間對比提案,且不說這樣就變成了只接收一個第一到達的提案,還可能因為網路原因每個決策者接受到的提案的先後順序不一樣,涼涼。

接著上面的問題,那如果把所有決策者收到的提案彙集起來選出個時間最早的呢?

把提案彙集,這時候肯定需要一個master來做判斷,大家有沒發現這個master好像就變成了propser,它拿到最早的提案,交給決策者...
其實,這就演變成了paxos的變種協議。

後記

為了避免競爭,加快收斂的速度,有人在演算法中加入leader來代替propser,且leader在叢集中只有一位,也就是說只有leader有權提議。這時leader會有單點問題,於是又加入了leader選舉機制保證健壯性,到目前為止paxos演變的越來越像我下一篇要講的zab協議了。

為了能講得更通俗,很多地方講得不夠嚴謹,見諒,有問題可以提出交流。

其實這篇和zookeeper的關係不太大算是講zab之前做的一個鋪墊吧。