以下是我在DTCC大会上的分享的《深入理解MySQL Group Replication》的核心内容Group Replication架构原理的PPT,分享给大家。


Group Replication的原理_java

Group Replication的原理_java_02

上图是状态机复制的简单原理,其实MySQL的异步复制也是状态机复制。

Group Replication的原理_java_03

Group Replication使用了原子广播系统的原理:

  • 每个节点上有一个广播模块。

  • 每个广播模块都能接收用户的请求。

  • 广播模块之间进行通讯,对请求进行全局排序。最终每个节点的广播模块上都会有一个顺序完全一样的请求队列。

  • 广播模块将队列中的请求按照顺序发送给DB执行,符合状态机复制的要求(按照同样的顺序执行同样的操作)。因此所有DB的数据保持一致。

原子广播系统我在《由浅入深理解Paxos协议(1)》中有详细的介绍。

Group Replication在实现上有一些变化,但原理是一样的。Group Replication广播的不是原始事务语句而是事务的Binlog Events。因此广播模块是嵌在事务执行流程中的,而不需要和客户端交互。当事务语句执行完准备提交时,Group Replication会捕捉到事务的Binlog Events然后进行原子广播。先执行,再全局排序的方法会导致冲突。即当前事务排在另一个修改了同一行数据的事务的后面,但是执行却在前面。因此需要做冲突检测。


本地事务和远程事务的执行流程不一样,因此分别介绍。

Group Replication的原理_java_04

Group Replication的原理_java_05

Group Replication的原理_java_06

Group Replication的原理_java_07

事务在每个节点上都需要在Certify模块进行冲突检测,不管是本地事务还是远程事务。冲突检测的过程是在每个模块上单独进行的,不需要在各个节点之间交互。这里其实是应用了状态机复制的原理,所有节点上的事务都是按照同样的顺序做的冲突检测。因此任何一个事务在所有节点上的冲突检测结果都是相同的。

  • 如果事务在一个节点上认证成功了,那么在其他节点上肯定也是成功的。

  • 如果事务在一个节点上认证失败了,那么在其他节点上肯定也是失败的。

冲突检测有两个因素:

  1. 事务是否修改了同样的数据(以行为单位,通过主键识别)。

  2. 是否是同时修改的。通过事务执行时的数据库快照版本来判定。数据库的快照是用GTID SET来标识的。事务提交前从全局变量gtid_executed中获取GTID SET。这个GTID SET就是代表了当前事务在提交前,数据库中已经执行了的GTIDs。也即是当前事务提交前,数据库的快照版本。数据库的快照版本会随着事务的Binlog Events一起广播到其他的节点上,用来做冲突检测。


由于时间原因,以下部分未能在DTCC上分享给大家。这里一并分享给大家。

冲突检测数据库中记录了已经通过认证的事务所修改的主键和一个GTID SET。

冲突检测时,从冲突检测数据库中找到当前事务修改的数据的记录。如果没有找到,就没有冲突。如果找到了,则将自己的快照版本和冲突检测数据库中记录的GTID SET进行比对:

  • 如果自己的快照版本中包含了冲突检测数据库中记录的所有GTIDs,那么就没有冲突。自己的快照中包含了,说明该事务在初始节点上执行时,上一次对本行数据的修改已经在初始节点上提交了。所以就不是同时执行的。

  • 如果自己的快照版本中没有包含冲突检测数据库中记录的所有GTIDs,则说明当前事务在初始节点上执行时,上一次对本行数据的修改还没有在初始节点上执行。因此判定为同时执行。

Group Replication的原理_java_08

认证成功后,要更新冲突检测数据库。更新后的GTID SET是当前事务的快照版本+当前事务的GTID。


Group Replication的原理_java_09

认证失败,不需要更新冲突检测数据库。