故障检测(Failure Detection)是 Group Replication 的一个核心功能模块,通过它可以及时识别集群中的故障节点,并将故障节点从集群中剔除掉。如果不将故障节点及时剔除的话,一方面会影响集群的性能,另一方面还会阻止集群拓扑的变更。
下面结合一个具体的案例,分析 Group Replication 的故障检测流程。
除此之外,本文还会分析以下问题。
- 当出现网络分区时,对于少数派节点,会有什么影响?
- 什么是 XCom Cache?如何预估 XCom Cache 的大小?
- 在线上,为什么 group_replication_member_expel_timeout 不宜设置过大?
案例
以下是测试集群的拓扑,多主模式。
主机名 | IP | 角色 |
node1 | 192.168.244.10 | PRIMARY |
node2 | 192.168.244.20 | PRIMARY |
node3 | 192.168.244.30 | PRIMARY |
本次测试主要包括两步:
- 模拟网络分区,看它对集群各节点的影响。
- 恢复网络连接,看看各节点又是如何反应的。
模拟网络分区
首先模拟网络分区故障,在 node3 上执行。
其中,iptables 命令会断开 node3 与 node1、node2 之间的网络连接。date 记录了命令执行的时间。
命令执行完 5s(这个时间是固定的,在源码中通过 DETECTOR_LIVE_TIMEOUT 指定),各个节点开始响应(从各节点的日志中可以观察到这一点)
首先看看 node1 的日志及集群状态。
从 node1,node2 的角度来看,此时 node3 处于 UNREACHABLE 状态。
接下来看看 node3 的。
从 node3 的角度来看,此时 node1,node2 处于 UNREACHABLE 状态。
三个节点,只有一个节点处于 ONLINE 状态,不满足组复制的多数派原则。此时,node3 只能查询,写操作会被阻塞。
又过了 16s(这里的 16s,实际上与 group_replication_member_expel_timeout 参数有关),node1、node2 会将 node3 驱逐出(expel)集群。此时,集群只有两个节点组成。
看看 node1 的日志及集群状态。
再来看看 node3 的,日志没有新的输出,节点状态也没变化。
恢复网络连接
接下来我们恢复 node3 与 node1、node2 之间的网络连接。
首先看看 node3 的日志
日志的输出包括两部分,以空格为分界线。
1. 当网络连接恢复后,node3 与 node1、node2 重新建立起了连接,发现自己已经被集群驱逐,于是节点进入到 ERROR 状态。
节点进入到 ERROR 状态,会自动设置为只读,即日志中看到的 super_read_only=ON。注意,ERROR 状态的节点设置为只读是默认行为,与后面提到的 group_replication_exit_state_action 参数无关。
2. 如果group_replication_autorejoin_tries不为 0,对于 ERROR 状态的节点,会自动重试,重新加入集群(auto-rejoin)。重试的次数由 group_replication_autorejoin_tries 决定,从 MySQL 8.0.21 开始,默认为 3。重试的时间间隔是 5min。重试成功后,会进入到分布式恢复阶段。
接下来看看 node1 的日志。
node3 又重新加入到集群中。
故障检测流程
结合上面的案例,我们来看看 Group Repliction 的故障检测流程。
集群中每个节点都会定期(每秒 1 次)向其它节点发送心跳信息。如果在 5s 内(固定值,无参数调整)没有收到其它节点的心跳信息,则会将该节点标记为可疑节点,同时会将该节点的状态设置为 UNREACHABLE 。如果集群中有等于或超过 1/2 的节点显示为 UNREACHABLE ,则该集群不能对外提供写服务。
如果在group_replication_member_expel_timeout(从 MySQL 8.0.21 开始,该参数的默认值为 5,单位 s,最大可设置值为3600,即 1 小时)时间内,可疑节点恢复正常,则会直接应用 XCom Cache 中的消息。XCom Cache 的大小由group_replication_message_cache_size 决定,默认是 1G。
如果在group_replication_member_expel_timeout时间内,可疑节点没有恢复正常,则会被驱逐出集群。
而少数派节点呢,不会自动离开集群,它会一直维持当前的状态,直到:
- 网络恢复正常。
- 达到 group_replication_unreachable_majority_timeout 的限制。注意,该参数的起始计算时间是连接断开 5s 之后,不是可疑节点被驱逐出集群的时间。该参数默认为 0。
无论哪种情况,都会触发:
节点状态从 ONLINE 切换到 ERROR 。
回滚当前被阻塞的写操作。
ERROR 状态的节点会自动设置为只读。
如果group_replication_autorejoin_tries不为 0,对于 ERROR 状态的节点,会自动重试,重新加入集群(auto-rejoin)。
如果group_replication_autorejoin_tries为 0 或重试失败,则会执行 group_replication_exit_state_action 指定的操作。可选的操作有:
READ_ONLY:只读模式。在这种模式下,会将 super_read_only 设置为 ON。默认值。
OFFLINE_MODE:离线模式。在这种模式下,会将 offline_mode 和 super_read_only 设置为 ON,此时,只有CONNECTION_ADMIN(SUPER)权限的用户才能登陆,普通用户不能登录。
ABORT_SERVER:关闭实例。
XCom Cache
XCom Cache 是 XCom 使用的消息缓存,用来缓存集群节点之间交换的消息。缓存的消息是共识协议的一部分。如果网络不稳定,可能会出现节点失联的情况。
如果节点在一定时间(由 group_replication_member_expel_timeout 决定)内恢复正常,它会首先应用 XCom Cache 中的消息。如果 XCom Cache 没有它需要的所有消息,这个节点会被驱逐出集群。驱逐出集群后,如果 group_replication_autorejoin_tries 不为 0,它会重新加入集群(auto-rejoin)。
重新加入集群会使用 Distributed Recovery 补齐差异数据。相比较直接使用 XCom Cache 中的消息,通过 Distributed Recovery 加入集群需要的时间相对较长,过程也较复杂,并且集群的性能也会受到影响。
所以,我们在设置 XCom Cache 的大小时,需预估 group_replication_member_expel_timeout + 5s 这段时间内的内存使用量。如何预估,后面会介绍相关的系统表。
下面我们模拟下 XCom Cache 不足的场景。
1. 将group_replication_message_cache_size调整为最小值(128 MB),重启组复制使其生效。
2. 将group_replication_member_expel_timeout调整为 3600。这样,我们才有充足的时间进行测试。
3. 断开 node3 与node1、node2 之间的网络连接。
4. 反复执行大事务。
5. 观察错误日志。
如果 node1 或 node2 的错误日志中提示以下信息,则意味着 node3 需要的消息已经从 XCom Cache 中逐出了。
6. 查看系统表。
除了错误日志,我们还可以通过系统表来判断 XCom Cache 的使用情况。
其中,
- COUNT_ALLOC:缓存过的消息数量。
- COUNT_FREE:从缓存中删除的消息数量。
- CURRENT_COUNT_USED:当前正在缓存的消息数量,等于 COUNT_ALLOC - COUNT_FREE。
- SUM_NUMBER_OF_BYTES_ALLOC:分配的内存大小。
- SUM_NUMBER_OF_BYTES_FREE:被释放的内存大小。
- CURRENT_NUMBER_OF_BYTES_USED:当前正在使用的内存大小,等于 SUM_NUMBER_OF_BYTES_ALLOC - SUM_NUMBER_OF_BYTES_FREE。
- LOW_COUNT_USED,HIGH_COUNT_USED:CURRENT_COUNT_USED 的历史最小值和最大值。
- LOW_NUMBER_OF_BYTES_USED,HIGH_NUMBER_OF_BYTES_USED:CURRENT_NUMBER_OF_BYTES_USED 的历史最小值和最大值。
如果断开连接之后,在反复执行大事务的过程中,发现 COUNT_FREE 发生了变化,同样意味着 node3 需要的消息已经从 XCom Cache 中驱逐了。
7. 恢复 node3 与 node1、node2 之间的网络连接。
在 group_replication_member_expel_timeout 期间,网络恢复了,而 node3 需要的消息在 XCom Cache 中不存在了,则 node3 同样会被驱逐出集群。以下是这种场景下 node3 的错误日志。
注意事项
如果集群中存在 UNREACHABLE 的节点,会有以下限制和不足:
- 不能调整集群的拓扑,包括添加和删除节点。
- 在单主模式下,如果 Primary 节点出现故障了,无法选择新主。
- 如果 Group Replication 的一致性级别等于 AFTER 或 BEFORE_AND_AFTER,则写操作会一直等待,直到 UNREACHABLE 节点 ONLINE 并应用该操作。
- 集群吞吐量会下降。如果是单主模式,可将 group_replication_paxos_single_leader (MySQL 8.0.27 引入的)设置为 ON 解决这个问题。
所以,在线上 group_replication_member_expel_timeout 不宜设置过大。
参考资料
[1] Extending replication instrumentation: account for memory used in XCom
[2] MySQL Group Replication - Default response to network partitions has changed
[3] No Ping Will Tear Us Apart - Enabling member auto-rejoin in Group Replication
标签:
留言评论