组复制MySQL Group Replication(简称MGR)是MySQL官方在已有的Binlog复制框架之上,基于Paxos协议实现的一种分布式复制形态。RDS MySQL集群系列实例支持组复制。本文介绍组复制的优势、技术实现原理、AliSQL对组复制稳定性的优化。
组复制的优势
组复制、半同步复制、异步复制的数据可靠性、数据一致性、全局事务一致性情况如下表所示。
特性 | 组复制 | 半同步复制 | 异步复制 |
数据可靠性 | ★★★★★ | ★★★ | ★ |
数据一致性 | 保证主备数据一致性 | 不保证 | 不保证 |
全局事务一致性 | 支持 | 不支持 | 不支持 |
数据强可靠性
组复制基于Paxos协议的多数派原则,确保数据可靠性。当多数派节点(指集群中超过半数的节点)接收到事务的Binlog后,事务才会提交。这保证了在多数派可用的情况下,任何少数派节点(集群中少于半数的节点)故障都不会导致数据丢失。
例如,5个节点的集群,3个节点收到Binlog,2个节点未收到Binlog,此时有2个节点故障:
即使2个故障节点是收到Binlog的节点,至少还有1个节点有数据。
如果故障的2个节点是没收到Binlog的节点,则至少有3个节点上有数据。
数据强一致性
组复制通过先传输事务到集群其他节点再写入Binlog的方式,确保主备节点数据一致性。旧主节点故障重启后,会自动加入集群并拉取缺失的Binlog,从而获得最新数据。
传统主备复制的问题:主节点在写入Binlog后、传输到备节点前发生故障,可能导致主备数据不一致。
全局事务强一致性
组复制支持全局事务强一致读和写能力,并可通过group_replication_consistency
参数调整一致性等级:
强一致读: 在备节点设置
group_replication_consistency=BEFORE
,查询时会等待主节点上所有先于该查询的事务完成后再执行,确保主备数据一致。强同步写: 在主节点设置
group_replication_consistency=AFTER
,写事务会在所有节点应用成功后才返回提交结果。
组复制的部署模式
多主模式(Multiple Leader):
所有节点均可读写,主要用于扩展写能力。依赖Paxos协议的多点写入和行级别的冲突检测,保证数据顺序一致。
缺点:但在多数派可用的情况下,任何节点故障都会导致短时间不可用。
单主模式(Single Leader):
集群中仅一个节点可写,其他节点只读。基于Paxos Single Leader实现,扩展读能力的同时保持高可用性。
当备节点故障时,只要多数派可用,就不会影响集群的可用性。
当主节点故障时,集群能够根据Paxos协议自主切换新主节点,保证数据强一致性。
RDS MySQL提供了单主模式的组复制实例,并对只读节点做了优化,在保证高可靠性和强一致性的同时提供更平滑的性能。
组复制的架构
在MySQL的Server层和Replica层之下,组复制分为三层:
组复制层(Group Replication Logic Layer):负责与Server层交互,向组通讯层发送、接收并回放事务。
组通讯层(Group Communication System Layer):负责消息传递、故障检测和集群成员管理。
XCom层(Paxos Layer):基于Paxos协议实现,确保数据顺序一致性和多数派可用性。
Paxos协议
Paxos协议在组复制中的作用包括:
确保集群中各节点收到数据的顺序一致,这是多主模式实现的基础。
确保多数派收到数据后事务才能提交,提升数据可靠性。
在Paxos协议中,使用锁的方式来实现节点间顺序一致性,这种方式存在一定的效率问题,并且还存在着负载不均衡的问题。在工程实现过程中,MySQL的XCom层基于Mencius协议(Paxos变种协议),通过轮询方式实现负载均衡,提升节点间效率。
多主模式实现原理
数据顺序: 每个组内数据发送是串行的,保证单组内顺序一致。多个组间通过轮询机制确保全局顺序,例如按 (1,1)、(1,2)、(1,3) 的顺序发送数据。
Noop机制: 如果某节点发现后续顺序号已完成Paxos过程且自身无数据发送,则广播Noop跳过该顺序号。每个节点需等待前序节点发送数据或Noop后才能继续。
缺陷: 当某节点故障或抖动时,既无法发送数据也无法发送Noop,导致后续节点无法发送数据,集群可能完全不可用。这是多主模式的主要缺陷。
图中(m,n)表示第n个组发出的第m条数据。例如,(2,1)表示第1个组发出的第2条数据。
单主模式实现原理
上文中提到的多主模式的缺陷可以优化,但无法从根源上避免。为此MySQL推出了组复制的单主模式,来解决少数派故障对集群可用性的影响。
上图是单主模式的XCom架构,由于只有一个节点可写,只需激活一个Paxos组。接收方的XCom在轮询数据时,会自动忽略其他Paxos组。这样,只要多数派可用,Paxos就能正常发送数据,集群的可用性不受影响。
在单主模式下,备节点不会发送事务数据,但有时需要发送一些集群管理信息。备节点在发送数据时,必须向主节点请求一个发送信息的位置,如上图中的<3, 1>,并使用这个位置向全集群发送自己的数据。这种发送方式效率低、时延高,但由于集群管理信息发送的频率很低,并不会对性能造成影响。
组复制层
组复制层负责向集群发送、接收和回放事务,主节点和备节点的工作原理如下:
主节点: 事务进入提交阶段时,其Binlog被发送到XCom层并传递给其他节点。多数派确认接收后,进行冲突检测:
检测成功:写入Binlog并提交事务。
检测失败:回滚事务。
备节点: 事务被多数派接收后,由XCom层传递至组复制层进行冲突检测:
检测成功:写入Relay Log并由Applier线程应用。
检测失败:丢弃事务数据。
冲突检测
场景
组复制在以下两种场景中需要进行冲突检测:
多主模式:所有写操作都需要冲突检测。
单主模式:切主时,若新主节点在应用完旧主的 Relay Log 前执行写事务,也需要冲突检测。
原理
冲突检测基于数据行的主键哈希值,采用行级检测机制。每个节点维护一个事务认证信息数组(哈希数组),其结构如下:
Key:数据行的哈希值。
Value:最近修改该行的事务GTID与源节点提交时的
gtid_executed
集合的并集。
当事务准备提交时:
源节点发送事务修改的数据及一个提交集合(标识当前事务提交前已完成的事务)。
集群内所有节点根据事务修改的相关行哈希值,从认证信息数组中读取对应的值,合并生成依赖集合(标识当前事务提交前必须完成的事务)。
在当前事务提交或写入Relay Log前,需要将上述两个集合进行比较:
如果提交集合包含了依赖集合,冲突检测成功,事务在源节点写入Binlog并提交,在其他节点写入Relay Log。
如果 提交集合不包含依赖集合,冲突检测失败,事务在源节点回滚,在其他节点丢弃Relay Log。
清理机制:
为节省内存空间,认证信息数组会定期清理无用数据:
当事务在所有节点上执行完毕后,其修改的行数据可从认证信息数组中移除。
组复制每60秒清理一次已执行事务的数据。
AliSQL对组复制稳定性的优化
尽管单主模式提升了组复制的稳定性,但在某些场景下仍存在问题。例如,当备节点延迟较大时,大量未及时应用的事务会导致认证信息堆积,影响系统稳定性:
占用过多内存,可能引发实例内存溢出(OOM)。
清理代价增加,进一步影响实例性能。
针对这些问题,AliSQL对认证信息清理进行了以下优化:
主节点优化: 主节点无需使用认证信息数组,因此完全移除该数组,消除其对资源和稳定性的潜在影响。
备节点优化: 仅在
group_replication_consistency=EVENTUAL
配置下保留认证信息。此配置下,备节点切为主节点后会立即对外提供服务,而不等待Relay Log回放完成,可能导致数据冲突。由于这种行为在生产环境中较少使用,禁止后可显著减少备节点的认证信息保留量,降低内存开销,提升集群稳定性。