在前面的序列2中,我们引出了Basic Paxos,其目的就是为了确定1条日志,1条日志对应到Basic Paxos里面就是一个value。
有兴趣朋友可以关注公众号“架构之道与术”, 获取最新文章。
或扫描如下二维码:
2个角色:Proposer和Acceptor
在前面的场景中,我们提到3个client并发的往3个node发送3条写指令。对应到Paxos协议里面,就是每个node同时充当了2个角色:Proposer/Acceptor。实际实现过程中,一般这2个角色是在同1个进程里面!
当node1收到client1发送的x = 1的指令,node1就作为一个proposer,向所有的acceptor(其他2个node + 自己)发出提议,希望大家都把x=1这条日志写到3个node上面;
同理,当node2收到client2发送的x = 3的指令,node2就作为一个proposer,向所有的acceptor发出提议,。。。
Basic Paxos的2PC
下面就来详细阐述Paxos的算法细节:
首先,每个acceptor需要持久化3个变量
(minProposalId, acceptProposalId, acceptValue)。初始阶段:minProposalId = acceptProposalId = 0, acceptValue = null。
下面是算法的2个阶段:
P1(Prepare阶段)
P1a: Proposer广播prepare(n),其中n是本机生成的一个自增id,不需要全局有序,比如可以用时间戳 + ip。
P1b: Acceptor收到prepare(n),做如下决策:
if n > minProposalId,回复yes。
同时 minProposalId = n(持久化),
返回(acceptProposalId, acceptValue)
else
回复no
P1c: Proposer如果收到半数以上的yes,则取acceptorProposalId最大的acceptValue作为v,进入第2个阶段,即开始广播accept(n,v)。如果acceptor返回的都是null,就取自己的值作为v,进入第2个阶段!
否则,n自增,重复P1a.
P2(Accept阶段)
P2a: Proposer广播accept(n, v)。这里的n就是P1阶段的n,v可能是自己的值,也可能是第1阶段的acceptValue
P2b: Acceptor收到accept(n, v),做如下决策:
if n > = minProposalId, 回复yes。同时
minProposalId = acceptProposalId = n (持久化),
acceptValue = value
return minProposalId
else
回复no
P2c: Proposer如果收到半数以上的yes,并且minProposalId = n,算法结束。
否则,n自增,重复P1a
Basic Paxos的2个问题
(1)从上面的算法可以看出,Paxos是一个“不断循环”的2PC。在P1C或者P2C阶段,算法都可能失败,重新开始循环。这也就是通常所说的“活锁”问题,就是可能陷入不断循环。
(2)每确定1个值,至少需要2次RTT(2个阶段,2个网络来回) + 2次写盘,性能是个问题。
而Multi-Paxos就是要解决这2个问题,关于Multi-Paxos,下次待续!