1. Group Replication
组复制是一种可用于实现容错系统的技术。复制组是一组服务器,每个服务器都有一个完整的数据副本(无共享复制方案),它们通过消息传递相互交互。通信层提供了一组保证。
复制组由多个服务器组成;组中的每个服务器可以在任何时候独立执行事务。读/写事务只有在组批准后才能提交。换句话说,对于任何读/写事务,组都需要决定是否提交,因此提交操作不是源服务器的单方面决定。只读事务不需要在组内进行协调,并立即提交。
当读/写事务准备在发起服务器上提交时,服务器会自动广播写值(更改的行)和相应的写集(更新的行的唯一标识符)。因为事务是通过原子广播发送的,所以组中的所有服务器要么都接收到事务,要么都没有接收到。如果它们接收到了事务,那么它们都会按照与之前发送的其他事务相同的顺序接收它。因此,所有服务器都以相同的顺序接收相同的事务集,并为这些事务建立全局总顺序。
但是,在不同服务器上并发执行的事务之间可能存在冲突。在称为认证的过程中,通过检查和比较两个不同并发事务的写入集来检测此类冲突。在认证过程中,冲突检测是在行级别进行的:如果在不同服务器上执行的两个并发事务更新了同一行,则存在冲突。冲突解决过程规定,首先订购的事务在所有服务器上提交,然后订购的第二个事务中止,因此在发起服务器上回滚,并由组中的其他服务器丢弃。例如,如果t1和t2在不同的位置同时执行,都改变了同一行,并且t2的顺序在t1之前,那么t2赢得了冲突,t1被回滚。这实际上是一个分布式的首次提交获胜规则。请注意,如果两个事务经常发生冲突,那么最好在同一台服务器上启动它们,这样它们就有机会在本地锁管理器上同步,而不是因为认证而回滚。
为了应用和外部化经过认证的事务,如果不破坏一致性和有效性,组复制允许服务器偏离商定的事务顺序。
2. Group Replication架构
MySQL Group Replication 是一个 MySQL 插件,它建立在MySQL复制基础架构,例如利用二进制日志、基于行的日志记录和全局事务标识符。它与当前的 MySQL集成框架,例如性能架构或插件和服务架构。下图显示框图描述了 MySQL Group Replication 的整体架构。
MySQL Group Replication 插件包括一组 API capture、apply 和 lifecycle,它们控制插件的方式 与 MySQL Server 交互。在一个方向上,从服务器到插件,会有关于服务器启动、服务器恢复、服务器准备接受连接以及服务器即将提交事务等事件的通知。在另一个方向上,插件指示服务器执行诸如提交或中止正在进行的事务,或在中继日志中排队事务等操作。
组复制插件架构的下一层是一组组件,当通知路由到它们时,这些组件会做出反应。捕获组件负责跟踪与正在执行的事务相关的上下文。应用程序组件负责在数据库上执行远程事务。恢复组件管理分布式恢复,并负责通过选择捐赠者、管理追赶过程和对供体失败做出反应,使加入组的服务器保持最新状态。
复制协议模块包含复制协议的特定逻辑。它处理冲突检测,并接收事务并将其传播到组。
组复制插件体系结构的最后两层是组通信系统(GCS)API和基于Paxos的组通信引擎(XCom)的实现。GCS API是一个高级API,它抽象了构建复制状态机所需的属性。因此,它将消息传递层的实现与插件的其余上层解耦。组通信引擎处理与复制组成员的通信。
3. Group Replication 使用场景
- 弹性复制
需要非常流畅的复制基础架构的环境,其中服务器的数量必须动态增长或减少,并且副作用尽可能少。例如,云数据库服务。
2. 高可用碎片
碎片化是实现大规模写入的一种流行方法。使用MySQL Group Replication实现高可用分片,其中每个分片映射到一个复制组。
3. 异步源副本复制的替代方案
在某些情况下,使用单个源服务器会使其成为单点争用。在某些情况下,向整个团队写作可能被证明更具可扩展性。
4. 自主系统
可以纯粹为复制协议中内置的自动化部署MySQL组复制。
4. 单主和多主模式
组复制在单主模式或多主模式下运行。组的模式是组范围的配置设置,由group_replication_single_primary_mode系统变量指定,该变量在所有成员上必须相同。ON表示单主模式,这是默认模式,OFF表示多主模式。在组复制运行时,您无法手动更改group_replication_single_primary_mode的值。您可以使用group_replication_switch_to_sile_primary_mode()和group_replication_sitch_to_multi_primary_mode()函数在组复制仍在运行时将组从一种模式移动到另一种模式。这些功能管理更改组模式的过程,并确保数据的安全性和一致性。
无论部署模式如何,组复制都不处理客户端故障转移。这必须由MySQL Router 代理、连接器或应用程序本身等中间件框架来处理。
5. 单主模式
在单主模式中 (group_replication_single_primary_mode=开) 该组具有设置为读/写的单个主服务器 模式。组中的所有其他成员都设置为只读 模式(super_read_only=ON)。 主数据库通常引导整个组。所有其他 加入组的服务器了解主服务器和 自动设置为只读模式。
在单主模式下,组复制强制只有一台服务器写入组,因此与多主模式相比,一致性检查可以不那么严格,DDL语句也不需要特别小心处理。选项group_replication_enforce_update_everywhere _checks启用或禁用组的严格一致性检查。在单主模式下部署或将组更改为单主模式时,此系统变量必须设置为OFF。
在单主模式下,组复制强制只有一台服务器写入组,因此与多主模式相比,一致性检查可以不那么严格,DDL语句也不需要特别小心处理。选项group_replication_enforce_update_everywhere _checks启用或禁用组的严格一致性检查。在单主模式下部署或将组更改为单主模式时,此系统变量必须设置为OFF。
指定为主服务器的成员可以通过以下方式更改:
如果现有初选离开该组,无论是自愿还是意外,都会自动选举新的初选。
可以使用group_replication_set_as_primary()函数指定特定成员作为新的主成员。
如果使用group_replication_switch_to_sile_primary_mode()函数将以多主模式运行的组更改为以单主模式运行,则会自动选择一个新的主,或者您可以通过使用函数指定新的主来指定它。
当选择新的主服务器(自动或手动)时,它会自动设置为读/写,其他组成员仍作为次服务器,因此是只读的。
查找主服务器
mysql> SELECT MEMBER_HOST, MEMBER_ROLE FROM performance_schema.replication_group_members;
6. 多主模式
在多主模式下 (group_replication_single_primary_mode=OFF) 没有成员具有特殊角色。任何与加入时其他组成员设置为读/写模式 组,并且可以处理写事务,即使它们是 同时发行。
如果成员停止接受写入事务,例如,在服务器意外退出的事件,连接到它的客户端可以重定向或故障转移到任何其他成员 在读/写模式下。组复制不处理 客户端故障转移本身,因此您需要使
用中间件框架例如Mysql Router, 一个代理、连接器或应用程序本身。
组复制是一个最终的一致性系统。这意味着,一旦传入流量减慢或停止,所有组成员都有相同的数据内容。当流量流动时,事务可以在某些成员上先于其他成员外部化,特别是如果某些成员的写入吞吐量低于其他成员,则可能会产生过时的读取。在多主模式下,速度较慢的成员还可能累积过多的待认证和申请事务,从而导致更大的冲突和认证失败风险。为了限制这些问题,您可以激活和调整组复制的流控制机制,以尽量减少快成员和慢成员之间的差异。
如果要保证组中每个事务的事务一致性,可以使用group_replication_consistance系统变量来实现。您可以选择一个适合您组的工作负载和数据读写优先级的设置,同时考虑到提高一致性所需的同步对性能的影响。您还可以为单个会话设置系统变量,以保护特别敏感的并发事务。
事务检查
当一个组以多主模式部署时,会检查事务以确保它们与该模式兼容。在多主模式下部署组复制时,会进行以下严格的一致性检查:
如果事务是在SERIALIZABLE隔离级别下执行的,那么它在与组同步时提交失败。
如果一个事务针对具有级联约束的外键的表执行,那么在与组同步时,它的提交将失败。
这些检查由group_replication_enforce_update_everywhere _checks系统变量控制。在多主模式下,系统变量通常应设置为ON,但可以通过将系统变量设置为OFF来停用检查。在单主模式下部署时,系统变量必须设置为OFF。
数据定义语句
在多主模式的组复制拓扑中,执行数据定义语句(也称为数据定义语言(DDL))时需要注意。
MySQL 9.4支持原子数据定义语言(DDL)语句,其中完整的DDL语句作为单个原子事务提交或回滚。无论是原子语句还是其他语句,DDL语句都隐式结束当前会话中活动的任何事务,就像您在执行语句之前完成了COMMIT一样。这意味着DDL语句不能在另一个事务中执行,也不能在事务控制语句中执行,如START transaction。..COMMIT,或与同一事务中的其他语句组合。
组复制基于乐观复制范式,其中语句被乐观地执行,并在必要时稍后回滚。每个服务器在执行时都没有首先保护组协议。因此,在多主模式下复制DDL语句时需要更加小心。如果对同一对象进行模式更改(使用DDL)和对象包含的数据更改(使用DML),则需要在模式操作尚未完成时通过同一服务器处理更改,并在所有地方复制。如果不这样做,当操作中断或仅部分完成时,可能会导致数据不一致。如果组以单主模式部署,则不会出现此问题,因为所有更改都是通过同一台服务器(主服务器)执行的。
7. 组复制服务
7.1 组成员
在MySQL组复制中,一组服务器组成一个复制组。组有一个名称,它采用UUID的形式。该组是动态的,服务器可以随时离开(自愿或非自愿)并加入。每当服务器加入或离开时,该组都会自动调整。
如果服务器加入该组,它会通过从现有服务器获取缺失的状态来自动更新自己。如果一台服务器离开了该组,例如它被关闭进行维护,其余的服务器会注意到它已经离开并自动重新配置该组。
组复制具有组成员资格服务,该服务定义哪些服务器联机并参与组。联机服务器列表称为视图。组中的每个服务器都有一个一致的视图,可以查看哪些服务器是在给定时刻积极参与组的成员。
组成员不仅必须就事务提交达成一致,还必须就当前视图达成一致。如果现有成员同意新服务器应成为组的一部分,则将重新配置组以将该服务器集成到其中,从而触发视图更改。如果服务器离开组,无论是自愿还是非自愿,组都会动态重新排列其配置,并触发视图更改。
在成员自愿离开组的情况下,它首先启动动态组重新配置,在此期间,所有成员必须在没有离开服务器的情况下就新视图达成一致。但是,如果成员非自愿地离开组,例如因为它意外停止或网络连接中断,则无法启动重新配置。在这种情况下,组复制的故障检测机制在短时间内识别出成员已离开,并建议在没有故障成员的情况下重新配置组。与自愿离职的成员一样,重新配置需要得到组中大多数服务器的同意。然而,如果该组无法达成协议,例如因为它以没有大多数服务器在线的方式进行分区,系统就无法动态更改配置,并阻止以防止出现分裂大脑的情况。这种情况需要管理员的干预。
成员可能会短暂离线,然后在故障检测机制检测到其故障之前,以及在组被重新配置以删除该成员之前,再次尝试重新加入组。在这种情况下,重新加入的成员会忘记其之前的状态,但如果其他成员向其发送了针对其崩溃前状态的消息,这可能会导致包括可能的数据不一致在内的问题。如果处于这种情况的成员参与了XCom的共识协议,则可能会导致XCom在失败前后做出不同的决定,从而在同一轮共识中传递不同的值。
为了应对这种可能性,MySQL组复制会检查同一服务器的新版本试图加入组的情况,而其旧版本(具有相同的地址和端口号)仍被列为成员。新化身被阻止加入该组,直到旧化身可以通过重新配置被移除。请注意,如果group_replication_member_expel_timeout系统变量添加了等待期,以允许成员在被驱逐之前有额外的时间重新连接到组,则被怀疑的成员如果在怀疑超时之前重新连接到该组,则可以作为其当前化身再次在该组中处于活动状态。当成员超过驱逐超时并被驱逐出组时,或者当服务器上的组复制因STOP group_Replication语句或服务器故障而停止时,它必须作为新的化身重新加入。
7.2 故障检测
组复制的故障检测机制是一种分布式服务,能够识别组中的服务器未与其他服务器通信,因此怀疑其已停止服务。如果该组织的共识是怀疑可能是真的,该组织将做出协调一致的决定,驱逐该成员。开除没有沟通的成员是必要的,因为该组需要大多数成员就交易或视图更改达成一致。如果某个成员没有参与这些决策,则该组必须将其删除,以增加该组包含大多数正常工作成员的机会,从而可以继续处理事务。
在复制组中,每个成员之间都有一个点对点的通信通道,从而创建了一个完全连接的图。这些连接由组通信引擎(XCom,Paxos变体)管理,并使用TCP/IP套接字。一个通道用于向成员发送消息,另一个通道则用于接收来自该成员的消息。如果一个成员在5秒内没有收到来自另一个成员的消息,则怀疑该成员失败,并在其自己的性能模式表replication_group_members中将该成员的状态列为“不可恢复”。通常,两个成员会怀疑对方失败了,因为他们彼此没有沟通。成员A怀疑成员B失败了,但成员B没有怀疑成员A失败了,这可能是由于路由或防火墙问题,尽管可能性较小。成员也可能对自己产生怀疑。一名与团队其他成员隔绝的成员怀疑其他人都失败了。
如果怀疑持续超过10秒,则怀疑成员会试图将其认为可疑成员有过错的观点传播给该组的其他成员。根据其内部XCom节点号计算,只有当可疑成员是通知者时,它才会这样做。如果一个成员实际上与组的其他成员隔离开来,它可能会试图传播自己的观点,但这不会产生任何后果,因为它无法确保其他成员达到法定人数以达成一致。只有当一个成员是通知者,并且其怀疑持续足够长的时间以传播给组的其它成员,并且其他成员也同意时,怀疑才会产生后果。在这种情况下,在协调决策中,可疑成员会被标记为从组中驱逐,并在group_replication_member_expel_timeout系统变量设置的等待期到期后被驱逐,驱逐机制会检测并执行驱逐。
如果网络不稳定,成员经常以不同的组合失去和重新建立联系,理论上一个团体最终有可能将其所有成员标记为驱逐,之后该团体将不复存在,必须重新建立。为了应对这种可能性,组复制组通信系统(GCS)跟踪被标记为驱逐的组成员,并在决定是否占多数时将其视为可疑成员组中的一员。这确保了组中至少有一个成员,并且组可以继续存在。当被开除的成员实际上已被开除出该团体时,GCS会删除其标记该成员开除的记录,以便该成员在有能力的情况下可以重新加入该团体。
7.3 容错
MySQL 组复制建立在 Paxos 的实现之上 分布式算法提供分布式协调服务器之间。因此,它需要大多数服务器积极主动地达到法定人数,从而做出决定。这有 直接影响系统可以容忍的故障数量 而不会影响自身及其整体功能。这 容忍故障所需的服务器数 (n) 为 。fn = 2 x f + 1 。下面是一个小表格,说明公式:
组成员数量 | 多数决定数量 | 容忍即时故障 |
1 | 1 | 0 |
2 | 2 | 0 |
3 | 2 | 1 |
4 | 3 | 1 |
5 | 3 | 2 |
6 | 4 | 2 |
7 | 4 | 3 |