15. 故障检测与网络分区 | 深入浅出MGR

2023-02-23 11:10:44 浏览数 (1)

* GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源。

  • 1. 故障检测
  • 2. 少数派成员失联时
  • 3. 多数派成员失联时
  • 4. Xcom cache
  • 5. 网络分区
  • 6. 小结
  • 参考资料、文档
  • 免责声明
  • 加入团队

本文介绍MGR的故障检测机制,以及发生网络分区后如何处理。

1. 故障检测

当MGR中个别节点与其他节点通信异常时,就会触发故障检测机制,经过多数派节点投票判断后再决定是否将其驱逐出MGR。

发生故障时,只有当多数派节点存活前提下,故障检测机制才能工作正常,使得MGR恢复可用性;当多数派节点本身已经异常的时候,MGR是无法自行恢复的,需要人为介入。

MGR中,各节点间会定期交换消息,当超过5秒(在MySQL中是固定5秒,在GreatSQL中新增选项group_replication_communication_flp_timeout可配置)还没收到某个节点的任何消息时,就会将这个节点标记为可疑状态。MGR各正常存活节点会对可疑节点每隔15秒检测一次(在GreatSQL中,调整为每隔2秒检测,效率更高,下面再介绍),当确认可疑节点在超过group_replication_member_expel_timeout秒超时阈值后,再将该节点驱逐出MGR。

需要注意的是,选项group_replication_member_expel_timeout从MySQL 8.0.21开始,默认值为5。在MySQL 8.0.21之前,默认值为0。在 <= MySQL 8.0.20 的版本中,group_replication_member_expel_timeout默认值为 0,也就是当某节点被判定为可疑状态后,会被立即驱逐。在MySQL 5.7中,没有该选项,行为模式也是一样的。

在MySQL中,MGR故障检测是由独立线程来完成的,该线程每隔15秒(MySQL在源码中硬编码定义了SUSPICION_PROCESSING_THREAD_PERIOD = 15)进行一次检查。因此,节点发生故障时,极端情况下,可能要耗费 5(5秒没发送消息,被判定为可疑节点) 15(SUSPICION_PROCESSING_THREAD_PERIOD) 5(group_replication_member_expel_timeout) = 25秒 才能驱逐该节点。最好的情况下,最快 5 5 = 10秒 后即可驱逐该节点。

在GreatSQL中对此进行了优化,新增选项group_replication_communication_flp_timeout(默认值5,最小3,最大60) 用于定义节点超过多少秒没发消息会被判定为可疑。此外,还修改了硬编码SUSPICION_PROCESSING_THREAD_PERIOD = 2,也就是故障检测线程每2秒(而非15秒)就会检查一次。因此在GreatSQL中,最快5(group_replication_communication_flp_timeout) 5(group_replication_member_expel_timeout) = 10秒完成驱逐,最慢5 5 2(SUSPICION_PROCESSING_THREAD_PERIOD) = 12秒完成驱逐。

在网络条件不好的情况下,建议适当加大 group_replication_member_expel_timeout 值,避免网络波动造成节点频繁被驱逐。不过也要注意另一个风险,见这篇文章所述:技术分享 | 为什么MGR一致性模式不推荐AFTER

存活的节点会把被驱逐的节点从成员列表中删除,但被驱逐的节点自身可能还没“意识”到(可能只是因为临时短时间的网络异常),在状态恢复后,该节点会先收到一条包含该节点已被驱逐出MGR的新视图信息,而后再重新加入MGR。被驱逐的节点会尝试group_replication_autorejoin_tries次重新加入MGR。

选项group_replication_exit_state_action定义了被驱逐节点之后的行为模式,默认是设置为super_read_only = ON,进入只读模式。

2. 少数派成员失联时

当集群中的少数派成员失联时(Unreachable),默认不会自动退出MGR集群。这时可以设置group_replication_unreachable_majority_timeout,当少数派节点和多数派节点失联超过该阈值时,少数派节点就会自动退出MGR集群。如果设置为0,则会立即退出,而不再等待。节点退出集群时,相应的事务会被回滚,然后节点状态变成ERROR,并执行选项group_replication_exit_state_action定义的后续行为模式。如果设置了group_replication_autorejoin_tries,也会再自动尝试重新加入MGR集群。

3. 多数派成员失联时

当多数派节点也失联时(Unreachable),例如在一个3节点的MGR集群中,有2个节点失联了,剩下的1个节点不能成为多数派,也就无法对新事务请求做出决策,这种情况就是发生了网络分区(脑裂)。也就是一个MGR集群分裂成两个或多个区域,也因此缺少多数派,这种情况下,MGR集群无法提供写入服务。

此时需要人工介入,通过设置group_replication_force_members强行指定新的成员列表。例如MGR集群由3个节点组成,其中两个节点都意外失联了,仅剩一个节点存活,此时就需要手动设置group_replication_force_members强行指定成员列表,也就是只有最后存活的节点。

两个重要提醒:

使用该方法基本上是最后迫不得已的选择,因此需要非常谨慎。若使用不当,可能会造成一个人为的脑裂场景,或者造成整个系统被完全阻塞。也有可能会选错新的节点列表。 强制设定新的节点列表并解除MGR阻塞后,记得再将该选项值清空,否则无法再次执行START GROUP_REPLICATION。

4. Xcom cache

当有节点处于可疑状态时,在它被确定踢出MGR集群之前,事务会缓存在其他节点的Xcom cache中。这个cache对应选项group_replication_message_cache_size。当可疑节点短时内又恢复后,就会先从Xcom cache中读取记录进行恢复,然后再进行分布式恢复。因此,在网络不太稳定并发事务较大,且物理内存也足够的场景里,可以适当加大Xcom cache size;反之,在物理内存较小,或者网络较为稳定的场景里,不应设置太大,降低发生OOM的风险。

在MySQL 5.7里,Xcom cache size最大值1G,且不可动态调整。从MySQL 8.0开始,可对其动态调整。在 <= MySQL 8.0.20的版本中,最小值1G。在>= MySQL 8.0.21的版本中,最小值128M。

可以执行下面的SQL查看当前Xcom cache消耗情况:

代码语言:javascript复制
[root@GreatSQL]> SELECT * FROM performance_schema.memory_summary_global_by_event_name
  WHERE EVENT_NAME LIKE ‘memory/group_rpl/GCS_XCom::xcom_cache';

在MySQL中,是动态按需分配Xcom cache的,如果太多有空闲,就释放;如果不够用,再动态分配更多内存,一次分配大概250000个cache item,很容易造成约150ms的响应延迟。也就是说,会随着事务多少的变化而可能频繁产生响应延迟。

在GreatSQL中,对Xcom cache采用了静态化分配机制,即一开始就预分配约1GB内存用于xcom cache,这可以避免前面提到的响应延迟抖动风险,不过“副作用”是mysqld进程所占用的内存会比原来多,在内存特别紧张的服务器上不太适合。

5. 网络分区

在MGR里,事务是需要经过多数派节点达成一致性共识(要么都提交,要么都回滚)。同样的,前面提到的节点间通信消息也是需要在多数派节点间达成共识。当MGR中的多数派节点失联时,就无法就此形成共识,也无法满足多数派投票/仲裁要求,此时MGR将拒绝写事务请求。这种情况,也称为网络分区,及一个MGR集群分裂成两个或多个分区,彼此间相互无法连通,任何一个分区中的节点都不能达成多数派。

可能Primary节点会因为网络分区时被踢出MGR集群,它在重新加回时,可能会因为本地有此前还没来得及同步到其他节点的事务,而造成本地有更多事务,会报告类似下面的错误:

代码语言:javascript复制
This member has more executed transactions than those present in the group. Local transactions: xx:1-300917674 > Group transactions: xx:1-300917669

此时需要人工介入处理,选择哪个节点作为最新的Primary节点。

6. 小结

本文介绍了MGR的故障检测机制、Xcom cache,什么是网络分区,以及发生故障时都有什么影响,如何恢复故障等。

参考资料、文档

  • MySQL 8.0 Reference Manual(https://dev.mysql.com/doc/refman/8.0/en/group-replication.html)
  • 数据库内核开发 - 温正湖(https://www.zhihu.com/column/c_206071340)
  • Group Replication原理 - 宋利兵(https://mp.weixin.qq.com/s/1iO-KISAU1HLSzEVLrxG9g)

免责声明

因个人水平有限,专栏中难免存在错漏之处,请勿直接复制文档中的命令、方法直接应用于线上生产环境。请读者们务必先充分理解并在测试环境验证通过后方可正式实施,避免造成生产环境的破坏或损害。

加入团队

如果您有兴趣一起加入协作,欢迎联系我们,可直接提交PR,或者将内容以markdown的格式发送到邮箱:greatsql@greatdb.com。

Enjoy GreatSQL :)


《零基础学习MySQL》视频课程

戳此小程序即可直达B站

https://www.bilibili.com/video/BV1Da411W7Va?spm_id_from=333.999.0.0&vd_source=ae1951b64ea7b9e6ba11f1d0bbcff0e4


文章推荐:

  • 活动 | 开源项目成熟度评测 入选开源社区成员 GreatSQL社区闪耀OSCAR 2022开源产业大会
  • 从join的实现窥探MySQL迭代器
  • GreatSQL vs MySQL性能测试来了,速围观~
  • 如何干涉MySQL优化器使用hash join?
  • LIMIT和OFFSET分页性能差!今天来介绍如何高性能分页

关于 GreatSQL

GreatSQL是由万里数据库维护的MySQL分支,专注于提升MGR可靠性及性能,支持InnoDB并行查询特性,是适用于金融级应用的MySQL分支版本。

GreatSQL社区官网: https://greatsql.cn/

Gitee: https://gitee.com/GreatSQL/GreatSQL

GitHub: https://github.com/GreatSQL/GreatSQL

Bilibili:

https://space.bilibili.com/1363850082/video

0 人点赞