到MySQL8.0.21为止, MGR已经有了一套完整的错误响应机制。这套机制由三部分构成:

  1. 故障探测(Failure Detection)

    当任何节点因故障或者网络分裂无法响应其他节点时,MGR能够识别出发生故障的节点。

  2. 移除故障节点(Expel Member)

    将故障节点从集群中移除出去。

  3. 自动重新加入(Auto-Rejoin)

    当故障消除后,恢复的节点能够知道自己被移除了,并且自动加入集群中。


故障探测(Failure Detection)

故障探测是由xcom(MGR的Paxos实现)完成的。

  • detected time

    xcom在每次成功的发送数据到某节点或者从某个节点接收到数据时都会记录当前时间(detected time)。意味着这个节点在当前时间还活着。

  • alive_task()

    alive_task做两件事情:

  1. 在节点空闲了0.5秒后,alive_task()会发送i_am_alive_op消息给其他节点。空闲是指0.5秒内没有发送任何消息出去。

  2. 当某个节点4秒内没有任何通信时(代码中称作may_be_dead),发送are_you_alive_op消息给这个节点,去探查该节点是否还活着。

detector_task()

每1秒做一轮检查。检查节点是否还活着。判断的标准是:

detected_time > task_now() - 5.0
  • 即5秒内没有和这个节点通信。如果此节点的detected time在5秒之内,则为活着,否则认为该节点可能已经死去。


当detector_task()发现任何节点的状态发生了变化:

  • 从活着变成可能死了

  • 从可能死了变成活着

都会通过local view回调函数xcom_receive_local_view来处理状态变化。状态的变化由GCS模块处理。


开除成员(Expel Member)

开除成员的流程由Gcs_suspicions_manager实现。Gcs_suspicions_manager两个重要的元素:

  • 疑似死亡节点列表

  • 移除死亡节点的线程


开除成员分为两个步骤

  • 设置疑似死亡状态(suspicious)

    前面说了xcom通过回调函数将处理权交给GCS模块。Gcs_suspicions_manager将可能已经死亡节点加入到疑似死亡节点列表中. 同时将这些节点的状态设置为UNREACHABLE。从replication_group_members表可以查询到节点的状态。

  • 移除故障节点

    当节点疑似死亡超过一定时间后,Gcs_suspicions_manager的处理线程会发送移除指令给XCOM,将该节点从集群中移除出去。这个时间通过group_replication_member_expel_timeout设置。所以一个节点从故障发生到从组内移除出去总时间是:

    group_replication_member_expel_timeout + 5(秒)


谁来执行移除故障节点的指令

当一个节点发生故障时,其他的节点可能同时检测到故障。如果同时发出移除指令,不会产生问题,但是效率不高。MGR定了一个规则,按照节点加入集群的顺序,由第一个还活着的节点来执行移除指令。


移除故障节点的真正含义

移除节点意味着集群中的节点数减少,因此可能导致集群的可靠性降低。


举个例子,假设一个集群有5个节点。MGR保证数据复制到至少3个节点上。当2个节点发生故障并被自动移除出集群后,集群中就只有3个节点了,MGR保证数据被复制到至少2个节点上。因此集群的可靠性就退化了。


当移除故障节点时,要求至少有半数以上的节点活着。所以当集群中只有两个节点时,故障的节点不会被移除出去。好在大多数的使用场景下,都是3个节点,因此大多数场景下可靠性不会退化。


自动重新加入(Auto-Rejoin)

当故障节点恢复后,会发现自己被移除出了集群。这时,这个节点会尝试自动加入集群。自动加入集群的过程和START GROUP REPLICATION不同。这个过程不需要做全局恢复(Global Recovery)。全局恢复需要通过group_replication_recovery异步通道复制加入集群前的数据。而自动加入时,所有的数据都是通过XCOM复制,包括加入前的数据。


XCOM数据缓存

和自动加入功能紧密相关的一个参数是group_replication_message_cache_size. 它定义了XCOM数据缓存的大小。当缓存无法保存所有数据时,就会将老的数据清除掉。如果缓存太小或者节点故障的时间过长,可能会导致一部分数据无法通过XCOM复制的情况发生。这时自动加入就会失败,必须要通过START GROUP REPLICATION 方式加入集群。


终极疑问

读到这里,你可能要有疑问了:为什么要设计一个自动移除、自动加入的过程呢?如果故障的节点不超过半数,不影响集群的可用性。仍然将这些故障的节点保留在集群中不可以吗?


当然是可以的,但是XCOM的实现上还不够完美。任何节点的故障,都会明显降低集群的性能。如果一个节点故障的时间很长,最好还是从集群中移除出去,从而避免集群性能下降。XCOM的实现细节,会在后续的文章中介绍。