本篇文章講的是分佈式一致性算法的理解,主要是理解和整合2PC,3PC和paxos算法的:html
首先咱們說說分佈式一致性的兩個概念,一個是分佈式設置不一樣的業務邏輯,來達到分佈式的一致性,好比分佈式系統收帳服務系統和付帳服務系統,收帳表和付帳表是不一樣的數據庫,人是要付出了錢,機器收了錢,保證錢數是對的,才能保證分佈式的一致性,這個應該叫分佈式業務邏輯一致性,還有一種就是都是同樣的數據庫,只是主庫和備份的關係,這個叫分佈式數據一致性,摻雜業務邏輯。算法
先說2PC和3PC數據庫
爲了解決分佈式一致性問題,產生了很多經典的分佈式一致性算法,本文將介紹其中的2PC和3PC。2PC即Two-Phase Commit,譯爲二階段提交協議。3PC即Three-Phase Commit,譯爲三階段提交協議。網絡
分佈式系統,即運行在多臺不一樣的網絡計算機上的軟硬件系統,而且僅經過消息傳遞來進行通訊和協調。
分佈式一致性問題,即相互獨立的節點之間如何就一項決議達成一致的問題。
分佈式
2PC,二階段提交協議,即將事務的提交過程分爲兩個階段來進行處理:準備階段和提交階段。事務的發起者稱協調者,事務的執行者稱參與者。
階段1:準備階段
一、協調者向全部參與者發送事務內容,詢問是否能夠提交事務,並等待全部參與者答覆。
二、各參與者執行事務操做,將Undo和Redo信息記入事務日誌中(但不提交事務)。
三、如參與者執行成功,給協調者反饋YES,便可以提交;如執行失敗,給協調者反饋NO,即不可提交。
階段2:提交階段
此階段分兩種狀況:全部參與者均反饋YES、或任何一個參與者反饋NO。
全部參與者均反饋YES時,即提交事務。
任何一個參與者反饋NO時,即中斷事務。
提交事務:(全部參與者均反饋YES)
一、協調者向全部參與者發出正式提交事務的請求(即Commit請求)。
二、參與者執行Commit請求,並釋放整個事務期間佔用的資源。
三、各參與者向協調者反饋Ack完成的消息。
四、協調者收到全部參與者反饋的Ack消息後,即完成事務提交。
附以下示意圖:
中斷事務:(任何一個參與者反饋NO)
一、協調者向全部參與者發出回滾請求(即Rollback請求)。
二、參與者使用階段1中的Undo信息執行回滾操做,並釋放整個事務期間佔用的資源。
三、各參與者向協調者反饋Ack完成的消息。
四、協調者收到全部參與者反饋的Ack消息後,即完成事務中斷。
附以下示意圖:
spa
一、同步阻塞:最大的問題即同步阻塞,即:全部參與事務的邏輯均處於阻塞狀態。
二、單點:協調者存在單點問題,若是協調者出現故障,參與者將一直處於鎖定狀態。
三、腦裂:在階段2中,若是隻有部分參與者接收並執行了Commit請求,會致使節點數據不一致。
因爲2PC存在如上同步阻塞、單點、腦裂問題,所以又出現了2PC的改進方案,即3PC。
.net
3PC,三階段提交協議,是2PC的改進版本,即將事務的提交過程分爲CanCommit、PreCommit、do Commit三個階段來進行處理。
階段1:CanCommit
一、協調者向全部參與者發出包含事務內容的CanCommit請求,詢問是否能夠提交事務,並等待全部參與者答覆。
二、參與者收到CanCommit請求後,若是認爲能夠執行事務操做,則反饋YES並進入預備狀態,不然反饋NO。
階段2:PreCommit
此階段分兩種狀況:
一、全部參與者均反饋YES,即執行事務預提交。
二、任何一個參與者反饋NO,或者等待超時後協調者尚沒法收到全部參與者的反饋,即中斷事務。
事務預提交:(全部參與者均反饋YES時)
一、協調者向全部參與者發出PreCommit請求,進入準備階段。
二、參與者收到PreCommit請求後,執行事務操做,將Undo和Redo信息記入事務日誌中(但不提交事務)。
三、各參與者向協調者反饋Ack響應或No響應,並等待最終指令。
中斷事務:(任何一個參與者反饋NO,或者等待超時後協調者尚沒法收到全部參與者的反饋時)
一、協調者向全部參與者發出abort請求。
二、不管收到協調者發出的abort請求,或者在等待協調者請求過程當中出現超時,參與者均會中斷事務。
階段3:do Commit
此階段也存在兩種狀況:
一、全部參與者均反饋Ack響應,即執行真正的事務提交。
二、任何一個參與者反饋NO,或者等待超時後協調者尚沒法收到全部參與者的反饋,即中斷事務。
提交事務:(全部參與者均反饋Ack響應時)
一、若是協調者處於工做狀態,則向全部參與者發出do Commit請求。
二、參與者收到do Commit請求後,會正式執行事務提交,並釋放整個事務期間佔用的資源。
三、各參與者向協調者反饋Ack完成的消息。
四、協調者收到全部參與者反饋的Ack消息後,即完成事務提交。
中斷事務:(任何一個參與者反饋NO,或者等待超時後協調者尚沒法收到全部參與者的反饋時)
一、若是協調者處於工做狀態,向全部參與者發出abort請求。
二、參與者使用階段1中的Undo信息執行回滾操做,並釋放整個事務期間佔用的資源。
三、各參與者向協調者反饋Ack完成的消息。
四、協調者收到全部參與者反饋的Ack消息後,即完成事務中斷。
注意:進入階段三後,不管協調者出現問題,或者協調者與參與者網絡出現問題,都會致使參與者沒法接收到協調者發出的do Commit請求或abort請求。此時,參與者都會在等待超時以後,繼續執行事務提交。
附示意圖以下:
3d
優勢:下降了阻塞範圍,在等待超時後協調者或參與者會中斷事務。避免了協調者單點問題,階段3中協調者出現問題時,參與者會繼續提交事務。
缺陷:腦裂問題依然存在,即在參與者收到PreCommit請求後等待最終指令,若是此時協調者沒法與參與者正常通訊,會致使參與者繼續提交事務,形成數據不一致。
日誌
2PC和3PC都還挺好理解,可是不管2PC或3PC,均沒法完全解決分佈式一致性問題。
htm
Google Chubby的做者Mike Burrows說過這個世界上只有一種一致性算法,那就是Paxos,其它的算法都是殘次品!
介紹一下paxos的背景
Paxos算法是分佈式技術大師Lamport提出的,主要目的是經過這個算法,讓參與分佈式處理的每一個參與者逐步達成一致意見。 用好理解的方式來講,就是在一個選舉過程當中, 讓不一樣的選民最終作出一致的決定。
Lamport爲了講述這個算法,假想了一個叫作Paxos的希臘成邦進行選舉的情景,這個算法也是所以而得名。在他的假想中,這個城邦要採用民主提議和投票的方式選出一個最終的決議,但因爲城邦的居民沒有人願意把所有時間和精力放在這種事情上,因此他們只能不定時的來參加提議,不定時來了解提議、投票進展,不定時的表達本身的投票意見。Paxos 算法的目標就是讓他們按照少數服從多數的方式,最終達成一致意見。
首先咱們要先思考Paxos到底解決了什麼問題?
先看看答案吧,簡單來講,paxos算法解決的就是一個最終一致性問題。假設一個集羣有三個節點,Paxos可讓三個節點更快的達成一致。由於在Paxos中規定,若是某個節點寫操做執行以前其餘兩個節點(也就是大多數的節點)的值已經相等並記爲V,那麼除非此次寫入的值也爲V,不然操做不能進行。而當其餘兩個節點的意見不統一時,採用高編號的節點的值。所以,最終必定會達到三個節點意見統一的狀態。
接下來就是文章正文,paxos的算法。接受者至關於決策者,提議者會給決策者發送信息!
Paxos算法的具體狀況:
一、在整個提議和投票過程當中,主要的角色就是"提議者」 (向」接受者」提出提議)和」接受者」(收到"提議者」的提議後,向」提議者」表達本身的意見)。
二、整個算法的大體過程爲:
第一階段:由於存在多個」提議者」,若是都提意見,那麼「接受者」接受誰的不接受誰的?太混亂了。因此,要先明確哪一個"提議者」是意見領袖有權提出提議,將來,」接受者」 們就主要處理這個」提議者」的提議了(這樣,也能夠在提出提議時就儘可能讓意見統一, 謀求儘早造成多數派)。
第二階段:由上階段選出的意見領袖提出提議,"接受者」 反饋意見。若是多數」接受者」接受了一個提議,那麼提議就經過了。
三、必需要了解的其餘相關背景:
1)怎麼明確意見領袖呢?經過編號。每一個"提議者」在第一階段先報個號,誰的號大,誰就是意見領袖。若是很差理解,能夠想象爲賄選(文字下面爲了方便表述,號越大的越有說話權,理解爲賄賂的錢多)。每一個提議者先拿着鈔票賄賂一圈」接受者」,誰給的錢多,第二階段」接受者」就聽誰的。(注: 這裏和下文提到的」意見領袖」,並環是一個新的角色,而是表明在那一輪賄賂成功的"提議者」。因此,請把意見領袖理解爲賄賂中勝出的"提議者」便可)
2)有個跟選舉常識不同的地方,就是每一個」提議者」不會執着於讓本身的提議經過,而是每一個」提議者」會執着於讓提議儘快達成一致意見。 因此,爲了這個目標,若是「提議者」在賄選的時候,發現」接受者」已經接受過前面意見領袖的提議了,即使」提議者」賄選成功,也會默默的把本身的提議改成前面意見領袖的提議。因此一旦賄賂成功,勝出的」提議者」再提出提議,提議內容也是前面意見領袖的提議(這樣,在謀求儘早造成多數派的路上,又前進了一步)。
3)錢的多少很重要,若是錢少了,不管在第一,仍是第二階段「接受者」都不會尿你,直接拒絕。
4)上面2)中講到,若是"提議者」在賄選時,發現前面已經有意見領袖的提議,那就將本身的提議默默改爲前面意見領袖的提議。這裏有一種狀況,若是你是「提議者」, 在賄賂的時候,」接受者1」跟你說」他見過的意見領袖的提議是案1」,而」接受者2」跟你說「他見過的意見領袖提議是方案2」,你該怎麼辦?這時的原則也很簡單,仍是:錢的多少很重要!你判斷一下是」接受者1」見過的意見領袖有錢,仍是」接受者2」見過的意見領袖有錢?如何判斷呢?由於」接受者」在被「提議者」賄賂的時候,本身會記下賄賂的金額。因此當你賄賂」接受者」時,- -一旦你給的賄賂多而勝出,」接受者」 會告訴你兩件事情: a.前任意見領袖的提議內容(若是有的話),b.前任意見領袖當時賄賂了多少錢。這樣,再面對剛纔的情景時,你只須要判斷一下"接受者1」和"接受者2」告訴你的信息中,哪一個意見領袖當時給的錢多,那你就默默的把本身的提議,改爲那個意見領袖的提議。
5)最後這一部分最有意思,但描述起來有點繞,若是不能一會兒就理解能夠先看後面的例子。在整個選舉過程當中,每一個人誰先來誰後到,」接受者」 什麼時間可以接到"提議者」的信息,徹底不可控的。因此極可能一個意見領袖已經產生了 ,可是因爲這個意見領袖的第一階段剛剛開始, 絕大部分"接受者」尚未收到這個意見領袖的提議。結果,這時忽然衝進來了一個新的土豪"提議者」,那麼這個土豪"提議者」也是有機會讓本身的提議勝出的!這時就造成了一種博弈: a. 上一個意見領袖要趕在土豪」提議者」賄賂到」接受者」前,趕到」接受者」面前上他接受本身的提議,不然會由於本身的以前賄賂的錢比土豪少而被拒絕。b.土豪"提議者」要趕在上一個意見領袖將提議傳達給「接受者」前,賄賂到」接受者」,不然土豪」提議者」即使賄賂成功,也要默默的將本身的提議改成前任意見領袖的提議。這整個博弈的過程,最終就看這兩個」提議者」誰的進展快了。但最終必定會有一個意見領袖,先獲得多數"接受者」的承認,那他的提議就勝出了。
四、總結
好啦,故事到這裏基本講述完了,我們來總結一下,其實Paxos算法就下面這麼幾個原則:
1) Paxos算法包括兩個階段:第一個階段主要是賄選,尚未提出提議;第二個階段主要根據第一階段的結果,明確接受誰的提議,並明確提議的內容是什麼(這個提議多是賄選勝出「提議者」本身的提議,也多是前任意見領袖的提議,具體是哪一個提議,見下面第3點原則)。
2)編號(賄賂金額)很重要,不管在哪一個階段,編號(賄賂金額)小的,都會被鄙視(被拒絕)。3)在第一階段中,一旦"接受者」已經接受了以前意見領袖的提議,那後面再來找這個」接受者」的」提議者」,即使在賄賂中勝出,也要被洗腦,默默將本身的提議改成前任意見領袖的提議,而後他會在第二階段提出該提議(也就是以前意見領袖的提議,以力爭讓你們的意見趨同)。若是"接受者」以前沒有接受過任何提議,那賄選勝出的"提議者」就能夠提出本身的提議了。
五、舉例
最後舉個例子,加深一下印象:
有兩個」提議者」和三個」接受者」 。
1)首先"提議者1」賄賂了3個"接受者」
2) 3個"接受者」記錄下賄賂金額,由於目前只有一個"提議者」出價,所以$1就是最高的了,因此"接受者」們返回賄賂成功。此外,由於沒有任何先前的意見領袖提出的提議,所以"接受者」們告訴"提議者1」沒有以前接受過的提議(天然也就沒有上一個意見領袖的賄賂金額了)。
3) 「提以者1"向「接受者1」提出了本身的提以: 1號提以,並告知本身以前已賄賂$1。
4)「接受者1」 檢查了一下,目前記錄的賄賂金額就是$1,因而接受了這一提議, 並把1號提議記錄在案。
5)在」提議者1」向"接受者2」 "接受者3」發起提議前,土豪「提議者2」出現,他開始用$2賄賂」接受者1」與」接受者2」。
6) 「接受者1」與"接受者2」馬上被收買,將賄賂金額改成$2。可是,不一樣的是: 」接受者1"告訴「提議者2」,以前我已經接受過1號提議了,同時1號提議的」提議者」賄賂過$1;而,"接受者2」告訴」提議者2」,以前沒有接受過其餘意見領袖的提議,也沒有上一個意見領袖的賄賂金額。
7)這時, 「提議者1」回過神來了,他向"接受者2」和」接受者3」發起1號提議,並帶着信息」我前期已經賄賂過$1」。
8) 」接受者2」 "接受者3」開始答覆: 」接受者2」檢查了一下本身記錄的賄賂金額,而後表示,已經有人出價到$2了,而你以前只出到$1,不接受你的提議,再見。但」接受者3」檢查了一下本身記錄的賄賂金額,目前記錄的賄賂金額就是$1,因而接受了這一提議,並把1號提議記錄在案。
9)到這裏, 」提議者1」已經獲得兩個接受者的贊同,已經獲得了多數"接受者」的贊同。因而」提議者1」肯定1號提議最終經過。
10) 下面,回到"提議者2」。剛纔說到, 」提議者2」賄賂了」接受者1」和"接受者2」,被「接受者1」告知: "以前已經接受過1號提議了,同時1號提議的'提議者’賄賂過$1」,並被」接受者2」告知: "之 前沒有接到過其餘意見領袖的提議,也沒有其餘意見領袖的賄賂金額」。這時"提議者2」,拿到信息後,判斷一下,目前賄賂過最高金額(即$1)的提議就是1號提議了,因此「提議者2」默默的把本身的提議改成與1號提議一致,而後開始向」接受者1」」接受者2」 發起提議(提議內容仍然是1號提議),並帶着信息:以前本身已賄賂過$2。
11) 這時」接受者1」 」接受者2」收到」提議者2」的提議後,照例先比對一下賄賂金額,比對發現」提議者2」以前已賄賂$2,而且本身記錄的賄賂金額也是$2,因此接受他的提議,也就是都接受1號提議。
這裏再多說一句:
回到上面的第5)步,若是」提議者2」第一次先去賄賂"接受者2」"接受者3」 會發生什麼?那極可能1號提議就不會成爲最終選出的提議。由於當」提議者2」先賄賂到了」接受者2」」接受者3」,那等「提議者1」 帶着議題再去找這兩位的時候,就會由於以前賄賂的錢少($1<$2)而被拒絕。因此,這也就是剛纔講到可能存在博弈的地方: a.」提議者1」要趕在「提議者2」賄賂到"接受者2」」接受者3」 以前,讓」接受者2」」接受者3」 接受本身的意見,不然」提議者1」會由於錢少而被拒絕; b.」提議者2」要趕在「提議者1」以前賄賂到」接受者」,不然」提議者2」即使賄賂成功,也要默默的將本身的提議改成「提議者1」 的提議。但你日後推演會發現,不管如何,總會有一個「提議者」的提議得到多數票而勝出。
以上,只是把大體的Paxos算法的思路介紹了一下,由於情景實在太複雜,好比: 「提議
者」、 「接受者」若是是4個、5..... 好比: "提議者」與」接受者」之間的交互誰先誰後,等等各種狀況。可是,其實都是可以嚴謹的推導出最後可以選出一個多數派的,不過篇幅就會太長了。你們有興趣能夠按照上面的思路,本身再模擬模擬"提議者」「接受者」 數量或多或少,交互或先或後的各類狀況,結果確定是最終惟一一個 提議會得到多數票而勝出。
回想當時本身看Paxos算法時,過不少的彎路,花了很長時間,這篇文章也是結合本身看Paxos算法時的一些心得所寫,但願對初學者能有些啓發。
參考網址:
https://www.zhihu.com/question/19787937
https://blog.csdn.net/zifanyou/article/details/84789022
https://www.cnblogs.com/esingchan/p/3917718.html
https://www.cnblogs.com/hugb/p/8955505.html