Basic Paxos
總的來說,Basic Paxos分成5個角色,倆個階段,分别是
角色:
1.Client
Client發送一個請求到分布式系統,比如請求一個檔案
1.Proposer
Proposer接收用戶端的請求,并且讓Acceptors接受這個請求。當發送沖突時,擔任協調者。
2.Acceptors
一組Acceptors組成法定人數(一群Acceptors),任何發送給Acceptors的消息都必須發送給法定人數,從Acceptors收到的任何消息都應該忽略,
除非從法定人數内的每個Acceptors都收到一份同樣的消息。
3.Learner
Learner充當協定的複制者,一旦Client的請求被Acceptors通過,Learner就可以執行用戶端的請求(執行請求,響應資料給Client),為了保證可用性,Learner可以動态添加。
上面三個角色,任何一個參與者都可以扮演任意角色,但是在一輪共識過程中,隻能擔任一個角色(在共識形成後Learner才有作用)。
4.Leader
Paxos需要一個Proposer充當Leader來管理過程。但是可能有多個Proposer相信自己是Leader,協定保證隻選擇其中的一個,如果有多個Leader,就會出現沖突更新。
Quorums
Quorums表示法定人數,任何倆組法定人數,必須至少有一個Acceptor是重複的,n/2+1。
Phase1
P1a:Prepare
prepare過程由Proposer提出一個prepare message,格式是{n},n表示這次議案的編号(n唯一,并且按照時間順序全局遞增)。
Proposer 把這個議案發給法定人數(一組Acceptors),如果Proposer不能和法定人數通訊,不能開始這個過程。
注意:prepare message 不能包含提案的值v
P1b:Promise
Acceptors一直在等待prepare message,如果Acceptors收到prepare message,必須檢查prepare message裡面的編号值 n。
1.如果編号值 n 大于以前收到的任意提案值,Acceptors必須響應promise消息,同樣,也必須忽略往後收到編号小于n的消息,
以前 Accept 過提案,它給Proposer的響應中必須包含先前 Accept 的提案,形式可能是{m,v}(m為提案的編号,v是 Accept 的值)。
2.編号n小于等于以前收到過的提案編号,Acceptor可以忽略這個提案(假裝沒有收到),當然,一個更優的做法是響應一個拒絕資訊,用于通知Proposer結束這次提案。
Phase2
P2a:Accept
如果Proposer 從法定人數中收到足夠多的promise,它需要把值v放進提案。如果有任何一個Acceptors 先前 Accept 過提案,Acceptors 會把 Accept 的提案響應給 Proposer,
比如是 {m,v}。那麼,Proposer必須(must語義)把 v 設定成收到 Promise 内最高提案的值,比如是 z。
如果所有法定人數 Acceptors 響應說先前沒有收到過提案,Proposer 可以設定任意的值 x。
Proposer發送 Accept 消息給Acceptor,消息的格式為{n,v}(v是 Proposer 選擇的值,n是先前 prepare 階段的提案編号)。
是以,Acceptors收到的 Accept 消息要麼是 { n,z},要麼是 { n,x }。
Accept消息應該了解成 " 請求 "," 請接受這次提案"。
P2b:Accepted
法定人數 Acceptors 從Proposer那裡收到 { n,v } 的 Accept 消息,當Acceptors 在 P1b 中沒有承諾給任何編号大于n的提案時,Acceptors必須接受值 v。
Acceptors 一旦接受值 v,應該回複一個 Accepted 消息給Proposer 和各個 Learner。
要不然就是不接受值 v,此時它應該忽略這個請求。
注意:
Acceptor可以接受多個提案,在其他Proposer還不知道新決定的值,并且用一個更高的n做編号發起提案就會出現這個情況。在這種情況下,雖然Acceptors在以前已經接受了一個新值, 它仍然可以響應 promise 并且 accept 新值,這些Proposer可能會有不同的值,但是,Paxos協定保證Acceptors都會一緻同意一個單一值(新值覆寫舊值)。
缺陷模型
在多個Proposer發出沖突的Prepare message或者Proposer沒有收到法定人數響應(Promise和Accepted),在這些情形下,如果發起新的提案。必須使用一個更高的提案編号
沒有任何失敗情形下的Basic Paxos流程
在下圖内,1 個Client,1個Proposer,3個Acceptors(法定人數是3),2個Learner,圖中表示的是第一輪共識,并且中間沒有任何錯誤發生。
Client Proposer Acceptor Learner
| | | | | | |
X-------->| | | | | | Request
| X--------->|->|->| | | Prepare(1)
| |<---------X--X--X | | Promise(1,{Va,Vb,Vc})
| X--------->|->|->| | | Accept!(1,V)
| |<---------X--X--X------>|->| Accepted(1,V)
|<---------------------------------X--X Response
| | | | | | |
在這裡,V 是 {Va,Vb,Vc}中的最後一個
Acceptor失敗時的Basic Paxos流程
下圖表示有一個Acceptors失敗了,但是剩餘的Acceptors總數仍然占大多數(總共是3個Acceptor,挂了一個,還有倆個Acceptor),是以,Basic Paxos仍然會成功。
Client Proposer Acceptor Learner
| | | | | | |
X-------->| | | | | | Request
| X--------->|->|->| | | Prepare(1)
| | | | ! | | !! FAIL !!
| |<---------X--X | | Promise(1,{Va, Vb, null})
| X--------->|->| | | Accept!(1,V)
| |<---------X--X--------->|->| Accepted(1,V)
|<---------------------------------X--X Response
| | | | | |
備援的Learner失敗時的Basic Paxos的流程
下圖表示有一個Learner失敗,但是Basic Paxos仍然會成功
Client Proposer Acceptor Learner
| | | | | | |
X-------->| | | | | | Request
| X--------->|->|->| | | Prepare(1)
| |<---------X--X--X | | Promise(1,{Va,Vb,Vc})
| X--------->|->|->| | | Accept!(1,V)
| |<---------X--X--X------>|->| Accepted(1,V)
| | | | | | ! !! FAIL !!
|<---------------------------------X Response
| | | | | |
Proposer 失敗時的Basic Paxos流程
在下面這個圖中,Proposer在提出一個值的過程中失敗了, 在Acceptor的Accepted傳回之前,并且Proposer發送了一個Accept給了法定人數中的某一個Acceptor。
同時,出現了一個新的Leader(某個Proposer,圖中沒有畫出來),注意圖中畫了倆輪共識,從上往下
Client Proposer Acceptor Learner
| | | | | | |
X----->| | | | | | Request
| X------------>|->|->| | | Prepare(1)
| |<------------X--X--X | | Promise(1,{Va, Vb, Vc})
| | | | | | |
| | | | | | | !! Leader fails during broadcast !!
| X------------>| | | | | Accept!(1,V)
| ! | | | | |
| | | | | | | !! NEW LEADER !!
| X--------->|->|->| | | Prepare(2)
| |<---------X--X--X | | Promise(2,{V, null, null}) -------響應Promise帶上先前的Accept的提案,注意後倆個是null。
| X--------->|->|->| | | Accept!(2,V)
| |<---------X--X--X------>|->| Accepted(2,V)
|<---------------------------------X--X Response
| | | | | | |
多個Proposers沖突的Basic Paxos流程
Client Leader Acceptor Learner
| | | | | | |
X----->| | | | | | Request
| X------------>|->|->| | | Prepare(1)
| |<------------X--X--X | | Promise(1,{null,null,null})
| ! | | | | | !! LEADER FAILS
| | | | | | | !! NEW LEADER (knows last number was 1)
| X--------->|->|->| | | Prepare(2)
| |<---------X--X--X | | Promise(2,{null,null,null})
| | | | | | | | !! OLD LEADER recovers
| | | | | | | | !! OLD LEADER tries 2, denied
| X------------>|->|->| | | Prepare(2)
| |<------------X--X--X | | Nack(2)
| | | | | | | | !! OLD LEADER tries 3
| X------------>|->|->| | | Prepare(3)
| |<------------X--X--X | | Promise(3,{null,null,null})
| | | | | | | | !! NEW LEADER proposes, denied
| | X--------->|->|->| | | Accept!(2,Va)
| | |<---------X--X--X | | Nack(3)
| | | | | | | | !! NEW LEADER tries 4
| | X--------->|->|->| | | Prepare(4)
| | |<---------X--X--X | | Promise(4,{null,null,null})
| | | | | | | | !! OLD LEADER proposes, denied
| X------------>|->|->| | | Accept!(3,Vb)
| |<------------X--X--X | | Nack(4)
| | | | | | | | ... and so on ...
注意:
上面圖中的描述和 Accepted 處的描述有點不同,在 Accepted 中的描述是,Acceptors可以忽略這個Accept請求,但是,在上圖中,Acceptors回複了一個Nack,并且帶上了最新的提案編号,
最壞的情況下,這個沖突會持續沖突下去,誰也不能送出成功