目录
1. MGR简介
1. 为什么是MGR
MGR是MySQL Group Replication的缩写,即MySQL组复制。
在以往,我们一般是利用MySQL的主从复制或半同步复制来提供高可用解决方案,但这存在以下几个比较严重的问题:
-
主从复制间容易发生复制延迟,尤其是在5.6以前的版本,以及当数据库实例中存在没有显式主键表时,很容易发生。
-
主从复制节点间的数据一致性无法自行实现最终一致性。
-
当主节点发生故障时,如果有多个从节点,无法自动从中选择合适的节点作为新的主节点。
-
如果采用(增强)半同步复制,那么当有个从节点因为负载较高、网络延迟或其他意外因素使得事务无法及时确认时,也会反过来影响主节点的事务提交。
因为上述几个明显的缺点,因此MySQL推出了全新的高可用解决方案 -- 组复制,这是本系列文章要着重介绍的新特性。
MGR是MySQL 5.7.17开始引入的,但随着5.7版本逐渐退出历史舞台(MySQL 5.7已于2020年10月起不再做大的功能更新,只有修修补补以及针对安全更新),更多MGR相关特性都只在MySQL 8.0上才有。
因此,如果线上还有基于MySQL 5.7版本的MGR环境的话,建议尽快升级、迁移到MySQL 8.0版本。进一步提醒,推荐MySQL 8.0.22及之后的版本,整体会更稳定可靠,也有些很不错的新功能(不只是MGR方面的)。
2. MGR技术概要
MGR具备以下几个特点:
-
基于shared-nothing模式,所有节点都有一份完整数据,发生故障时可以直接切换。
-
MGR提供了数据一致性保障,默认是最终一致性,可根据业务特征需要自行调整一致性级别。
-
支持在线添加、删除节点,节点管理更方便。
-
支持故障自动检测及自动切换,发生故障时能自动切换到新的主节点,再配合MySQL Router中间件,应用层无需干预或调整。
-
支持单节点、多节点写入两种模式,可根据架构或业务需要选择哪种方案,不过强烈建议选用单主模式。
MGR可以选择单主(Single-Primary)模式
如上图所示,一开始S1节点是Primary角色,提供读写服务。当它发生故障时,剩下的S2-S5节点会再投票选举出S2作为新的Primary角色提供读写服务,而S1节点在达到一定超时阈值后,就会被踢出。
亦可选择多主(Multi-Primary)模式(再次强烈建议选用单主模式)
如上图所示,一开始S1-S5所有节点都是Primary角色,都可以提供读写服务,任何一个节点发生故障时,只需要把指向这个节点的流量切换下就行。
上述两种架构模式下,应用端通过MySQL Router连接后端在MGR服务,当后端节点发生切换时,Router会自动感知,对应用端来说几乎是透明的,影响很小,架构上也更灵活。
3. MGR技术架构
首先来个MGR的技术架构图:
MGR是以Plugin方式嵌入MySQL,部署更灵活方便。
事务从Server层通过钩子(hook)进入MGR API接口层,再分发到各组件层,在组件层完成事务Capture/Apply/Recover,通过复制协议层(Replication Protocol Logics)传输事务,最后经由GCS协调事务在各节点的最终一致性。
MGR节点间由组通信系统(GCS)提供支持,它提供了故障检测机制、组成员角色管理,以及安全且有序的消息传递,这些机制可确保在各节点间一致地复制数据。这项技术的核心是Paxos算法的实现,在MySQL里称之为XCom,由它充当MGR的通信引擎。
对于要提交的事务,组中的多数派节点必须就全局事务序列中给定的事务顺序达成一致。各节点做出决定提交或中止事务的选择,但所有节点都要做出相同的决定。如果发生网络分区,导致节点间无法达成一致决定,则在网络恢复前,MGR无法工作。
MGR支持单主和多主两种模式,在单主模式下,各节点会自动选定主节点,只有该主节点能同时读写,而其他(从)节点只能只读。在多主模式下,所有节点都可以进行读写。
相对于MariaDB Galera Cluster(以及基于此技术的Percona XtraDB Cluster,下面为了书写方便,都统称为PXC),个人认为MGR具备以下几个优势:
-
PXC的消息广播机制是在节点间循环的,需要所有节点都确认消息,因此只要有一个节点故障,则会导致整个PXC都发生故障。而MGR则是多数派投票模式,个别少数派节点故障时,一般不影响整体的可用性。这也是PXC存在的最大问题。
-
PXC的节点间数据传输除了binlog,还有个gcache,这相当于是给MySQL又增加两个黑盒子。而MGR则都是基于原生binlog的,没有新增黑盒子,运行起来更可靠,需要排障时也更方便。
-
发生网络分区时,整个PXC集群都不可用。而MGR则至少还能提供只读服务。
-
PXC的流控机制影响更大,一旦触发流控,所有节点都受到影响。而MGR触发流控后,只会影响本地节点,不影响远程节点。当然了,MySQL的流控做的也比较粗糙,在GreatSQL中进一步完善和优化。
-
执行DDL期间,整个PXC集群都不可同时执行DML,也就是说不支持Online DDL。而MGR是支持的,这也是很大的优势。
相对于传统主从复制(Replication),我认为MGR的优势有以下几点:
-
主从复制非常容易产生复制延迟,尤其是当表中没有显式主键时。而在MGR里,要求表一定要有主键(或是可用作聚集索引的非空唯一索引),避免了这个问题。
-
半同步复制中,一旦slave因为锁或其他原因响应慢的话,也会导致master事务被阻塞。MGR是采用多数派确认机制,个别节点响应慢对Primary节点的影响没那么大(不要选用AFTER模式)。
-
主从复制没有类似MGR那样提供事务数据的一致性保证。MGR自带了事务数据一致性保障机制。
以上是我根据MySQL、MariaDB、Percona的资料整理得到的观点,不一定准确和全面,有不完善的地方还请留言指正。
4. 小结
- 本节主要介绍了什么是MGR,MGR的技术架构概要,以及MGR相对PXC的几个技术优势。
- MGR是MySQL四部战略走的关键一环,依靠MGR和MySQL Shell、MySQL Router已实现了读节点扩展,以及写节点扩展(MGR多主模式),下一步预计实现sharding,让我们拭目以待。
2. 组复制技术架构
1. 传统主从复制技术架构
传统主从复制的方式是在master节点上执行数据更新事务,而后记录这些事务到binlog中,再将binlog发送到slave节点转储成relay log,在slave节点上再有单独的线程读取这些relay log然后重新执行或应用这些事务,它是shared-nothing的,每个节点都有一份完整的数据副本,其技术流程图如下所示:
MySQL还提供了半同步复制,这是在传统主从复制的基础上增加了一个同步的步骤,master节点上提交事务前,要先等到slave节点确认收到事务信息才可以(所以前文才说当slave节点响应慢时会影响master节点的事务提交),其技术流程图如下所示:
2. MGR组复制技术架构
MGR也是shared-nothing的,每个节点都有一份完整的数据副本,节点间通过GCS(Group Communication System)进行交互。GCS层提供了节点间的全局消息及其有序性的保证。
MGR可以做到在任何节点、任何时间都能执行读写事务(不含只读事务),不过读写事务要被整个复制组确认后才能提交。如果是只读事务则没有这个限制,任何节点都可以发起及提交。
当读写事务准备提交前,它会向复制组发出一个原子广播,内容包括:该事务修改的数据,及其所对应的writeset。复制组中所有节点要么接收该事务,要么都不接收。如果组中所有节点都接收该事务消息,那么它们都会按照与之前发送事务的相同顺序收到该广播消息。因此,所有组成员都以相同的顺序接收事务的写集,并为事务建立全局顺序。
在多个节点上并行执行的事务是可能产生冲突的,这时候就需要对比判断两个并行事务的writeset来确认,这个过程称为事务认证,也叫做冲突检测。事务冲突检测是行级别的,也就是说两个并行的事务更新同一行时,则视为产生冲突。这时的做法是全局顺序在前面的事务可以成功,所有节点都提交该事务。而全局顺序在后面的事务会失败回滚,各节点会删除该事务。这实际上是个分布式的谁先提交谁先赢得事务的规则。建议:如果经常发生节点间的事务冲突,那最好将这些事务放在同一个节点上执行,这样它们在本地事务并发控制协调下可能都可以提交成功,而不至于由于MGR的冲突检测而导致某个事务总是被回滚。
对于正在应用或外化的事务,MGR允许它们不一定按照原有顺序执行,只要不破坏事务的一致性和有效性即可。MGR默认要求是最终一致性,也就是说当所有事务都应用完毕后,所有节点的数据是一致的。当流量巨大时,事务可能会被外化而导致顺序轻微不一致。例如在多主模式下,一个本地事务在通过认证后会被立即外化,尽管此时可能还有个有这更早全局顺序的远程事务还没被应用,只要MGR的认证线程认为这个事务不会产生冲突即可。在单主模式下,在Primary节点上的本地并发事务,在不产生冲突的情况下,其提交和外化的顺序可能和该事物的全局事务顺序有轻微不一致。在Secondary节点上,由于没有写事务,因此它们的事务顺序和全局事务顺序是一致的。
下图描述了MGR的组复制协议,可以看到和传统主从复制(及半同步复制)的一些差异。为了简单起见,图中少了共识算法和Paxos相关的信息:
3. MGR的单主和多主模式
MGR支持单主或多主两种模式。
在启动时,通过设置选项 group_replication_single_primary_mode
来决定使用哪种模式,各节点中该值的设置要求一致。设置为 ON 时表示采用 单主模式,当设置为 OFF 时表示采用 多主模式。
在运行过程中,不能在线修改 group_replication_single_primary_mode
的值,但是从MySQL 8.0.13开始,可以通过调用 group_replication_switch_to_single_primary_mode()
和 group_replication_switch_to_multi_primary_mode()
这两个udf在线修改运行模式,或者通过MySQL Shell修改。
在 单主模式 下,有且只有一个(Primary)节点可以写入数据,其余(Secondary)节点都只能读数据。而在 多主模式 下,可以在任意节点上同时读写数据。
MGR最多只能支持9个节点,无论单主还是多主模式。
4. 节点管理
MGR由一组节点构成,每个节点都有唯一的名字,以 UUID 的格式表现。节点可以动态加入或离开(也可能是被动被驱逐)MGR。
MGR的组成员服务用于维护定义各活跃节点的信息,这些活跃节点信息也称之为组视图(view)。各节点的组视图是一致的,这表示在给定时刻组中有哪些活跃成员。
MGR各节点除了在事务提交时要保持一致外,也包括组视图发生变化时也要达成一致。当有新节点加入,或现有节点离开时,都会触发新的组视图变更。
当有节点主动离开集群时,它会触发集群自动重配置,剩下的节点会就新的组视图达成一致。但若节点是因为网络异常或宕机等原因意外离开集群时,则无法触发自动重配置,这时候集群故障检测机制会在该节点离开一段时间后识别到这个状态,并发出重配置组视图的提议。重配置组视图需要得到多数派成员的同意才行,当无法形成一致时,就无法实现自动重配置,需要人工介入处理。无法形成一致意见可能的原因有,剩下的节点数没达到总结点数的一半以上,也就是无法形成多数派。
在节点被确认故障之前,或在重新配置组以删除该故障节点前,允许该节点短暂离线,然后尝试重新加入集群。在这种情况下,该节点可能会丢失它以前的状态(事务数据),如果此时其他节点向它发送了包含崩溃前的消息,则这就可能会导致数据不一致等问题。
为了解决这个问题,从MySQL 5.7.22开始,MGR会检查具有相同地址+端口的节点再次以新身份加入集群的情况,确认当前是否还有其旧身份存在。这时候其新身份不能加入,直到旧身份能从集群中删掉。
注意:
选项
group_replication_member_expel_timeout
的作用是设置一个等待期,使得节点在被正式驱逐前有更多时间尝试重新加回集群,也就是说处于被怀疑状态的节点,在超时之前还可尝试重新加入集群ÿ