|
翻译自“The king is dead, long live the king”: Our Paxos-based consensus”
在这篇博文中,我们会描述一下我们的基于Paxos的方案,名字叫扩展通讯(eXtended COMmunications),或者缩写为XCOM,这是MySQL Group Replication的关键组件。
XCOM负责传播事务给同组的MySQL实例,并管理改组实例的成员关系。他的关键功能包括:
- 有序投递(Ordered Delivery): 确保消息 (也就是事务)是按同样的顺序投递给所有的成员的
- 动态成员关系:提供管理属于同组的MySQL实例功能
- 故障检测:和动态成员关系一起,决定处于故障状态的成员的命运

MGR启动初期,我们使用了Corosync作为组内通讯系统,但之后很快就决定了还是使用自己的方案,该方案描述在
接下来,我们会展示一些MGR和分布式共识协议的背景信息,然后描述XCOM之后的设计决策。
1. 背景
MySQL Group Replication基于Database State Machine. Update 事务在某个成员上开始和执行,而无需跟远端成员的协商。在提交时,事务的变化传播给组内所有成员并且是按相同的顺序传播到所有地方。之后一个认证流程检查是否有并发事务之间的冲突,验证是否有任何其他事务已经尝试更新了某个已经之前被更新了的记录(verifying if any other transaction has tried to update a record that had been already updated before)。 如果没有冲突,那么事务就在所有成员处提交,有冲突则事务被取消。
如果需要了解更详细的信息,可以查看
该解决方案背后,有一套组内通讯系统,它维护这组内的成员关系,并且保证了带着事务变更信息的消息是全然有序的。成员关系管理和全然有序的消息传播,在分布式系统中,作为基本的概念,被称之为共识:
在我们这种情况下,MySQL服务实例就以下情况达成一致:一个新的MySQL服务实例是否应该加入组、或者一个老的MySQL实例是否应该移出组、或者哪个事务修改应该作为下一个进行传播。
Paxos 可能是最为知名的共识协议,它分两阶段工作

经典Paxos是面向leader的算法。因此,第一个阶段被称作准备阶段或者Leader选举阶段,在这个阶段,某个成员发出一条消息,附带一个ballot number,给所有成员,以说明它想要成为leader。如果收到消息的一个成员,还没有向任何成员许诺它已经接受了一个更高ballot number的请求,那么收到消息的这个成员会回复消息。如果申请成为leader的成员从组内大多数成员出得到恢复,它就会成为新的leader。否则,该成员会在一定时间的超时后,使用一个更高的ballot number来再度尝试参与选举,直到成功。
注意,只有在当前的leader已经被怀疑处于故障状态的时候,这个选举阶段才是需要的。否则,只有协议的第二阶段需要执行。可以参见 Good Leaders are game changes: Paxos & Raft ,这里面有关于leader选举、ballot numbers等等的讨论。
在第二阶段,leader提议一个值,并且在它得到大多成员回复时,认为该值已经被接受。 提议的消息会打上这个leader的ballot number作为标签,并且其他某个成员只有在没有具有更高ballot number的成员尝试获得leadership时,才会回复这个leader,表示它接受这个提案。
当这个leader确认了一个提议已经被接受。它发送一条learn消息给所有组内成员,表示他们可以投递这个消息到Group Communication System Layer,而这个Layer最终会投递消息给MGR。通常情况下,这条learn消息会被(piggybacked onto?)或者更其他消息一起批量处理。
实际应用中,这种一致性的同意是发生在一系列值之上,对应的协议被称作Multi-Paxos。

注意在经典的或标准的Multi-Paxos中,任何成员都必须发送事务的变更给leader,然后这个leader确保消息投递的整体有序。如果某个事务本身就是在Paxos leader那个成员那里执行的,这没有问题。否则就会有额外的交流步骤,而且通常leader会变成一个瓶颈。
2. XCOM
MGR是多主的可随处修改的方案,事务的变更可以来自于组内任意一个成员。采用一个基于单主的协议显然会影响可扩展性,因为所有的更新都需要经过leader,然后这个leader再负责传播这些变更。所以我们第一个目标就是客服这种单主模式带来的可能的瓶颈,并且创建了一个多leader的,或者更精确的说,多个proposer的方案。这种方式跟Mencius有一定相似,比如说使用skip messages,但总体的设计跟原始Paxos更加接近。

在这个协议总,每个成员被赋予一个唯一的数字,并且在全然有序的消息形成的流中,赋予一个保留的slot。举例来说,假如我们有三个成员:
- 0号成员负责以下slots:0, 3, 6, … 3 * n + 0
- 1号成员负责以下slots:1, 4, 7, … 3 * n + 1
- 2号成员负责以下slots:2, 5, 8, … 3 * n + 2
在一个有着'g'个成员的组内,下一个slot和对应成员的关系由这个公式给出:g * n + 成员数目 ,这里'n'是单调递增序列,有每个成员自行维护,并在每次一个提案发出时自行递增。
所以实际上并没有leader选举过程,每个成员在消息所组成的流中,都是它所负责的slots的leader。每个成员在其所对应的slots,都可以直接提议消息,而不用等待其他成员,虽然在这样做的距离上有一定限制(该限制在下个小节介绍)。
2.1 处理Gaps
如果成员可以不用等待任何协商而直接提议消息,那么在消息流中可能会有一些Gaps。比如说,成员 1 和 2 可能就消息 1 and 2 分别达成一致,但成员 0 可能还有就消息 0 进行提议或达成一致,不论出于什么原因。

这种情况下,在没有就slot 0的内容达成一致并投递的情况下,所有成员不能最终投递slot 1和2 中的内容。否则,全体有序消息传播的熟悉会被违背。所以,全部成员不得不进行等待,知道他们获悉了slot 0总的内容,然后再开始投递slot 0,1,2 中的内容。
所以,消息流中的gaps可能影响性能,并且系统需要仔细处理。成员0还没有填充slot 0,可能是由于它没有什么需要提议的,也可能是对应成员已经挂了,或者就是对应成员很慢。
如果成员0没有什么可以提议的,它会发送一条skip消息,给组内其他成员,说明它没有什么要说的,其他成员可以在这个slot里面填充"noop"。skip消息可能在两种情况下发出,一是当特定成员发现自己没有什么数据消息要发出时,一是该成员发现其他成员在等待他的提案以推动进展。第二种情况在该成员能够意识到,是在其学习到更后面的slot中的决议时.

skip消息无需经历标准的Paxos协议流程(也就是prepare, accept and learn消息)。他是一个learn消息,直接通知其他成员他们应该填充对应的slot 以"noop"消息。
这里之所以是一个优化,是由于其他非slots'的所有者成员只能通过propose "noop"的方式,并且不得不执行Paxos的所有阶段(也就是Prepare和Propose阶段)。换句话说,如果成员1想要提议一些内容以填充 slot 0,从而投递1号消息和2号消息,它不得不提议一个"noop"消息。

注意prepare阶段的目标之一,是找出是否有另一个消息已经在这个slot被决定或提议了。在这种情况下,消息会由代理slot持有者的成员发出。 通过Paxos协议的两阶段,该成员会确保没有不一致的情况发生。为了避免有几个成员代表另一个成员提议"noop"(因为这种情况会拖慢整个系统),有着最低的unique number的成员会实际负责该提议。但是,这个过程中并没有正式的leader选举过程,因为该成员并不会为其他成员的slots负责,他只是在需要的时候介入,以推动整个系统的进展。
2.2 已实现的优化
消息可以批量处理,填到单个slot中, 从而减少交互步骤。另外,成员们可以不用等待它之前的提案结果,直接提议新的消息。
Batching和pipelining是两种可以提高性能的优化,并且我们已经实现了它们。然而,
它们的有效性极为依赖系统的属性,主要是网络延迟和带宽,但也收到CPU速度和应用程序特性的影响。 查看 Tuning Paxos for high-throughput with batching and pipelining 以获得这方面的更多详细资料。
在accept阶段传输应用程序数据时,我们也只传递一次,以避免大量数据被传来传去。根据 Vitor,单单这个优化就提高了整体的性能20%左右。
3. 当前的局限
当前版本的XCOM,作为MySQL Server 5.7.17的一部分,不允许用户调整pipeline的大小和绑定到一起的提议的数目。
当前版本也不允许配置成员在协议中的角色:proposer, acceptor and learner。这意味着所有成员都是proposers,很容易可以推断,单个较慢的成员会影响到整个系统的性能。 性能的降低可能由于网络的局限性或问题造成,比如高时延的网络;也可能由于机器内部的局限性和问题造成,比如某台机器在超负荷运转。
5. 结论
从https://dev.mysql.com/downloads/mysql/下载MGR,并且从manual中找到安装说明。 请尝试一下,如果你遇到任何问题,还请在MySQL Server: Group Replication’类别下面开个bug report,这样我们就可以知道有问题并且去进一步调研。 |
|