在一個分佈式系統中,因爲節點故障、網絡延遲等各類緣由,根據CAP理論,咱們只能保證一致性(Consistency)、可用性(Availability)、分區容錯性(Partition Tolerance) 中的兩個。html
對於一致性要求高的系統,好比銀行取款機,就會選擇犧牲可用性,故障時拒絕服務。MongoDB、Redis、MapReduce使用這種方案。git
對於靜態網站、實時性較弱的查詢類數據庫,會犧牲一致性,容許一段時間內不一致。簡單分佈式協議Gossip,數據庫CouchDB、Cassandra使用這種方案。web
圖1算法
如圖1所示,一致性問題,能夠根據是否存在惡意節點分類兩類。無惡意節點,是指節點會丟失、重發、不響應消息,但不會篡改消息。而惡意節點可能會篡改消息。有惡意節點的問題稱爲拜占庭將軍問題,不在今天的討論範圍。Paxos很好地解決了無惡意節點的分佈式一致性問題。數據庫
1990年,Leslie Lamport在論文《The Part-Time Parliament》中提出Paxos算法。因爲論文使用故事的方式,沒有使用數學證實,起初並無獲得重視。直到1998年該論文才被正式接受。後來2001年Lamport又從新組織了論文,發表了《Paxos Made Simple》。做爲分佈式系統領域的早期貢獻者,Lamport得到了2013年圖靈獎。網絡
Paxos算法普遍應用在分佈式系統中,Google Chubby的做者Mike Burrows說:「這個世界上只有一種一致性算法,那就是 Paxos(There is only one consensus protocol, and that's Paxos)」。分佈式
後來的Raft算法、是對Paxos的簡化和改進,變得更加容易理解和實現。ide
Paxos原本是虛構故事中的一個小島,議會經過表決來達成共識。可是議員可能離開,信使可能走丟,或者重複傳遞消息。對應到分佈式系統的節點故障和網絡故障。性能
圖2優化
如圖2所示,假設議員要提議中午吃什麼。若是有一個或者多我的同時提議,但一次只能經過一個提議,這就是Basic Paxos,是Paxos中最基礎的協議。
顯然Basic Paxos是不夠高效的,若是將Basic Paxos並行起來,同時提出多個提議,好比中午吃什麼、吃完去哪裏嗨皮、誰請客等提議,議員也能夠同時經過多個提議。這就是Multi-Paxos協議。
Paxos算法存在3種角色:Proposer、Acceptor、Learner,在實現中一個節點能夠擔任多個角色。
圖3
Learner不參與投票過程,爲了簡化描述,咱們直接忽略掉這個角色。
運行過程分爲兩個階段,Prepare階段和Accept階段。
Proposer須要發出兩次請求,Prepare請求和Accept請求。Acceptor根據其收集的信息,接受或者拒絕提案。
Prepare階段
Accept階段
完整算法如圖4所示:
圖4
Acceptor須要持久化存儲minProposal、acceptedProposal、acceptedValue這3個值。
Basic Paxos共識過程一共有三種可能的狀況。下面分別進行介紹。
如圖5所示。X、Y表明客戶端,S1到S5是服務端,既表明Proposer又表明Acceptor。爲了防止重複,Proposer提出的編號由兩部分組成:
序列號.Server ID
例如S1提出的提案編號,就是1.一、2.一、3.1……
圖5 以上圖片來自Paxos lecture (Raft user study)第13頁
這個過程表示,S1收到客戶端的提案X,因而S1做爲Proposer,給S1-S3發送Prepare(3.1)請求,因爲Acceptor S1-S3沒有接受過任何提案,因此接受該提案。而後Proposer S1-S3發送Accept(3.1, X)請求,提案X成功被接受。
在提案X被接受後,S5收到客戶端的提案Y,S5給S3-S5發送Prepare(4.5)請求。對S3來講,4.5比3.1大,且已經接受了X,它會回覆這個提案 (3.1, X)。S5收到S3-S5的回覆後,使用X替換本身的Y,因而發送Accept(4.5, X)請求。S3-S5接受提案。最終全部Acceptor達成一致,都擁有相同的值X。
這種狀況的結果是:新Proposer會使用已接受的提案
圖6 以上圖片來自Paxos lecture (Raft user study)第14頁
如圖6所示,S3接受了提案(3.1, X),但S1-S2尚未收到請求。此時S3-S5收到Prepare(4.5),S3會回覆已經接受的提案(3.1, X),S5將提案值Y替換成X,發送Accept(4.5, X)給S3-S5,對S3來講,編號4.5大於3.1,因此會接受這個提案。
而後S1-S2接受Accept(3.1, X),最終全部Acceptor達成一致。
這種狀況的結果是:新Proposer會使用已提交的值,兩個提案都能成功
圖7 以上圖片來自Paxos lecture (Raft user study)第15頁
如圖7所示,S1接受了提案(3.1, X),S3先收到Prepare(4.5),後收到Accept(3.1, X),因爲3.1小於4.5,會直接拒絕這個提案。因此提案X沒法收到超過半數的回覆,這個提案就被阻止了。提案Y能夠順利經過。
這種狀況的結果是:新Proposer使用本身的提案,舊提案被阻止
活鎖發生的概率很小,可是會嚴重影響性能。就是兩個或者多個Proposer在Prepare階段發生互相搶佔的情形。
圖8 以上圖片來自Paxos lecture (Raft user study)第16頁
解決方案是Proposer失敗以後給一個隨機的等待時間,這樣就減小同時請求的可能。
上一小節提到的活鎖,也可使用Multi-Paxos來解決。它會從Proposer中選出一個Leader,只由Leader提交Proposal,還能夠省去Prepare階段,減小了性能損失。固然,直接把Basic Paxos的多個Proposer的機制搬過來也是能夠的,只是性能不夠高。
將Basic Paxos並行以後,就能夠同時處理多個提案了,所以要能存儲不一樣的提案,也要保證提案的順序。
Acceptor的結構如圖9所示,每一個方塊表明一個Entry,用於存儲提案值。用遞增的Index來區分Entry。
圖9
Multi-Paxos須要解決幾個問題,咱們逐個來看。
一個最簡單的選舉方法,就是Server ID最大的當Leader。
每一個Server間隔T時間向其餘Server發送心跳包,若是一個Server在2T時間內沒有收到來自更高ID的心跳,那麼它就成爲Leader。
其餘Proposer,必須拒絕客戶端的請求,或將請求轉發給Leader。
固然,還可使用其餘更復雜的選舉方法,這裏再也不詳述。
Prepare的做用是阻止舊的提案,以及檢查是否有已接受的提案值。
當只有一個Leader發送提案的時候,Prepare是不會產生衝突的,能夠省略Prepare階段,這樣就能夠減小一半RPC請求。
Prepare請求的邏輯修改成:
當Leader收到超過半數的noMoreAccepted回覆,以後就不須要Prepare階段了,只須要發送Accept請求。直到Accept被拒絕,就從新須要Prepare階段。
目前爲止信息是不完整的。
第1個問題的解決方案很簡單,就是Proposer給所有節點發送Accept請求。
第2個問題稍微複雜一些。首先,咱們能夠增長一個Success RPC,讓Proposer顯式地告訴Acceptor,哪一個提案已經被接受了,這個是徹底可行的,只不過還能夠優化一下,減小請求次數。
咱們在Accept請求中,增長一個firstUnchosenIndex參數,表示Proposer的第一個未接受的Index,這個參數隱含的意思是,對該Proposer來講,小於Index的提案都已經被接受了。所以Acceptor能夠利用這個信息,把小於Index的提案標記爲已接受。另外要注意的是,只能標記該Proposer的提案,由於若是發生Leader切換,不一樣的Proposer擁有的信息可能不一樣,不區分Proposer直接標記的話可能會不一致。
圖10
如圖10所示,Proposer正在準備提交Index=2的Accept請求,0和1是已接受的提案,所以firstUnchosenIndex=2。當Acceptor收到請求後,比較Index,就能夠將Dumplings提案標記爲已接受。
因爲以前提到的Leader切換的狀況,仍然須要顯式請求才能得到完整信息。在Acceptor回覆Accept消息時,帶上本身的firstUnchosenIndex。若是比Proposer的小,那麼就須要發送Success(index, value),Acceptor將收到的index標記爲已接受,再回復新的firstUnchosenIndex,如此往復直到二者的index相等。
Paxos是分佈式一致性問題中的重要共識算法。這篇文章分別介紹了最基礎的Basic Paxos,和可以並行的Multi-Paxos。
在Basic Paxos中,介紹了3種基本角色Proposer、Acceptor、Learner,以及提案時可能發生的3種基本狀況。在Multi-Paxos中,介紹了3個須要解決的問題:Leader選舉、Prepare省略、完整信息流。
在下一篇文章中,咱們將實現一個簡單的demo來驗證這個算法,實現過程將會涉及到更多的細節。
Paxos lecture (Raft user study)
YouTube | Paxos lecture (Raft user study)
本做品採用CC BY 4.0許可協議,轉載時請註明連接。