内容简要:
一、MGR特性
二、集群架构
三、数据同步原理
四、性能分析
五、适用场景
六、高可用方案
(一)MGR是什么
1.MGR的定义
MGR是具备强大的分布式协调能力,可用于创建弹性、高可用性、高容错的复制拓扑的一个MySQL插件。
2.通讯协议
基于Paxos算法的GCS原子广播协议,保证了一条事务在集群内要么在全部节点上提交,要么全部回滚。
3.组成员资格
MGR内部提供一个视图服务,集群节点之间相互交换各自的视图信息, 从而且实现集群整体的稳态。
4.数据一致性
MGR内部实现了一套不同事务之间修改数据的冲突认证检测机制。在集群的所有节点当中进行一个冲突认证检测,反之,通过冲突认证检测的事务即可提交成功。
(二)示例

上图是一个三节点的MGR实例集群,Member1代表Primary节点,Member2、Member3代表Secondary节点。
当一个事务发起提交后,它会通过原子广播协议分发到集群其他Secondary节点。集群的Secondary节点进行Binlog Event,通过冲突检测之后,事务提交成功。在所有的Secondary节点提交成功之后,会在Primary节点进行提交。
反之,如果在Primary节点冲突认证检测失败,Secondary节点会丢弃这段事务对应的Binlog,Primary节点回滚该事务。
MGR架构分为单主模式和多主模式,由多种插件组成。
(一)MGR插件组成
如上图所示,MGR插件组成使用MySQL Server与API接口层以及若干组件,最后由GCS(Group Communication System)协议封装而成。
MySQL Server调用MGR插件是基于MySQL现有的主从复制,利用Row格式的Binlog和Gtid等功能实现的集群架构。
API接口层复制基于MySQL Server交互的接口集,在逻辑上将MySQL内核与MGR插件隔绝开来。其他组件例如Capture组件,它是负责事务状态在集群内提交或是回滚,以及通过Binlog event广播到其他节点上进行的冲突认证检测进行到哪个阶段。Apply组件代表MGR集群Secondary节点Binlog回放,Recovery组件代表进行崩溃恢复或集群扩容时增量数据的应用。
(二)单主模式
单主模式集群原理流程图
ON表示单主模式,也是默认模式,OFF表示多主模式。
l 如上图所示,在单主模式下(group_replication_single_primary_mode = ON):
1.该变量在所有组成员中必须设置为相同的值,同一个组中,不能将成员部署在不同模式中。例如,一个成员配置为单主模式,另一个成员配置为多主模式。
2.该集群具有一个设置为读写模式的主节点,组中的所有其他成员都设置为只读模式(superread-only = ON);
3.读写节点通常是引导该组的第一个节点,加入该集群的所有其他只读节点均需要从读写节点同步数据,并自动设置为只读模式。
(三)多主模式
多主模式集群原理流程图
l 在多主模式下(group_replication_single_primary_mode = OFF):
1.所有节点不会区分Primary和Standby角色;
2.加入该集群时,与其他组成员兼容的任何节点都被设置为读写模式,并且可以处理写请求, 即使它们在集群内是并发执行的;
3.如果组复制中的某个节点停止接受写事务,例如,在某个节点意外宕机的情况下,可以将与 其连接的客户端重定向或故障转移到处于读写模式的任何其他健康的节点;
4.组复制本身不处理客户端故障转移,因此需要使用中间件框架(例如MySQL Router 8.0,代理,连接器或应用程序本身)来实现。
(一)同步原理示例
同步原理示例
如上图所示,以一个三节点的MGR集群为例。在单主模式下,当一个事务发起提交,它会通过原子广播协议将事务伴随着Binlog Event广播到其他Secondary节点上。在获得集群大多数节点同意之后,它会进行一个提交。如果通过冲突认证检测,那么该事务最终会在集群当中提交。
如果在Secondary节点上面没有通过冲突认证检测,那么Secondary节点丢弃该事务对应的Binlog,Primary节点回滚该事务,
(二)冲突检测原理
冲突检测原理
l 如上图所示,在冲突检测时:
1.每个事务的Gtid Set和对应的主键Hash值组成事务认证列表,在每个节点中都维护这样一个冲突检测库,这个库在内存当中;
2.gtid set:标记数据库的快照版本,事务提交前从gtid_execute变量中获取该值;
3.事务提交前,数据库中执行了的Gtid集合,随着Binlog中的Event通过原子广播的方式分发到集群的所有节点上进行事务冲突检测。
(三)冲突检测示例
如上图所示,以T1与T2这两条Update语句为例。
l 若T2修改的数据在冲突检测数据库中无匹配记录,则判定为通过冲突检测认证;
l 若T2中的GTID SET包含了冲突检测数据库中相同主键值的GTID SET,则冲突认证检测通过;
l 冲突认证检测通过后,每个节点的冲突检测数据库按照如下规则变更:
1. 若在冲突检测数据库中无匹配记录,则向其中插入一条新的记录。
2. 如果有记录,则更新冲突检测数据库中的GTID SET值。
若T1修改的数据在冲突检测数据库中有匹配到记录,且T1的GTID SET不包括冲突检测数据库中的GTID SET,则判定为冲突检测不通过。
注意:冲突检测不通过时,不会更新认证数据库里的GTID SET。
(一)存在的问题
目前业内存在以下问题:
l MGR可确保仅在集群中的大多数节点都已收到事务,并就并发发送的所有事务之间的相对顺序达成一致后才提交事务。相对顺序意味着,在分发到Secondary节点之后,可以不按照Primary节点提交的顺序进行提交,只需保证和集群的一致性即可。
l 在流量小的时候不存在任何的性能问题。当流量突增时,如果集群中某些节点的写入吞吐量比其他节点少,尤其是小于Primary节点,则这些节点的数据和Primary节点的数据存在偏差。例如说在集群当中,一个3节点的集群,如果节点之间服务性能存在差异的话,则会存在性能问题。
l 在单主模式的集群中,如果发生故障转移,在新的Primary节点可以立刻接受写入请求的情况下,则存在集群内事务一致性的问题。
举例说明,当集群扩容时,例如由3节点集群扩容到5节点集群:
l 无论采用Clone的方式还是用Xtrabackup做全量数据恢复后,都避免不了在集群扩容期间产生的增量数据以二进制日志的方式来追平;
l 若新扩容的节点配置较低,写入吞吐差,则新加入的节点很有可能一直处于Recover的状态, 该节点很难达到Online的状态。
(二)事务一致性保证
在进行高可用切换之后,存在事务一致性保证,这是由于Secondary节点和Primary节点存在追数据的过程,如果数据没有追平,那么业务数据可能会读到旧的数据,用户可以根据group_replication_consistency参数对应的可选值进行调整,总共有5个值如下:
1. EVENTUAL
开启该级别的事务(T2),事务执行前不会等待先序事务(T1)的回放完成,也不会影响后序事务等待该事务回放完成。
2.BEFORE
开启了该级别的事务(T2),在开始前首先要等待先序事务(T1)的回放完成,确保此事务将在最新的数据上执行。
3.AFTER
开启该级别的事务(T1),只有等该事务回放完成。其他后序事务(T2)才开始执行,这样所有后序事务都会读取包含其更改的数据库状态,而不管它们在哪个节点上执行。
4. BEFORE_AND_AFTER
开启该级别等事务(T2),需要等待前序事务的回放完成(T1);
同时后序事务(T3)等待该事务的回放完成。
5. BEFORE_ON_PRIMARY_FAILOVER
在发生切换时,连到新主的事务会被阻塞,等待先序提交的事务回放完成;
这样确保在故障切换时客户端都能读取到主服务器上的最新数据,保证了一致性。
用户根据不同的级别,根据业务上是读多写少,还是写多读少,或者是读写均衡的请求,不同的场景选择不同的值即可。
(三)流控机制
1.流控机制的功能
l 性能的问题对应着解决方案,MGR的流控机制试图解决以下问题:
1)集群内节点之间不会相差太多的事务;
2)快速适应集群内不断变化的负载,例如集群内的写压力暴增或集群中增加更多的节点;
3)均分可用写容量到集群内的所有节点上;
4)避免减少吞吐量而造成资源浪费。
2.基本机制
l 流控机制存在两个基本机制:
1)监控集群内所有节点以收集有关吞吐量和队列大小的一些统计信息,以便对每个节点能承受的最大写入压力进行有根据的评估;
2)对集群中的所有节点的并发写能力时刻保持监控,一旦某节点的并发压力超过了集群中所有节点的平均 写能力,就会对其执行流量控制。
3.基本队列
流控机制存在两个基本队列:认证队列和二进制日志应用队列。
当其中一个队列的大小超过用户定义的阈值时,就会触发流量控制机制。
l 对于流量控制配置:
首先,需要选择对谁配置流量控制,是对认证队列、还是针对应用队列、还是两者都需要配置流量控制。然后,对需要配置流量控制的对象(认证队列和应用队列)设置流量控制阈值。
4.流控过程
l 流控具体过程如下:
1)将根据上一阶段延迟的事务数量逐步减少10%,让触发限流机制的队列减小到限流机制被触发的阈值之内, 待到恢复后,为避免在队列大小超过阈值时出现吞吐量的陡增,在此之后,每个时间段的吞吐量只允许增长相同的10%;
2)当前的限流机制不会影响到触发限流机制阈值内的事务,但是会延迟应用超过阈值的事务,直到本监控周期结束;
3)如果触发节流机制的阈值设置的非常小,部分事务的延迟可能会接近一个完整的监控周期。
在日常业务中,MGR高可用集群存在如下经典适用场景:
1.弹性复制
需要非常灵活的复制基础设施的环境,其中MySQL Server的数量必须动态增加或减少,并且在增加或减少Server的过程中,对业务的副作用尽可能少。例如,云数据库服务。
2.高可用分片
分片是实现写扩展的一种流行方法。基于MGR实现的高可用分片,其中每个分片都会映射到一个复制组上(逻辑上需要一一对应,但在物理上一个复制组可以承载多个分片)。
3.替代主从复制
在某些情况下,使用一个主库会造成单点争用。在某些情况下,向整个组内的多个成员同时写入数据,多种模式可以避免单点争用,对应用来说可能伸缩性更强。
上图为业内的一个常用的高可用方案。
通常在云数据库里,一个三节点的MGR集群本身不保证业务的写入重定向,那么在MGR集群上面加一个读写分离的中间件Maxscale。
将源代码重新编译之后,会打开一个它自带的保活机制,Maxscale会自动探测MGR集群里Primer节点状态,如果发生高可用切换或者是当前的Primary节点宕机之后,它会重新探测选取出来一个新的Primary节点,然后自动将业务写请求重定向到新的Primary节点上。业务只需要将Client端经过SQL解析连到Maxscale,然后经Maxscale做一个路由转发,即可实现一个灵活的高可用。