(本文包括章節(jié):1、由來(lái),2、算法簡(jiǎn)單回顧,3、演習(xí)道具,4、演習(xí),5、算法提出者Leslie的八卦。hoho)
1、由來(lái):
劉備接受了諸葛亮的提議,決定將paxos算法的思想應(yīng)用到蜀帝國(guó)的決策機(jī)制上。然而,玄德生性謹(jǐn)慎,決定先行試點(diǎn),實(shí)踐下可行性。孔明提議,由蜀國(guó)五大肌肉男:關(guān)羽、張飛、趙云、馬超、黃忠,做為決策者,而廖化、周倉(cāng)、魏延分別無(wú)序的提出關(guān)于同一件事的水火不容的三個(gè)提案,孔明堅(jiān)信:即使腦殘者使用了paxos算法,也不會(huì)出現(xiàn)沖突的政令不一情況。paxos算法理論以及劉備是怎么被孔明忽悠的部分,同學(xué)們可以參考上篇《paxos分布式一致性算法--講述諸葛亮的反穿越》:http://blog.csdn.net/russell_tao/article/details/7244530
閑話少敘,書接上文。
為了少打點(diǎn)字,劉備與諸葛亮倆玻璃不再以對(duì)話形式出現(xiàn)了。他們?cè)O(shè)置了五個(gè)官署(五虎將辦公地,相當(dāng)于Server),三個(gè)提案點(diǎn)(周倉(cāng)等三人,發(fā)起提案時(shí)的辦公地。相當(dāng)于Client),當(dāng)然都不在一起,信使們從提案點(diǎn)到官署傳遞信息的話,正常情況下需要半個(gè)小時(shí),也就是30分鐘。這次演習(xí),哥倆不關(guān)注學(xué)習(xí)情況,所以paxos第三段就不在演習(xí)內(nèi)容里了。諸葛亮為廖化、周他、魏延對(duì)于事件e準(zhǔn)備了三個(gè)自相矛盾的提案,我們分別用p1、p2和p3代替吧。先行說(shuō)明提案:
事件e(也就是本次paxos實(shí)例):蜀國(guó)今后的發(fā)展路線
提案p1:學(xué)習(xí)紅色錘子鐮刀,走激進(jìn)主義,一切發(fā)展按照計(jì)劃進(jìn)行,小民們憑票消費(fèi),銀子多了也沒(méi)用,集中力量辦大事,崇尚國(guó)家壟斷主義。
提案p2:學(xué)習(xí)自由聯(lián)盟,走自由主義,寧失去效率也不失去公正,發(fā)展民營(yíng)經(jīng)濟(jì)為先,民主、法制、新聞自由,通過(guò)這種公正來(lái)激發(fā)社會(huì)的整體創(chuàng)造力。
提案p3:堅(jiān)持孔孟之道,走保守主義,兼顧黃老之學(xué),堅(jiān)信中學(xué)為體、西學(xué)為用,國(guó)體不可大改,走有大漢國(guó)情的老路讓別人說(shuō)去吧。
2、算法簡(jiǎn)單回顧
我們?cè)俸?jiǎn)單回顧下提案者和作為決策者的五虎將行動(dòng)準(zhǔn)則,共有六步,書記官(暫讓五虎將兼職)負(fù)責(zé)記錄下通過(guò)的提案p(通過(guò)了就叫法令了),這樣,我們用1a,1b,2a,2b,3a,3c來(lái)表述全部的六步。(這六步就是三段式提交了,這在上篇《paxos分布式一致性算法--講述諸葛亮的反穿越》里講過(guò),不再?gòu)?fù)述。)
魏延、廖化、周倉(cāng):
1a,作為提案者,首先向劉備要到個(gè)編號(hào),搞清楚自己對(duì)事件e的態(tài)度。記錄下當(dāng)前時(shí)間,接下來(lái)向五虎將的多數(shù)派(3個(gè)或以上)發(fā)送事件+編號(hào)。
2a,此時(shí)開(kāi)始處理五虎將的回應(yīng),這就有多種情況了。收到明確拒絕就得放棄!檢查沙漏,如果到達(dá)時(shí)間限制了,還沒(méi)有足夠的多數(shù)派回應(yīng),那么就試著給五虎將的其他人再發(fā)送提案看看。如果收到了足夠的五虎將里多數(shù)派的回應(yīng),那么,確定在2a這步里,如果要提案,到底提哪個(gè)提議?是自己現(xiàn)在要提的提案?
3a,提案者如果收到足夠的五虎將多數(shù)派回應(yīng)通過(guò),則記錄提案為通過(guò)的政策法令,同時(shí)通知所有書記官,也就是兼職的五虎將,把法令記錄到羊皮紙上來(lái)。
五虎將:
1b,作為決策者,也需要沙漏,主要用于2b步驟后批準(zhǔn)政策法令后,給自己設(shè)定個(gè)超時(shí)時(shí)間,若第三步信使沒(méi)有過(guò)來(lái),則超時(shí)后自動(dòng)把提案變成政策法令記錄到羊皮紙上。1b這個(gè)步驟是收到了信使的消息,來(lái)自于1a步驟里的提案者。收到事件e和編號(hào)N。五虎將這時(shí)將有可能出現(xiàn)三個(gè)動(dòng)作:拒絕、通過(guò)以及第三個(gè)復(fù)雜點(diǎn)的動(dòng)作,雖然通過(guò)但告訴魏延廖化,哥曾經(jīng)批準(zhǔn)過(guò)某提案了。(三種條件的達(dá)成請(qǐng)參考上篇文章《paxos分布式一致性算法--講述諸葛亮的反穿越》)
2b,與1b步驟相同,唯一不一樣的是,如果決定批準(zhǔn)某個(gè)提案,必須先把該提案和編號(hào)記錄到羊皮紙的背面。(羊皮紙的詳細(xì)用途參見(jiàn)演習(xí)前提)
3b,記錄法案到羊皮紙的正面上。(本步驟不在下面演習(xí)中出現(xiàn))
3、演習(xí)道具
先解釋下我們用到的道具吧。
羊皮紙(相當(dāng)于硬盤):其正面記錄真正通過(guò)的法令,背面相當(dāng)于永久有效的草紙,背面記錄一個(gè)三元組(S,V,Sh),S表示上次批準(zhǔn)的提案編號(hào),V表示上次批準(zhǔn)的提案,Sh表示處理過(guò)的最大提案編號(hào)。(羊皮紙丟掉后的效果在演習(xí)結(jié)束后說(shuō)明)
草紙:與羊皮紙背面相同,記錄三元組。唯一不同的是,草紙容易丟失。
沙漏:記錄時(shí)間。我們簡(jiǎn)單的認(rèn)為,任何兩個(gè)地方一次通訊時(shí)間為30分鐘。所以,如果我們從提案者那出發(fā),信使到五虎將再回來(lái),我們認(rèn)為一個(gè)小時(shí)足矣(忽略五虎將或者提案者的處理時(shí)間)。
下面的演習(xí)中,只有消息的丟失,實(shí)際上對(duì)于消息的重發(fā)和延遲,也不會(huì)有任何問(wèn)題。只是對(duì)五虎將的缺席,需要做說(shuō)明。如果五虎將的羊皮紙丟失,是不能直接再次加入進(jìn)五人決策團(tuán)的,必須學(xué)習(xí)到最新的狀態(tài)。沒(méi)丟羊皮紙,則可以隨時(shí)加入進(jìn)來(lái)。
書記官記錄法令中的不一致情況這里不加討論。
為了方便在圖表中表示,我們先給五虎將五個(gè)字母編號(hào):關(guān)羽a,張飛b,趙云c,馬超d,黃忠e。
三種顏色表示不同的提案者:黃色表示廖化,藍(lán)色表示周倉(cāng),紅色表示魏延。
下面這幅圖,表示不同的時(shí)間點(diǎn),五虎將和三個(gè)提案者當(dāng)時(shí)的狀態(tài)。
->表示第一步預(yù)提案。包括1a和1b兩步。
-->表示第二步提交提案,包括2a和2b。
五虎將記錄的(s,v,sh)表示的三元組上面講過(guò)了。法令項(xiàng)下面對(duì)應(yīng)的是提案者魏、廖、周三人的狀態(tài)。(wait)表示剛發(fā)出提案,1小時(shí)內(nèi)等待返回呢。
e is drop表示發(fā)送給e黃忠的提案消息丟失了。
好了,可以往下看了。
4、演習(xí)
先放圖,解釋在下面。

詳細(xì)說(shuō)明上圖:
8:30分上班了,紅色周倉(cāng)同學(xué)首先向關(guān)羽、趙云、黃忠三人發(fā)出了提案p1,編號(hào)為100,周倉(cāng)開(kāi)始等返回,預(yù)計(jì)9:30分時(shí)能收到三位的返回。我們假定,發(fā)給黃忠的信使出門就被孔明的跑車撞了。孔明闖禍后老實(shí)了,以下,不再出現(xiàn)信使失誤事件了。
8:40分,崇尚民主的廖化同學(xué)向關(guān)羽、張飛、黃忠三人發(fā)出了編號(hào)為101的提案p2,預(yù)計(jì)9:40分收到返回的信使。
8:50分,喜歡孔孟的魏延同學(xué)向趙云、馬超、黃忠三人發(fā)出了編號(hào)為110(魏延就是搞到大編號(hào)了啊)的提案p3,預(yù)計(jì)9:50收到返回的信使。
9:00整,周倉(cāng)的提案p1到了關(guān)羽、趙云手里(黃忠沒(méi)收到),兩人無(wú)條件接受,記錄(100,p1,100),承諾編號(hào)低于100的提案我可不會(huì)再處理了,然后兩個(gè)信使開(kāi)始返回。
9:10分,廖化編號(hào)為101的提案p2到了關(guān)羽、張飛、黃忠之手,張飛、黃忠哥倆從沒(méi)收過(guò)事件e的提案,毫無(wú)疑問(wèn)記為(101,p2,101),讓信使回復(fù)接受。關(guān)羽則不然,紅臉兄在10分鐘前收到了周倉(cāng)的編號(hào)為100的p1提案。所以,按規(guī)則辦,關(guān)羽改自己的記錄為(100,p1,101),讓信使給廖化回復(fù):你的編號(hào)101比較大,我同意你繼續(xù),不過(guò)我之前同意過(guò)一個(gè)編號(hào)為100的提案p1,請(qǐng)注意哦。
9:20分,魏延的p3提案到了趙云、馬超、黃忠三人之手,馬超第一次收到提案,記為(110,p3,110),回復(fù)批準(zhǔn)。趙云和黃忠則不同,趙云收到過(guò)周倉(cāng)的p1提案,這時(shí)要比提案編號(hào)了,魏延的110大于周倉(cāng)的100,于是趙云記為(100,p1,110),告訴信使:我通過(guò)了,我承諾編號(hào)小于110的我不會(huì)處理,同時(shí),我曾經(jīng)批準(zhǔn)過(guò)編號(hào)為100的提案p1。同理,黃忠記為(101,p2,110),也告訴信使:我曾經(jīng)批準(zhǔn)過(guò)編號(hào)為101的提案p2。
9:30分,周倉(cāng)同學(xué)檢測(cè)返回的信使了,關(guān)羽和趙云都返回批準(zhǔn),但是黃忠沒(méi)有返回。因?yàn)楸仨歂/2+1,也就是大多數(shù)人批準(zhǔn)才行,所以,周倉(cāng)向張飛發(fā)出提案p1。
9:40分,廖化收到了來(lái)自關(guān)羽、張飛、黃忠的回復(fù),三人皆表示同意,但關(guān)羽表示:關(guān)某曾收到過(guò)編號(hào)100的p1提案。所以按照規(guī)則,廖化此時(shí)不能堅(jiān)持自己原來(lái)的提案p2,而要改成關(guān)羽返回的提案p1,然后發(fā)起提交皆段,同樣是讓信使帶給關(guān)羽、張飛、黃忠三人,我們用->>(a,b,e)表示。
9:50分,魏延收到了趙云、馬超、黃忠三人在9:20分的答復(fù),三人都同意了,但回答各不相同。馬超沒(méi)有多話,趙云說(shuō)我曾收到過(guò)編號(hào)為100的p1提案,黃忠說(shuō)我曾經(jīng)收到過(guò)編號(hào)為101的p2提案。于是,魏延根據(jù)規(guī)則,不再提自己原來(lái)的p3提案,改為101編號(hào)對(duì)應(yīng)的提案p2。接著,魏延開(kāi)始向這三人發(fā)出提交請(qǐng)求,編號(hào)為110的提案p2。
10:00整,張飛收到了9:30分周倉(cāng)補(bǔ)發(fā)的編號(hào)為100的提案p1,這之前,張飛在9:10分時(shí)曾經(jīng)批準(zhǔn)過(guò)來(lái)自廖化的提案p2,編號(hào)是101。所以,張飛在9:10時(shí)就已經(jīng)承諾了,以后決不再處理編號(hào)小于101的提案。于是,張飛大吼一聲:我拒絕。當(dāng)然信使將會(huì)在10:30才能把消息帶給周倉(cāng)。
10:10分,關(guān)羽、張飛、黃忠收到了來(lái)自廖化于9:40分發(fā)出的(101,p1)提案,關(guān)羽和張飛都發(fā)現(xiàn)自己可以批準(zhǔn),記錄到羊皮紙的背面,同時(shí)告訴信使:告訴廖化P1提案我批準(zhǔn)了,我承諾編號(hào)小于101的提案不予理會(huì)。黃忠則不然,老將黃忠在9:20分時(shí)收到過(guò)魏延編號(hào)為110的提案,那時(shí)他批準(zhǔn)了,意味著,所有小于110的提案他都會(huì)拒絕掉。這次廖化的提案才101,當(dāng)然被拒絕掉了。三人的回復(fù)將于10:40會(huì)到達(dá)廖化處。
10:20分,魏延編號(hào)為110的P2提案到達(dá)趙云、馬超、黃忠,三人沒(méi)有疑問(wèn),畢竟110編號(hào)最大,都表示批準(zhǔn),并記錄(110,p2,110)到各自的羊皮紙背面,回復(fù)信使通過(guò)。
10:30分,周倉(cāng)收到了他在9:30分發(fā)給張飛的回復(fù),張飛在10:00拒絕了,所以周倉(cāng)這個(gè)提案就此作廢。
10:40分,廖化收到了10:10來(lái)自關(guān)羽、張飛、黃忠的回復(fù),關(guān)張二人批準(zhǔn),然而老黃忠明確表示拒絕,于是這次編號(hào)101的提案作廢。
10:50分,魏延收到了趙云、馬超、黃忠的回復(fù),三人都表示批準(zhǔn),于是編號(hào)為110的提案p2最終作為法令記錄下來(lái)(之后的3b學(xué)習(xí)過(guò)程略過(guò)),從此以后,蜀國(guó)的路線被確立為走民主路線,許多年后,蜀國(guó)統(tǒng)一了銀河系。完。
以上任何步驟,大家可以任意制造難度,例如讓同一個(gè)信使重復(fù)投遞消息,或者延遲一天后消息到達(dá)某虎將處。或者讓某個(gè)虎將正常如廁,而后正常歸來(lái)。大家會(huì)發(fā)現(xiàn),一致性是可以達(dá)到的,無(wú)論怎樣,對(duì)于同一個(gè)事件e,互相沖突的三個(gè)法案:p1,p1,p3,一定只有一個(gè)可以達(dá)成。
對(duì)于任一虎將兄的掛掉,我們要分情況。如果是去大便,那么他的羊皮紙是不能丟的。大便完了,可以正常回到自己的官署辦公。但是如果把羊皮紙丟了,那就不能立刻加入,必須向所有其他人學(xué)習(xí),把失落的過(guò)程都學(xué)到,才能正常加入。這點(diǎn)至關(guān)重要,就是說(shuō),只要硬盤不壞,隨時(shí)SERVER重啟都能加入。硬盤一壞,對(duì)不起,學(xué)習(xí)完了才能繼續(xù)辦公。
5、后記---Leslie的八卦:
paxos算法是解決分布式服務(wù)數(shù)據(jù)一致性的終極算法,google的基礎(chǔ)服務(wù)chubby(GFS的基礎(chǔ)服務(wù))的開(kāi)發(fā)者說(shuō), “there is only one consensus(一致性) protocol, and that’s Paxos”。Microsoft有fast paxos論文,yahoo的zookeeper也用了paxos算法。可見(jiàn),paxos是解決完全的分布式服務(wù)(無(wú)單點(diǎn))間數(shù)據(jù)一致性的最好方法。但是paxos比較復(fù)雜,特別是網(wǎng)上的中文資料里少有能說(shuō)得清楚的(主要是太多paxos變種算法了,摻合到一起攪得人頭大),例如中文wiki上的paxos解釋,光看這個(gè)是不可能搞懂paxos的。
paxos算法由Leslie Lamport在1990年提出,毫無(wú)疑問(wèn),paxos想解決的就是分布式環(huán)境下(server會(huì)掛掉,通訊協(xié)議不可靠,消息可能延遲、丟失、重發(fā))如何保持?jǐn)?shù)據(jù)一致性的問(wèn)題。Leslie Lamport同學(xué)在1982年提出的“拜占庭將軍”問(wèn)題上嘗到了甜頭,這也是個(gè)分布式環(huán)境下的一致性問(wèn)題,Leslie通過(guò)類比的方式,偽造了“拜占庭將軍”歷史,通過(guò)這種簡(jiǎn)單的類比成功的簡(jiǎn)化了復(fù)雜的分布式環(huán)境,效果非常好。于是在1990年Leslie同樣用類比的方式提出了paxos算法,該問(wèn)題跟“拜占庭將軍”問(wèn)題的區(qū)別是,“拜占庭將軍”允許有叛徒,也就是允許偽造消息(默許被黑客攻擊),而paxos則不允許消息被偽造。
Leslie很有幽默感的把論文寫成一個(gè)考古發(fā)現(xiàn),至始至終都在虛構(gòu)他的“考古發(fā)現(xiàn)”。他說(shuō)在考古中發(fā)現(xiàn)了失落的文明:希臘的paxos小島。這里的議員通過(guò)郵遞員傳遞消息,議會(huì)中一個(gè)議員提出法案,多數(shù)議員批準(zhǔn)后法案獲得通過(guò)。當(dāng)然無(wú)論議員還是郵遞員,都是兼職的,他們不可靠,隨時(shí)可能走人,呵,典型的分布式環(huán)境,server可以掛,消息可以丟。Leslie根據(jù)考古文獻(xiàn)反推出了paxos議會(huì)如何搞定法案一致性的問(wèn)題。
發(fā)表論文時(shí),Leslie一直用這種語(yǔ)氣在寫論文,于是《ACM Transactions on Computer Systems》編輯們認(rèn)為太荒誕了,不能從頭到尾虛構(gòu)故事吧?畢竟是嚴(yán)謹(jǐn)?shù)目茖W(xué)雜志,于是打回。Leslie同學(xué)身為牛人,堅(jiān)持自己的看法,同時(shí)認(rèn)為編輯們沒(méi)有幽默感,拒絕修改。時(shí)間流逝,一晃九年過(guò)去,九年后有團(tuán)隊(duì)根據(jù)該論文開(kāi)發(fā)出一個(gè)paxos實(shí)現(xiàn),終于,編輯們低頭了,允許發(fā)布Leslie的論文,但還是加了段編者著,在其中表示Leslie其實(shí)是個(gè)熱愛(ài)計(jì)算機(jī)技術(shù)的考古學(xué)家!也算稍事解嘲。
寫這兩篇文章,我也試了下借喻的手段,用我們熟悉的三國(guó)人物,看看能否講清楚paxos。其實(shí)paxos的算法本身算不得很復(fù)雜,但如果想講清楚在各種異常情形下paxos算法的表現(xiàn),給大家?guī)?lái)的明確的直觀感受:paxos確實(shí)能解決一致性問(wèn)題,這就不容易了。所以篇幅所限,只寫了丟失一個(gè)消息的情況。不過(guò)大家如果從頭看到這,應(yīng)該可以簡(jiǎn)單的任意推導(dǎo)出其他異常吧?
最后,上面說(shuō)的只是算法機(jī)制,如果需要了解現(xiàn)有的各種產(chǎn)品實(shí)現(xiàn),最方便的還是看zookeeper源碼,畢竟是開(kāi)源的,例如去:http://zookeeper.apache.org/doc/r3.3.2/zookeeperOver.html,可以看下概述。淘寶開(kāi)發(fā)團(tuán)隊(duì)有許多關(guān)于zookeeper實(shí)現(xiàn)的文章,到網(wǎng)上搜下就能看到。
對(duì)google的chubby實(shí)現(xiàn),因?yàn)椴皇情_(kāi)源的,只有篇論文可以看:http://static.googleusercontent.com/external_content/untrusted_dlcp/research.google.com/zh-CN/us/archive/chubby-osdi06.pdf