带你一步步走入Paxos的世界 -- 序列4 -- Multi-Paxos

在前面的序列中,我们知道Basic Paxos可以用来确定1条日志。而Multi-Paxos就是针对每条日志都执行1个2PC的Paxos协议,从而确定多条日志,也就是一个日志流。有了日志流,就能基于日志流建立一个”复制状态机“模型。

本人新书出版,对技术感兴趣的朋友请关注:
在这里插入图片描述

https://mp.weixin.qq.com/s/uq2cw2Lgf-s4nPHJ4WH4aw

#复制状态机
这里写图片描述

在上图中,有3台机器,每台机器上都有一个日志流+1个状态机。日志流是落盘的,而状态机是纯内存的。

通过Multi-Paxos保证3台机器上的日志流完全一致,那么把日志流apply到各自的状态机上,状态机肯定也就完全一致。这就是所谓的“复制状态机”模型。

对于客户端呢,是多写。多个客户端,并发的往这3台机器写入。

上面就是一个最最基本的,利用Basic Paxos协议来实现的一个复制状态机模型。

但是这个最基本的实现,有什么问题呢?

问题1:活锁问题

在前面我们知道,Basic Paxos是1个不断循环的2PC。所以如果是多个客户端写多个机器的话,每个机器都是Proposer,会导致并发冲突很高,也就是每个节点都可能执行多次循环才能确定一条日志。极端情况,就是每个节点都在无限循环的执行2PC,也就是所谓的“活锁问题”。

为了减少并发冲突,我们可以变多写为单写,也就是选出一个Leader,只让这个Leader充当Proposer。

其他机器收到写请求,都把写请求转发给这个Leader;或者让客户端把写请求都发给Leader。

解决方案1 – 无租约的Leader选举

在上面的basic-paxos实现的复制状态机中,我们知道可以多写。也就意味着,可以出现多个leader。我们的算法,并不需要强制保证,任意时刻只能有1个leader。

下面的leader选举算法来自standford的课程ppt:
这里写图片描述

可以看出,这个算法很简单,因为网络超时原因,很容易知道可能出现多个leader,但这并不影响Multi-paxos协议的正确性,只是可能增大并发写的冲突。

解决方案2 – 有租约的Leader选举

另外一种方案是严格保证任意时刻只能有1个leader,也就是所谓的“租约”。

租约的意思是:在1个限定的期限内,就是某台机器一直是leader。即使这个机器挂了,leader也不能切换。必须等到租期到了之后,才能开始新的leader选举。

这种方式会带来短暂的不可用,但保证了任意时刻只会有1个leader。

具体实现方式,可以参见PaxosLease

问提2:性能问题

在前面的系列中,我们知道Basic-Paxos是一个无限循环的2PC,1条日志的确认至少需要2个RTT + 2次落盘(1次是prepare的广播与回复,1次是accept的广播与回复)。

如果每条日志都要2个RTT + 2次落盘,这个性能就很差了。

而Multi-paxos在选出Leader之后,可以把2PC优化成1PC,也就只需要1个RTT + 1次落盘了。

解决方案:2PC --》 1PC

基本思路就是当一个节点被确认为leader之后,它先广播1次prepare,一旦超过半数同意之后,之后对于收到的每条日志,直接执行accept。

在这里,perpare就不再是对1条日志的控制了,而是相对于拿到了整个日志的控制权。一旦这个leader拿到了整个日志的控制权,后面就直接略过prepare,直接执行accept。

那如果有新的leader出现怎么办呢?

新的leader出现,它肯定会先发起prepare,导致minProposalId变大。这个时候旧的leader的广播accept肯定就会失败,旧的leader就会自己转变成一个普通的acceptor,新的leader就把旧的顶替掉了。

具体实现细节

在basic-paxos中,我们知道2PC的具体参数形式如下:

prepare(n)
accept(n,v)

在multi-paxos中,多个一个日志的index参数,也变成了如下形式:

prepare(n, index)
accept(n,v,index)

问题3:被choose的日志,状态如何同步给其他机器

对于1条日志,当Proposer(也就是上面的leader) 接收到多数派对accept请求的同意之后,就知道这条日志被"choose"了,也就是被确认了,不能再更改!

但是只有proposer知道这条日志被choose了,其他的acceptor并不知道这条日志被choose了。如何把这个信息传递给其他accepotor呢?

解决方案1:proposer主动通知

在standford的课程ppt里面,提到了这种方案。给上面的accept再增加一个参数:

accept(n, v, index, firstUnchoosenIndex)

这里写图片描述

Proposer在广播accept的时候,最后额外带来一个参数firstUnchosenIndex = 7。意思是说:7之前的日志,都已经“choose"了。

Acceptor收到这种请求之后,就检查7之前的日志,如果发现7之前的日志符合以下条件:
acceptedProposal[i] == request.proposal(也就是第1个参数n),就把该日志的状态置为choose。

解决方案2:acceptor被动查询

当一个acceptor被选为leader之后,对于所有未choose的日志(也就是未确认的日志),可以挨个再执行一遍paxos,来判断该条日志的、被大多数缺认的值是多少。

因为basic-paxos有一个核心特性:一旦一个值被choose(被确定)之后,无论再执行多少遍paxos,该值都不会改变!!因此,再执行1遍paxos,相当于向集群发起了1次查询!

Multi-Paxos的精髓之1 – 1个强一致的“P2P网络”

关于Multi paxos,还有很多的实现细节,后面会再从其他角度来论述。在此,先对本文所讲述的,做1个总结:

任何1条日志,也就2种状态(choose, unchoose)。当然,还有一种状态就是applied,也就是被choose的日志,被apply到状态机。这种状态跟paxos协议关系不大。

choose状态,就是这条日志,被多数派接受,不可更改;

unchoose,就是还不确定,引用下面来自阿里ob团队的李凯的话,就是“薛定谔的猫”,或者“最大commit原则“。1条unchoose的日志,可能是已经被choose了,只是该节点还不知道;也可能是还没有被choose。要想确认,那就再执行1次paxos,也就是所谓的“最大commit原则“。
https://mp.weixin.qq.com/s?__biz=MzAwMDU1MTE1OQ==&mid=403582309&idx=1&sn=80c006f4e84a8af35dc8e9654f018ace&scene=0&key=710a5d99946419d9c39ba913a16ee674c6016edfedfc691aa0df9db57d008419c1a96168b861e0ef8b01d6ec76c7e693&ascene=7&uin=MTc0MDg1&devicetype=android-19&version=26030931&nettype=WIFI&pass_ticket=J96esr4md7XLhmfoelhpNAXq73CErFPyQ5BlGEWTtHg=

精髓:整个Multi-paxos就是类似1个P2P网络,所有节点互相双向同步,对所有unchoose的日志进行不断确认的过程!!这个网络中,可以出现多个leader,可能出现多个leader来回切换,这都不影响正确性!

Multi-Paxos的精髓之2 – "时序“的透彻理解

Multi-Paxos保证了所有节点的日志顺序一模一样,但对于每个节点自身来说,可以认为它的日志并没有所谓的“顺序”。

什么意思呢?

1)假如1个客户端,连续发送了2条日志a, b(a没有收到回复,就发出了b)。那对于服务器来讲,存储顺序可能是a,b;也可能是b,a;也可能a, b之间还插入了其他客户端发来的日志!

2)假如1个客户端,连续发送了2条日志a, b(a收到回复之后,再发出的b)。那对于服务器来讲,存储顺序可能是a, b;也可能是a, xxx, b。但不会出现b在a的前面。

所以说,所谓的“时序”,只有在单个客户端串行的发送日志时,才有所谓的顺序。

多个客户端并发的写,服务器又是并发的对每条日志执行paxos,整体看起来就没有所谓的“顺序”。

写在最后

从上面的讨论可以看出,Multi-paxos并不像Basic-paxos那样有一个标准答案。针对Multi-paxos的方方面面,其实存在着不同的实现方案!!!

在后面的序列中,会从其他角度,进一步讨论Multi Paxos。

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值