结合phxpaxos简单看下paxos

一、paxos的基本假设

关于paxos最为简洁的描述在这里,作者的大致思路是根据结论来找到条件来满足这个条件,而这个限制是逐步收紧,并且在各个参与者之间逐步进行职责转移和派发。

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值。

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值。

而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.

二、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());

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());
}

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);
}
……
}

而这个具体的增加,其中会判断提议值是否更大,它始终记录提议值最大的被接受提议值。是否是多数派则通过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());

if (oOtherPreAcceptBallot.isnull())
{
return;
}

if (oOtherPreAcceptBallot > m_oHighestOtherPreAcceptBallot)
{
m_oHighestOtherPreAcceptBallot = oOtherPreAcceptBallot;
m_sValue = sOtherPreAcceptValue;
}
}

三、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);
}
……
}

posted on 2019-03-21 16:04  tsecer  阅读(162)  评论(0编辑  收藏  举报

导航