前言
本文介绍关于MySQL组复制的背景信息和基本原理。包括,介绍MySQL传统复制方法的原理和隐患、介绍组复制的原理,单主模式和多主模式等等。通过结合原理图学习这些概念,可以很好的帮助我们理解组复制技术这一MySQL高可用方案,有利于提升我们对组复制的管理能力,以及为部署组复制和学习InnoDB Cluter打下理论基础。
官方参考文档:group-replication.html
1 复制技术
1.1 异步复制
1)异步复制的原理图如下:
2)异步复制的大致过程:
- 主库执行SQL语句:存储引擎执行SQL操作;
- 主库写binlog:主库记录执行的所有数据库变更操作,将这些操作以二进制格式保存在binlog中;
- 主库传送binlog事件:主库写binlog后,把 binlog 里面的内容传给从库的中继日志(relay log)中;
- 主库事务返回客户端:主库写binlog后,可直接在引擎层提交事务,将事务返回客户端。
步骤3和步骤4实是同步进行的。
3)异步复制的隐患:
由于步骤3和步骤4实是同步进行的,也就是说主库写binlog后,直接提交事务的同时,向从库发送binlog事件。当主库出现故障,复制中断,原来主库上可能有一部分已经完成提交的事务还没来得及发送到从库,当从库切换为主库后,就会发现主库之前写入的数据丢失了,无法保证主从数据一致性。
1.2 半同步复制
1)半同步复制的原理图如下:
2)半同步复制的大致过程:
- 主库执行SQL语句:存储引擎执行SQL操作;
- 主库写binlog:主库记录执行的所有数据库变更操作,将这些操作以二进制格式保存在binlog中;
- 主库传送binlog事件:主库写binlog后,把 binlog 里面的内容传给从库的中继日志(relay log)中;
- 从库发送 ACK:从库收到binlog后,发送给主库一个 ACK,表示收到了;
- 主库事务返回客户端:主库收到从库的ACK信号后,在引擎层提交事务,将事务返回客户端。
跟异步复制相比,半同步复制保证了事务在返回客户端后,对应的binlog事件从库确认收到了,已经写入到relay log中。
3)半同步复制的隐患:
当事务在写入binlog之后,写入relay log之前,主库宕机了,主从切换后,从库看到的数据有可能跟写入binlog的会话数据不一致。并且,当主库恢复后,由于宕机前,事务已经写入binlog,在实例恢复过程中会从新将这部分事务提交,这就导致了主从数据不一致。
1.3 组复制
MySQL Group Replication(MGR)是MySQL数据库的一种高可用性解决方案,它提供了一个用于MySQL服务器的多主复制插件。它允许一组MySQL服务器一起工作,形成一个单一的、高可用性的、容错的复制组。
MySQL Group Replication背后的设计和实现基于Paxos算法。Paxos是一种分布式一致性算法,用于确保在分布式系统中的节点之间达成一致的共识。在MySQL Group Replication中,Paxos算法的思想被用来协调和保持组中成员之间的一致性状态。
关于MySQL Group Replication的一些关键点如下:
-
同步复制: Group Replication的一个显著特点是支持同步复制。当在一个服务器上提交事务时,它会立即被复制到组中的所有其他服务器。这确保了在任何给定时间点,所有成员都具有相同的数据集。
-
自动组成员管理: Group Replication自动管理组的成员资格。当向组中添加新服务器时,它会自动与现有成员同步。如果服务器失败或离开组,剩余的服务器会自动调整以适应变化,确保持续运行。
-
多主复制: Group Replication组中的每个服务器都可以接受读和写事务。这允许分布式工作负载,并提供了改进的读可伸缩性。
-
一致性: Group Replication通过使用分布式认证过程确保所有成员的一致性。这意味着在提交事务之前,它会由组中大多数成员认证,确保数据保持一致。
-
容错性: 该组设计为容错。如果一个或多个服务器失败,剩余的服务器可以继续提供读和写请求。当故障的服务器恢复时,它会自动重新与组同步。
-
冲突解决: 在存在冲突事务的情况下,Group Replication使用投票机制来确定冲突事务的顺序。这有助于保持组内的一致状态。
-
与复制的兼容性: Group Replication与传统的MySQL异步复制兼容。这意味着您可以在同一环境中使用一些使用传统复制的服务器,而另一些使用Group Replication。
要实施Group Replication,通常需要配置MySQL实例,设置必要的安全凭据,并启动组。对于对高可用性、容错性和一致性要求至关重要的场景,它是一个强大的解决方案。
1)组复制的原理图如下:
2)组复制与传统复制的区别:
组复制引入了两个新的机制,Consensus和Certify,这两个机制共同确保了 Group Replication 中的数据一致性和高可用性。 Consensus 用于在组内达成一致的决策,而 Certify 用于确保提交的事务得到足够多的认证。
Consensus(共识),在组复制中,Consensus 指的是通过 Paxos 算法,确保组内成员就状态协商、Primary 节点选举、事务提交等关键决策达成一致的过程。Consensus 机制用于确保组内的所有成员就某个问题或决策达成一致意见。确保消息的全局有序和消息被半数以上的成员确认接受。
Certify(认证),是组复制的一种机制,用于确保事务在提交时,组内的大多数成员都已经接收并执行了这个事务。在提交事务时,Primary 节点会等待至少大多数成员的确认,确保事务得到了足够多的认证。简单来说,就是确保所有成员对于同一个事务要么都认证,要么全都认证失败,事务得到了足够多的认证后才会提交。
3)组复制的工作机制:
组复制由多个成员组成,组中每个成员可以独立执行事务(多主模式)。但是,所有读写事务只有在获得组批准后才会提交(只读事务可以不通过组内协调就能提交)。
Primary节点负责接收事务提交,并将这些事务广播给组内的其他成员,组中的所有成员要么接收事务,要么都不接收。并且都以相同的顺序接收同一组事务,并为事务建立一个全局总顺序。
在组复制中,并发执行的事务的冲突检测和解决与死锁处理类似,确保对同一行数据的并发更新不会导致数据不一致或冲突。如果在不同节点上的两个并发事务更新了相同的行,系统会根据一致性协议进行解决。通过 Paxos 算法确保对同一行数据的并发更新不会导致数据不一致。排序靠前的提交,排序靠后的事务可能需要回滚。
2 组复制使用场景
MySQL组复制提供了一个高可用性、高弹性、可靠的MySQL服务。通过将系统状态复制到一组服务器,组复制使您能够创建具有冗余的容错系统,组内的成员之间可以同时进行读写操作,并保持数据的一致性。即使一些组成员出现故障,只要不是全部或大多数,系统仍然可用。根据故障成员的数量,组的性能或可伸缩性可能会下降,但它仍然可用,保证了数据库服务的持续可用性。
以下是一些MySQL Group Replication的使用场景:
-
高可用性: Group Replication提供了高可用性的数据库解决方案。由于组内的每个成员都可以成为Primary节点,当某个节点发生故障时,系统可以通过重新选举来选择新的Primary节点,保证数据库服务的持续可用性。
!!!需要注意的是,尽管数据库服务是可用的,但在组成员意外退出的情况下,必须将连接到它的那些客户端重定向到故障转移到另一个组成员。 -
读写分离: 组内的每个成员都可以接收读和写操作,这使得可以在不同节点上进行读写操作,从而分担数据库负载,提高整体系统的读写性能。
-
弹性伸缩: 支持在运行时动态添加或移除节点,以适应业务负载的变化。这种弹性伸缩的能力使得数据库系统更加灵活和可调整。
-
故障转移: 在发生故障时,Group Replication可以自动进行故障转移。系统会重新选举新的Primary节点,确保写入操作的连续性。
-
实时数据分析: 在需要进行实时数据分析的场景中,可以利用Group Replication在多个节点上执行读操作,提高数据分析的性能。
-
维护和升级: 在维护数据库或进行升级时,可以在组内的一个节点上执行维护操作,而其他节点仍然可以提供服务。维护完成后,再将节点重新加入组。
3 单主模式和多主模式的区别
组复制有两种运行模式,一种是单主模式,一种是多主模式。这个模式是在整个组中设置的,由 group_replication_single_primary_mode
这个系统变量指定,而且在所有成员上必须保持一致。ON 表示单主模式,这也是默认的模式;OFF 表示多主模式。需要注意的是,不能在同一个组的成员中同时使用不同的模式,比如:一个成员配置在多主模式,而另一个成员在单一主模式下。
当组复制正在运行时,不能手动更改 group_replication_single_primary_mode
的值。
在MySQL 8.0.13之前的版本中,如果要更改组的模式,必须停止组复制并在所有成员上更改 group_replication_single_primary_mode
的值。然后进行一次完整的组重启(由 group_replication_bootstrap_group=ON
的服务器引导),以实施对新操作配置的更改。注意:不需要重新启动mysqld服务,只需要将组复制重新引导即可。
从MySQL 8.0.13开始,支持在线对组复制模式进行变更。使用 group_replication_switch_to_single_primary_mode()
和 group_replication_switch_to_multi_primary_mode()
这两个函数在组复制仍在运行时将组从一种模式切换到另一种模式。这两个函数会管理切换组模式的过程,并确保数据的安全性和一致性。
3.1 单主模式
在单主模式下(group_replication_single_primary_mode=ON),组内有一个primary节点,该节点被设置为读写模式,组中的所有其他成员(secondary节点)都被自动设置为只读模式(使用super_read_only=ON)。通常情况下,primary节点通常是引导该组的第一个节点,加入该复制组的所有其他secondary节点均需要从读写节点同步数据,并自动设置为只读模式。
在单一主模式下,组复制会强制只有一个节点作为可读写节点,其他节点均为只读,因此与多主模式相比,一致性检查可能不那么严格,DDL语句不需要额外小心处理。选项 group_replication_enforce_update_everywhere_checks
用于启用或禁用组的严格一致性检查。在部署单一主模式或将组更改为单一主模式时,必须将此系统变量设置为OFF。
被指定为primary节点的成员可能通过以下方式进行角色的更改:
- 有primary节点主动或意外离开组,将自动选举新的primary节点。
- 使用
group_replication_set_as_primary()
函数指定某个成员为新的primary节点。 - 使用
group_replication_switch_to_single_primary_mode()
函数将组复制模式从多主模式更改为单主模式,会自动选举新的primary节点。也可以您可以使用此函数指定新的primary节点。
上述介绍的两个非自动并更primary节点的函数,只支持所有复制组成员在MySQL8.0.13或更高版本时使用。当自动选举或手动指定新的primary节点时,它会自动设置为读写,其他组成员仍然保持为secondary节点,因此仍为只读,原理图如下:
当组中一个节点被选为新的primary节点时,可能存在已应用于旧primary节点但尚未应用于新primary节点已经变更了的数据积压。在消化了这部分积压的数据之前,会存在以下情况:
- 在新primary节点上的写事务可能会和之前的旧数据导致冲突,会造成回滚;
- 新primary节点上的只读事务可能导致读取到旧的数据。
MySQL提供了一种可以减小快速和慢速成员之间的差异,从而减少这种情况发生的可能性的方法,就是启用并适当调整组复制的流控制机制。
从MySQL8.0.14版本开始,可以使用 group_replication_consistency
系统变量来配置组的事务d的一致性级别,以防止上述由于事务积压导致的情况发生。设置为 BEFORE_ON_PRIMARY_FAILOVER
(或任何更高的一致性级别),在新选举的primary节点上保留新事务,直到将积压的事务全都应用完成后,才会接着应用在primary主节点上发起的事务。
如果组没有使用流控制和事务一致性保证,最好在重新将应用程序切换到新primary节点之前,应等待新primary节点应用其与复制相关的中继日志(已经通过冲突认证检测,但在relay log中还未来得及回放的日志)。
3.2 多主模式
在多主模式下(group_replication_single_primary_mode=OFF),所有成员都是primary节点。新节点加入组时都被设置为读写模式,并且可以处理写事务,即使它们是并发执行的。
如果一个成员停止接受写事务,例如组中的某个成员意外宕机了,连接到它的客户端可以被重定向或故障切换到任何其他处于读写模式的健康成员。下图说明了多主模式下故障转移的大致过程:
组复制是一种最终一致性的系统,就是说当传入的流量减缓或停止,所有组成员都具有相同的数据内容。在流量流动时,事务可能会在某些成员上外部化(客户端接收到新数据),而在其他成员上则可能较慢,特别是如果某些成员的写入吞吐量较低,从而可能导致性能差的节点上读取到旧数据。在多主模式下,较慢的成员还可能累积过多的待认证和应用的事务,增加了冲突和认证失败的风险。为了限制这些问题,可以激活并调整流控制机制,以最小化快速和慢速成员之间的差异。
从MySQL8.0.14开始,可以使用group_replication_consistency
系统变量来实现对组中的每个事务都有一致性保证。可以选择适合组工作负载和数据读写优先级的设置。同时,考虑到提高一致性对组复制性能的影响,还可以为单个会话设置该系统变量,用于保护特别是对并发敏感的事务。
事务检查:
当一个组以多主模式部署时,会对事务进行检查,以确保其与多主模式兼容。相关的严格一致性检查如下:
- 不允许将事务的隔离级别设置为SERIALIZABLE隔离级,否则在其与组同步时,将提交失败;
- 不支持外键约束,否则也将提交失败。
这些检查由 group_replication_enforce_update_everywhere_checks
系统变量控制。在多主模式下,此变量通常应设置为ON,但可以通过设置为OFF来选择性地取消激活这些检查。在部署单主模式时,此变量必须设置为OFF。
多主模式下DDL语句的注意点:
在多主模式的Group Replication拓扑结构中,执行数据定义语句(通常称为数据定义语言DDL)时需要特别注意。
MySQL8.0引入了对原子数据定义语言(DDL)语句的支持,其中完整的DDL语句作为单个原子事务被提交或回滚。DDL语句会隐式结束当前会话中活动的任何事务,相当于执行了COMMIT一样。这意味着DDL语句不能在另一个事务内执行,不能在事务控制语句(比如START TRANSACTION … COMMIT)内执行,也不能在同一事务内与其他语句组合执行。
在多主模式下复制DDL语句时需要更加小心。如果对同一对象进行模式更改(使用DDL)和该对象包含的数据的更改(使用DML),需要通过同一节点处理这些更改。否则,可能导致在操作被中断或仅部分完成时数据不一致。如果组部署在单一主模式下,则不会发生此问题,因为所有更改都是通过同一服务器(主服务器)执行的。
版本兼容性:
为了获得最佳的兼容性和性能,组中的所有成员应该运行在相同版本的MySQL Server,相同版本的组复制。在多主模式下,这更为重要,因为所有成员通常都会以读写模式加入组,如果一个组包含运行不同MySQL Server版本的成员,就有可能导致一些成员与其他成员不兼容,因为它们支持其他成员没有的功能,或者缺少其他成员拥有的功能。为了防范这种情况,在新成员加入组时(包括升级并重新启动的以前的成员),该成员会进行与组的其余部分的兼容性检查。
这些兼容性检查的一个重要结果在多主模式下尤为重要。如果加入组的成员运行的MySQL Server版本高于现有组成员运行的最低版本,它将加入组但仍保持为只读模式。(在单一主模式下运行的组中,新添加的成员在任何情况下默认为只读模式。)运行MySQL 8.0.17或更高版本的成员在检查兼容性时会考虑发布的补丁版本。运行MySQL 8.0.16或更低版本,或者MySQL 5.7的成员只考虑主版本。
在一个运行在多主模式下且成员使用不同MySQL Server版本的组中,组复制会自动管理运行MySQL 8.0.17或更高版本的成员的读写和只读状态。如果一个成员离开组,那么运行现在最低版本的版本的成员会被自动设置为读写模式。当使用 group_replication_switch_to_multi_primary_mode()
函数将运行在单主模式下的组切换到多主模式时,会自动设置成员的正确模式。如果成员运行的MySQL Server版本高于组中存在的最低版本,则它们会被自动放置在只读模式,而运行最低版本的成员会被放置在读写模式。
【关联文章】
1)MySQL组复制的介绍
2)MySQL单主模式部署组复制
3)MySQL组复制的管理