關於paxos最爲簡潔的描述在這裏,做者的大體思路是根據結論來找到條件來知足這個條件,而這個限制是逐步收緊,而且在各個參與者之間逐步進行職責轉移和派發。node
P2a. If a proposal with value v is chosen, then every higher-numbered proposal accepted by any acceptor has value v.
其中最爲關鍵的就是從一個抽象的限制P2b到一個能夠實際具體操做P2c的轉換,在此次限制(職責)轉換的過程當中,首先把P2a是到P2b的限制比較簡單天然,可是它是第一次把限制從acceptor轉移到了proposer:由於若是全部的更高提議被提議時都是chosen值,那麼接受者確定接受的也都是chosen值。web
P2b. If a proposal with value v is chosen, then every higher-numbered proposal issued by any proposer has value v.
把限制轉移到提議者以後,這個限制仍是一個比較抽象的限制,或者說不是一個能夠具體操做的限制,由於要求提議者須要知道chosen值,而這個chosen值如何肯定則並無具體操做流程。此時就是須要把限制具體細化到能夠操做的級別。這個時候須要從P2b到P2c的細化:
假設第m次提議的v值被肯定,也就意味着存在一個多數派C,這個多數派accept了這個值,此時的C是固定的acceptor集合。考察這個集合C,因爲提議值大於m的提議都是已經chosen的v值,因此它們在以後一直都是肯定值v。
對於一個提議者,它若是選擇任意一個acceptor多數派集合S,這個S集合和C之間確定有至少一個相同元素,而且這個元素已經接受了提議值v,而且提議號在m到n-1之間。
P2c. For any v and n, if a proposal with value v and number n is issued,
then there is a set S consisting of a majority of acceptors such that
either (a) no acceptor in S has accepted any proposal numbered less
than n, or (b) v is the value of the highest-numbered proposal among
all proposals numbered less than n accepted by the acceptors in S.
對於這個多數派集合,那麼提議號小於m的被chosen值(若是存在的話)是未被接受的,而大於等於m的提議號的值都是相同的chosen值v。因此取這個集合中全部已經接受的提議中提議號最大的一個,它必定是chosen值。promise
而P2b這個命題把限制從acceptor轉移到了proposer,當acceptor的一個值被接受以後,proposer提議的每一個值都應該是v。這裏第一次把皮球從acceptor踢到了proposer。
因爲P2c是對提議者做了限制,當一個提議被chosen以後,全部提議的值都是以前的提議值。這個知足P2c便可知足P2b的理解仍是比較簡單的:由於肯定以後,全部的提議值都是該值,而接受者只會接收提議值,因此接收值必定是v。
可是對於提議者來講,如何當一個值被chosen以後,它的提議值必定是這個肯定值呢?這裏首先要證實,當第m次提議的v值被肯定以後,咱們要證實如何保證以後每次提議n>m的提議值都有值v。
根據假設,若是m次提議的v被chosen,則說明有一個多數acceptor集合,這個集合中的全部元素接受值都是以v,這個多數集合是肯定爲C(這個集合是致使v被接受的acceptor集合)。如今固定考察這個集合C中的每一個acceptor:因爲以後的每次大於m的提議都具備相同的值v,因此它們收到m……n-1次提議都有相同的v值。在第n次提議前時,集合中這些元素接受是提議多是m……n-1次的任意次提議,而且這些提議有相同的值v。
對於任意一個包含了多數派的集合S來講,它必定包含有一個C中的至少一個元素。這樣對於任意一個多數派集合S,對於n提議的v值,其中任意一個元素都沒有接受過編號小於n的提議,或者v是全部小於提議n的提議中最大值的。
當有這個集合的狀況下,可能集合中不包含任何已經接受的提議,
For any v and n, if a proposal with value v and number n is issued,
then there is a set S consisting of a majority of acceptors such that
either (a) no acceptor in S has accepted any proposal numbered less
than n, or (b) v is the value of the highest-numbered proposal among
all proposals numbered less than n accepted by the acceptors in S.less
2、phxpaxos中prepare階段對於多數派的處理函數
在prepare的回包中,經過
m_oMsgCounter.AddPromiseOrAccept(oPaxosMsg.nodeid());
m_oProposerState.AddPreAcceptValue(oBallot, oPaxosMsg.value());
更新可能已經被接受的值
phxpaxos-master\src\algorithm\proposer.cpp
void Proposer :: OnPrepareReply(const PaxosMsg & oPaxosMsg)
{
……
m_oMsgCounter.AddReceive(oPaxosMsg.nodeid());spa
if (oPaxosMsg.rejectbypromiseid() == 0)
{
BallotNumber oBallot(oPaxosMsg.preacceptid(), oPaxosMsg.preacceptnodeid());
PLGDebug("[Promise] PreAcceptedID %lu PreAcceptedNodeID %lu ValueSize %zu",
oPaxosMsg.preacceptid(), oPaxosMsg.preacceptnodeid(), oPaxosMsg.value().size());
m_oMsgCounter.AddPromiseOrAccept(oPaxosMsg.nodeid());
m_oProposerState.AddPreAcceptValue(oBallot, oPaxosMsg.value());
}
else
{
PLGDebug("[Reject] RejectByPromiseID %lu", oPaxosMsg.rejectbypromiseid());
m_oMsgCounter.AddReject(oPaxosMsg.nodeid());
m_bWasRejectBySomeone = true;
m_oProposerState.SetOtherProposalID(oPaxosMsg.rejectbypromiseid());
}.net
if (m_oMsgCounter.IsPassedOnThisRound())
{
int iUseTimeMs = m_oTimeStat.Point();
BP->GetProposerBP()->PreparePass(iUseTimeMs);
PLGImp("[Pass] start accept, usetime %dms", iUseTimeMs);
m_bCanSkipPrepare = true;
Accept();
}
else if (m_oMsgCounter.IsRejectedOnThisRound()
|| m_oMsgCounter.IsAllReceiveOnThisRound())
{
BP->GetProposerBP()->PrepareNotPass();
PLGImp("[Not Pass] wait 30ms and restart prepare");
AddPrepareTimer(OtherUtils::FastRand() % 30 + 10);
}
……
}rest
而這個具體的增長,其中會判斷提議值是否更大,它始終記錄提議值最大的被接受提議值。是不是多數派則經過IsPassedOnThisRound函數肯定
void ProposerState :: AddPreAcceptValue(
const BallotNumber & oOtherPreAcceptBallot,
const std::string & sOtherPreAcceptValue)
{
PLGDebug("OtherPreAcceptID %lu OtherPreAcceptNodeID %lu HighestOtherPreAcceptID %lu "
"HighestOtherPreAcceptNodeID %lu OtherPreAcceptValue %zu",
oOtherPreAcceptBallot.m_llProposalID, oOtherPreAcceptBallot.m_llNodeID,
m_oHighestOtherPreAcceptBallot.m_llProposalID, m_oHighestOtherPreAcceptBallot.m_llNodeID,
sOtherPreAcceptValue.size());ip
if (oOtherPreAcceptBallot.isnull())
{
return;
}
if (oOtherPreAcceptBallot > m_oHighestOtherPreAcceptBallot)
{
m_oHighestOtherPreAcceptBallot = oOtherPreAcceptBallot;
m_sValue = sOtherPreAcceptValue;
}
}get
3、phxpaxos中對於值被chosen的處理
這個地方比較奇怪的是值是否被chosen是在proposer邏輯中完成的,而learner的功能相對比較少,它並無進行確認數量的計數。void Proposer :: OnAcceptReply(const PaxosMsg & oPaxosMsg){…… if (m_oMsgCounter.IsPassedOnThisRound()) { int iUseTimeMs = m_oTimeStat.Point(); BP->GetProposerBP()->AcceptPass(iUseTimeMs); PLGImp("[Pass] Start send learn, usetime %dms", iUseTimeMs); ExitAccept(); m_poLearner->ProposerSendSuccess(GetInstanceID(), m_oProposerState.GetProposalID()); } else if (m_oMsgCounter.IsRejectedOnThisRound() || m_oMsgCounter.IsAllReceiveOnThisRound()) { BP->GetProposerBP()->AcceptNotPass(); PLGImp("[Not pass] wait 30ms and Restart prepare"); AddAcceptTimer(OtherUtils::FastRand() % 30 + 10); }……}