组复制常见疑问 | 全方位认识 MySQL 8.0 Group Replication
一个组中MySQL Server(组成员)的最大数量是多少?
单个复制组中的允许组成员(MySQL Server)的最大数量是9个。如果有更多的Server尝试加入该组时,其连接请求将被拒绝。该限制数量是通过已有的测试案例和基准测试中得出的一个安全边界,在这个安全边界中,组能够安全、可靠、稳定地运行在一个稳定的局域网中。
组中的成员之间如何连接与通讯?
系统变量group_replication_bootstrap_group有什么用途?
指示启用该系统变量的Server在执行START GROUP_REPLICATION语句时引导创建一个组,并充当种子成员。后续的其他Server如果要加入组(加入组的Server在这里称为joiner成员),则需要向创建组的成员请求加入组(接受连接请求的组成员在这里称为donor节点),创建组的成员在接收到joiner节点请求之后,会动态更改一些配置,以便将其添加到组中。
有如下两种场景需要使用该系统变量来引导创建一个组:
* 在第一次创建组时,在第一个启动的Server中使用。
* 在完全重新启动整个组时,在第一个启动的Server中使用。
如何为分布式恢复过程设置凭据?
可以使用CHANGE MASTER TO语句预先配置组复制恢复通道的凭据(凭据指的是用户名和用户密码等)。
可以使用组复制来扩展写负载吗?
不直接扩展写负载。组复制是一个非共享的完整复制数据副本的解决方案,组中的所有成员都有一份完整的数据副本。因此,如果组中的一个成员提交一个事务向存储写入了N个字节,那么也将向组中其他成员的存储写入大约N个字节,因为组中一个成员中发起的事务,其产生的数据变更日志(二进制日志)会被复制到其他任意成员中并进行事务回放。但是,相对于事务发起的原始成员来说,其他通过二进制日志(row格式)实现事务同步的成员不需要执行事务的全过程(即,事务发起的原始成员和通过二进制日志同步事务的成员,在处理同一个事务的过程上有所不同),通过二进制日志来同步和回放的机制,意味着其接收到的数据包是经过优化的紧凑格式(可能存在着分段、打包、压缩处理),与原始成员相比,这可能会减少所需的IO操作数量,而且通过二进制日志格式回放的方式可以更快地应用事务对数据的更改(事务只需要回放row格式的二进制日志即可,而不需要完整重新执行事务的全过程)。
如果组使用多主模式,则可以将无冲突的事务分散到不同的主要节点中,这样就能够一定程度上扩展写负载能力(通过多节点写来扩展一小部分IO操作,能够间接扩展一小部分写负载)。
与简单复制(主从复制)相比,在相同的工作负载下,组复制是否需要更多的网络带宽和CPU ?
由于组成员之间需要不断地相互交互消息以实现同步数据和相互告知组成员状态的目的。因此,相对于主从复制来说,预计会产生一些额外的负载,但具体多多少负载很难量化,因为它还取决于组的大小(即,组成员数量。例如:9个组成员对带宽需求大于3个成员,且内存和CPU消息也更大,因为成员数量越多,组中消息传递和处理工作就越复杂)。
可以跨广域网部署组复制吗?
可以,但是每个成员之间的网络连接必须可靠并具有良好的性能,低延迟、高带宽的网络连接是保证组复制高性能的必要条件,如果网络带宽存在瓶颈,可以参考"6.3 消息压缩" 中介绍的方法来降低组复制的带宽消耗。但是,如果网络连接存在丢包的问题,可能导致重新传输造成更高的端到端延迟,这个时候,吞吐量和延迟都将受到负面影响。注意:当任何组成员之间的网络往返时间(RTT)超过5秒时,可能会触发内置的故障检测机制而导致组成员被驱逐出组(实际是否被驱逐出组,需要看具体的配置)。
如果出现临时的连接问题,成员会自动重新加入组吗?
这取决于连接发生问题的原因。如果连接问题是暂时的,并且重新连接的速度足够快(即,发生问题的时间很短),以至于故障检测器没有发现或者未达到故障级别,那么组成员可能就不会被驱逐出组。如果发生问题的时间足够长,则故障检测器最终会发现问题并将故障成员驱逐出组。
从MySQL 8.0版本开始,可以使用两个系统变量进行调节,这就为发生问题的组成员增加了一个继续留在组中或被驱逐出组之后重新加入组的机会:
* group_replication_member_expel_timeout:设置从怀疑的创建(在最初的5秒检测期之后发生)到成员被驱逐出组之间的间隔时间。最大支持3600秒(1个小时)的等待时间。
* group_replication_autorejoin_tries:设置一个组成员被驱逐出组或者与组中多数成员失联达到超时时间之后,尝试自动重新加入组的次数。设置该系统变量为非0值时,成员会按照该系统变量设置的次数每隔5分钟进行一次自动重新加入组的尝试。
如果一个成员被驱逐出组,并且耗尽了自动重新加入组的尝试次数都不能成功加入组,那么将会按照系统变量group_replication_exit_state_action指定的值执行退出操作。之后,如果需要将其重新加入组,你需要手动执行加入组的步骤(或者使用自动化运维脚本)。
什么时候会将一个组成员驱逐出组?
如果某个组成员变为静默状态(不主动发出组通讯消息,也不应答其他成员发送的组通讯消息),则其他组成员会将其从组配置中删除。实际场景中,当组成员发生崩溃或网络连接断开时可能会发生这种情况。
如果某个组成员在经过了给定的时间(这里指是系统变量group_replication_member_expel_timeout指定的时间值)之后还处于静默状态,则它将会被驱逐出组,组中的其他成员将会创建一个新的组配置(新的组成员资格)。
当一个组成员明显落后于组时会发生什么?
在默认的配置下,当一个成员明显落后于组时,可能会触发流量控制,进而拖慢整个组。在发生流量控制时并没有能够自动将成员从组中驱逐出组的策略,也并没有相应的系统变量进行配置,但流量控制阈值可以根据需要自行调整来缓解流量控制。
当怀疑组中存在问题时,是否有特定的组成员负责触发组的重新配置?
没有,组中的任何成员都可能被怀疑存在问题(没有哪个成员可以保证不出问题)。当一个组成员发生失败且被组中其他所有成员一致同意时,则该成员就会被驱逐出组,且触发组的自动重新配置,无法人为控制或设置某个成员来负责将该失败的成员驱逐出组。
组复制可以用于数据分片环境吗?
组复制的目的是提供高可用的副本集,组中的每个成员都拥有相同的数据,写操作会在组中的所有成员上进行同步(即,组中的不同成员之间的数据是一致的,同一个组中,只有同一份数据但拥有多个副本)。因此,如果要通过数据分片来扩展数据库的写服务能力,需要将数据分散到多个复制组中,然后,构建一个围绕多个复制组的数据分片架构,其中每个复制组只维护和管理整个数据集的给定分片或分区(例如:4个数据分片,每一个数据分片都使用一个单独的复制组来承载)。这种类型的设置,通常称为“分片集群”。这样,就实现了对读写服务能力的线性扩展,且不受限制。
如何在启用SELinux的环境中使用组复制?
如果启用了SELinux(是否启用可以使用sestatus -v命令进行检查),则需要开放由系统变量group_replication_local_address配置的组复制通信端口的通讯,以便mysqld进程在启动时能够绑定并监听该端口。要查看MySQL当前允许使用哪些端口,可以执行"semanage port -l | grep mysqld"命令进行查看。如果发现配置的组通讯端口不在查询结果中,则你需要将其添加到SELinux允许的端口列表中。例如:通过命令"semanage port -a -t mysqld_port_t -p tcp 33061"可以将33061端口添加到SELinux允许的端口列表中。
如何在启用了iptables的环境中使用组复制?
如果启用了iptables,那么需要在iptables允许访问的规则中开放组复制相关的端口,以便组成员之间能够进行正常的组通信。可以在每个组成员的服务器中执行"iptables -L"命令查看当前生效的防火墙规则。如果发现配置的组通讯端口不在查询结果中,则你需要将其添加到iptables允许的访问规则中。例如:通过命令"iptables -A INPUT -p tcp --dport 33061 -j ACCEPT" 可以将33061端口添加到被允许的防火墙规则中。
如何恢复组成员使用的复制通道的中继日志?
组复制使用的复制通道的行为与主从复制使用的复制通道相同(组复制是基于主从复制的基础架构上实现的),因此组复制依赖于中继日志。如果修改了系统变量relay_log的值、或者未显式设置该系统变量的值时主机名发生了变化,那么组复制通道大概率可能出现错误。如果出现这种情况,可以使用如下两种方式尝试解决:
* 停止出现问题的组成员的组复制通道,然后,将旧的中继日志索引文件的内容预先添加到新的中继日志索引文件中,然后,重新启动组复制通道(这种方法其实是在主从复制拓扑中,中继日志出现名称问题时的解决方法,在组复制中,建议使用第二种方法)。
* 使用STOP GROUP_REPLICATION语句停止组复制通道,然后直接执行START GROUP_REPLICATION语句来重新启动组复制通道。组复制插件会自动重新创建新的group_replication_applier通道。
为什么组复制中的自增变量默认设置值改变了?
在一个Server中启动组复制时,其系统变量auto_increment_increment的值会被自动修改为系统变量group_replication_auto_increment_increment的值,默认为7,系统变量auto_increment_offset的值被自动修改为Server ID。当组复制正常停止时,自动修改的的值会被还原为原始值。自动设置自增值避免了人工为组成员设置自增值时,不小心设置了相同的自增值导致写操作被回滚的风险。默认值7是在组复制最大成员数量(9个成员)基础上的一个均衡值。
注意:只有当系统变量auto_increment_increment和auto_increment_offset保持默认值时,才会按照上述规则对自增值执行自动修改与恢复操作。否则,组复制不会自动修改。从MySQL 8.0开始,当组复制处于单主模式时(只有一个主要节点可提供写操作),组复制也不会自动修改自增。
怎么找到主要节点(primary节点)?
如果组运行在单主模式,那么就需要查找哪个成员是主要节点(多主模式下,所有成员都是主要节点)。详情可参考"1.3.1.2. 找出主要节点"。
罗小波·数据库技术专家
全文完。
Enjoy MySQL 8.0 :)
叶老师的「MySQL核心优化」大课已升级到MySQL 8.0,扫码开启MySQL 8.0修行之旅吧