Mysql MGR(1)MGR基础概念

注意:本系列多参考复制自官网,部分在其他相关资料

【0】MGR相关参数

# 参数

group_replication_single_primary_mode=ON   # MGR单主模式,为OFF 则为多主模式
group_replication_enforce_update_everywhere_checks=OFF #启用或禁用组的严格一致性检查。单主模式下必须OFF,多主模式下必须ON;
group_replication_member_weight=50   # 权重1-100,默认为50,权重越高 故障转移切换优先级越高;选主规则:【优先根据数据库版本,然后是权重,最后是Serer_uuid】
group_replication_consistency=EVENTUAL  # 默认 EVENTUAL,新主节点可以在之前的主节点事务全部应用之前接受新的 RO 和 RW 事务

# 函数

STRING group_replication_set_as_primary(member_uuid[, timeout])  # 手动故障转移,timeout 参数在 8.0.29才可以用
SELECT group_replication_set_as_primary('00371d66-3c45-11ea-804b-080027337932', 300)

SELECT group_replication_switch_to_single_primary_mode(member_uuid); # 切换到单主模式
SELECT group_replication_switch_to_multi_primary_mode()  # 在集群任意节点上,切换到多主模式


# DMV

查看MGR状态:SELECT * FROM performance_schema.replication_group_members;

【1】组复制

转自官网:https://dev.mysql.com/doc/refman/8.0/en/group-replication-summary.html

(1.1)组复制的概念

MySQL Group Replication 是一个 MySQL 插件,它建立在现有的 MySQL 复制基础设施之上,利用了二进制日志、基于行的日志记录和全局事务标识符等功能。

《1》对于任何读写事务(不包含只读事务),组需要决定它是否提交

  复制组由多台服务器组成,组中的每台服务器都可以随时独立执行事务。但是,所有读写事务只有在得到组批准后才会提交。

  换句话说,对于任何读写事务,组需要决定它是否提交,因此提交操作不是来自原始服务器的单方面决定。只读事务不需要在组内协调并立即提交。

《2》所有服务器都以相同的顺序接收相同的事务集,并且为这些事务建立了全局总顺序

  当一个读写事务准备在源服务器上提交时,服务器会自动广播写入值(已更改的行)和相应的写入集(已更新行的唯一标识符)。

  因为事务是通过原子广播发送的,所以组中的所有服务器都接收到事务,或者没有。如果他们收到它,那么他们都以与之前发送的其他交易相同的顺序收到它。

  因此,所有服务器都以相同的顺序接收相同的事务集,并且为这些事务建立了全局总顺序。

《3》多主模式下,组复制下的不同主机上写入多个冲突事务,则哪个事务先提交就赢得冲突,后提交的自动回滚;(单主模式没有多写入烦恼,所以无需理会)

  但是,在不同服务器上同时执行的事务之间可能存在冲突。这种冲突是通过检查和比较两个不同的并发事务的写入集来检测的,在一个称为 认证的过程中在认证期间,冲突检测在行级别进行:

    如果在不同服务器上执行的两个并发事务更新同一行,则存在冲突。冲突解决过程表明,首先订购的事务在所有服务器上提交,然后订购的事务第二次中止,因此在原始服务器上回滚并被组中的其他服务器丢弃。

    例如,如果 t1 和 t2 在不同的站点同时执行,都更改同一行,并且 t2 排序在 t1 之前,则 t2 赢得冲突,并且 t1 回滚。这实际上是一个分布式的首次提交获胜规则。

《4》多主模式下,不破坏一致性和有效性的前提下,事务传送到从库后其可以与提交顺序不一致的顺序执行;单主模式下,这种情况可能性非常少;

  为了应用和外部化已认证的事务,组复制允许服务器在不破坏一致性和有效性的情况下偏离约定的事务顺序。Group Replication 是一个最终一致性系统,这意味着一旦传入流量变慢或停止,所有组成员都具有相同的数据内容。

  当流量流动时,交易可以以稍微不同的顺序外部化,或者在其他成员之前外部化。例如,在多主模式中,本地事务可能在认证后立即外部化,尽管尚未应用全局顺序中较早的远程事务。

  当认证过程确定交易之间没有冲突时,这是允许的。在单主模式下,在主服务器上,并发的、非冲突的本地事务可能以与 Group Replication 同意的全局顺序不同的顺序提交和外部化的可能性很小。

  在不接受来自客户端的写入的辅助节点上,事务总是按照约定的顺序提交和外部化。非冲突的本地事务可能会以与 Group Replication 同意的全局顺序不同的顺序提交和外部化。

  

(1.2)组复制服务

Group Replication 有一个组成员服务,它定义了哪些服务器在线并参与了该组。在线服务器列表称为 view 视图组中的每个服务器都具有一致的视图,即哪些服务器是在给定时刻积极参与组的成员。

  (1)成员主动离开组:它首先启动动态组重新配置,在此期间所有成员必须在没有离开服务器的情况下就新视图达成一致。

  (2)成员被动离开组:例如由于意外停止或网络连接断开,则无法启动重新配置。在这种情况下,Group Replication 的故障检测机制会在短时间内识别出成员已离开,并建议在没有故障成员的情况下重新配置组。当然这需要大多数服务器的同意;

  (3)脑裂:如果小组无法达成协议,例如,因为它以这样一种方式进行分区,没有大多数服务器在线,系统无法动态更改配置,并阻止以防止脑裂情况。这种情况需要管理员干预。

一个成员可能会在短时间内下线,然后在故障检测机制检测到其故障之前以及在重新配置组以删除该成员之前再次尝试重新加入该组。

  在这种情况下,重新加入的成员会忘记其先前的状态,但如果其他成员向其发送旨在用于其崩溃前状态的消息,这可能会导致问题,包括可能的数据不一致。

  如果处于这种情况的成员参与 XCom 的共识协议,则可能会导致 XCom 在失败前后做出不同的决定,从而为同一轮共识提供不同的价值    

为了解决这个问题:(为了防止闪断等情况,导致同一台机器疯狂退出又已新成员身份立马加入)

从 MySQL 5.7.22 和 MySQL 8.0 开始,Group Replication 会检查同一服务器的新版本尝试加入组而其旧版本(具有相同地址和端口号)仍然存在的情况列为成员。

  新的化身被阻止加入组,直到旧的化身可以通过重新配置移除。

  请注意,如果 group_replication_member_expel_timeout 系统变量,以允许成员在被驱逐之前有额外的时间重新连接到该组,如果在怀疑超时之前重新连接到该组,则被怀疑的成员可以作为其当前化身再次活跃在该组中。

  当成员超过驱逐超时并被驱逐出组时,或者当组复制在服务器上因STOP GROUP_REPLICATION语句或服务器故障而停止时,它必须作为新的化身重新加入。     

(1.3)故障检测机制

在复制组中,每个成员都有一个到其他成员的点对点通信通道,从而创建一个全连接图。这些连接由组通信引擎(XCom,Paxos 变体)管理并使用 TCP/IP 套接字。一个通道用于向成员发送消息,另一个通道用于接收来自成员的消息。

  (1)如果一个成员在 5 秒内没有收到另一个成员的消息,则产生怀疑,该成员是否出现故障,并将该成员的状态列为 unreachable 在自己的 Performance Schema 表中 replication_group_members

  (2)如果怀疑持续超过 10 秒,则怀疑成员会尝试将其认为可疑成员有错误的观点传播给该组的其他成员。可疑成员仅在它是通知者时才这样做,根据其内部 XCom 节点编号计算得出。

      在这种情况下, group_replication_member_expel_timeout 系统变量过期,驱逐机制检测并执行驱逐。

  在网络不稳定且成员经常以不同的组合方式失去和恢复彼此连接的情况下,理论上有可能一个组最终将其所有成员标记为驱逐,之后该组将不复存在并必须建立再次。为了应对这种可能性,从 MySQL 8.0.20 开始,Group Replication 的 Group Communication   System (GCS) 会跟踪已标记为驱逐的组成员,并在决定是否有多数时将其视为可疑成员组中的成员. 这确保了至少一个成员保留在组中,并且组可以继续存在。当被开除的成员实际上已从组中删除时,

【2】MGR 单主模式

版本建议 8.0.17 及以上

转自官网:https://dev.mysql.com/doc/refman/8.0/en/group-replication-single-primary-mode.html

(2.0)限制要求

深入官网参考 MGR限制:https://dev.mysql.com/doc/refman/8.0/en/group-replication-requirements.html

下面是关于MGR使用的一些限制:

  • 所有表必须是InnoDB引擎。可以创建非InnoDB引擎表,但无法写入数据,在利用Clone构建新节点时也会报错。
  • 所有表都必须要有主键。同上,能创建没有主键的表,但无法写入数据,在利用Clone构建新节点时也会报错。
  • 不要使用大事务,默认地,事务超过150MB会报错,最大可支持2GB的事务(在GreatSQL未来的版本中,会增加对大事务的支持,提高大事务上限)。
  • 如果是从旧版本进行升级,则不能选择 MINIMAL 模式升级,建议选择 AUTO 模式,即 upgrade=AUTO
  • 由于MGR的事务认证线程不支持 gap lock,因此建议把所有节点的事务隔离级别都改成 READ COMMITTED。基于相同的原因,MGR集群中也不要使用 table lock 及 name lock(即 GET_LOCK() 函数 )。
  • 在多主(multi-primary)模式下不支持串行(SERIALIZABLE)隔离级别。
  • 不支持在不同的MGR节点上,对同一个表分别执行DML和DDL,可能会造成数据丢失或节点报错退出。
  • 在多主(multi-primary)模式下不支持多层级联外键表。另外,为了避免因为使用外键造成MGR报错,建议设置 group_replication_enforce_update_everywhere_checks=ON
  • 在多主(multi-primary)模式下,如果多个节点都执行 SELECT ... FOR UPDATE 后提交事务会造成死锁。
  • 不支持复制过滤(Replication Filters)设置。

看起来限制有点多,但绝大多数时候并不影响正常的业务使用。

此外,想要启用MGR还有几个要求:

  • 每个节点都要启用binlog。
  • 每个节点都要转存binlog,即设置 log_slave_updates=1
  • binlog format务必是row模式,即 binlog_format=ROW
  • 每个节点的 server_id 及 server_uuid 不能相同。
  • 在8.0.20之前,要求 binlog_checksum=NONE,但是从8.0.20后,可以设置 binlog_checksum=CRC32
  • 要求启用 GTID,即设置 gtid_mode=ON
  • 要求 master_info_repository=TABLE 及 relay_log_info_repository=TABLE,不过从MySQL 8.0.23开始,这两个选项已经默认设置TABLE,因此无需再单独设置。
  • 所有节点上的表名大小写参数 lower_case_table_names 设置要求一致。
  • 最好在局域网内部署MGR,而不要跨公网,网络延迟太大的话,会导致MGR性能很差或很容易出错。
  • 建议启用writeset模式,即设置以下几个参数
    • slave_parallel_type = LOGICAL_CLOCK
    • slave_parallel_workers = N,N>0,可以设置为逻辑CPU数的2倍
    • binlog_transaction_dependency_tracking = WRITESET
    • slave_preserve_commit_order = 1
    • slave_checkpoint_period = 2

(2.1)单主模式下的选主

在单主模式下,组复制强制只有单个服务器写入组,因此与多主模式相比,一致性检查可以不那么严格,并且不需要额外小心处理 DDL 语句。

group_replication_single_primary_mode=ON   # MGR单主模式,为OFF 则为多主模式
group_replication_enforce_update_everywhere_checks=OFF #启用或禁用组的严格一致性检查。单主模式下必须OFF,多主模式下必须ON;

指定为主服务器的成员可以通过以下方式进行更改:

  • 如果现有的主节点离开组,无论是自愿还是意外,都会自动选出一个新的主节点。

  • group_replication_set_as_primary() 您可以使用该功能 指定特定成员作为新的主要成员 。

  • 如果您使用该 group_replication_switch_to_single_primary_mode() 函数将一个以多主模式运行的组更改为以单主模式运行,则会自动选举一个新的主节点,或者您可以通过函数指定新的主节点来指定新的主节点。

只有当所有组成员都运行 MySQL 8.0.13 或更高版本时,才能使用这些函数。当自动选举或手动指定新的主服务器时,它会自动设置为读写,其他组成员保持从属,因此是只读的。

故障转移选新主过程如下图:

  

(2.2)选主后的事务问题

概述:故障转移成新主后,可能relay 中还有未应用完成的事务,但这个时候也可以接受新的读和写操作,容易造成读到的数据过时、写入的事务和未应用完成的事务有冲突;

  当一个新的主节点被选举或任命时,它可能会积压一些已应用于旧主节点但尚未应用于此服务器的更改。

  在这种情况下,在新的主节点赶上旧的主节点之前,读写事务可能会导致冲突并被回滚,而只读事务可能会导致读取过时。

  

解决:

  (1)Group Replication 的流控制机制可以最大限度地减少快速成员和慢速成员之间的差异,如果它被激活并正确调整,则可以减少发生这种情况的机会。 有关流控制的更多信息,请参阅 第 18.7.2 节,“流控制”

    流控制,就是限定组复制的一个频率和一次性提交的大小;

  (2)从 MySQL 8.0.14 开始,您还可以使用 group_replication_consistency 系统变量来配置组的事务一致性级别以防止此问题。该设置 BEFORE_ON_PRIMARY_FAILOVER(或任何更高的一致性级别)在新选择的主节点上保留新事务,直到应用积压。

    有关事务一致性的更多信息,请参阅 第 18.5.3 节,“事务一致性保证”

  (3)如果组没有使用流控制和事务一致性保证,那么在将客户端应用程序重新路由到它之前,等待新的主节点应用其与复制相关的 relay log 中继日志是一个很好的做法。

(2.3)选主算法

成员在选举初选时考虑的因素依次如下:

  1. 考虑的第一个因素是哪些成员或哪些成员正在运行最低的 MySQL 服务器版本。如果所有组成员都运行 MySQL 8.0.17 或更高版本,则成员首先按其发布的补丁版本排序。如果任何成员运行 MySQL Server 5.7 或 MySQL 8.0.16 或更低版本,则成员首先按其发布的主要版本排序,而补丁版本将被忽略。

  2. 如果多个成员运行最低 MySQL 服务器版本,则考虑的第二个因素是每个成员的成员权重,由成员 group_replication_member_weight 上的系统变量指定。如果该组的任何成员正在运行 MySQL Server 5.7,而此系统变量不可用,则忽略此因素。

    系统变量指定 0-100 范围内的 group_replication_member_weight 数字。所有成员的默认权重为 50,因此将权重设置为低于此以降低其排序,将其设置为高于它的权重以增加其排序。您可以使用此加权函数来优先使用更好的硬件或确保在主节点的计划维护期间故障转移到特定成员。

  3. 如果多个成员运行最低 MySQL 服务器版本,并且其中多个成员具有最高成员权重(或成员权重被忽略),则考虑的第三个因素是每个成员生成的服务器 UUID 的字典顺序,由 server_uuid系统变量指定。具有最低服务器 UUID 的成员被选为主要成员。该因素充当有保证且可预测的决胜局,因此如果无法由任何重要因素决定,则所有小组成员都会做出相同的决定。

(2.4)查看组复制成员情况和状态

SELECT MEMBER_HOST, MEMBER_ROLE FROM performance_schema.replication_group_members;
+-------------------------+-------------+
| MEMBER_HOST             | MEMBER_ROLE |
+-------------------------+-------------+
| remote1.example.com     | PRIMARY     |
| remote2.example.com     | SECONDARY   |
| remote3.example.com     | SECONDARY 

【3】多主模式

版本建议 8.0.17 及以上

(3.1)多主下的选主

在多主模式 ( group_replication_single_primary_mode=OFF) 中,没有成员具有特殊角色。任何与其他组成员兼容的成员在加入组时都设置为读写模式,并且可以处理写事务,即使它们是并发发出的。

  如果成员停止接受写入事务,例如,在服务器意外退出的情况下,连接到它的客户端可以重定向或故障转移到处于读写模式的任何其他成员。

  Group Replication 本身不处理客户端故障转移,因此您需要使用中间件框架(例如MySQL Router 8.0)、代理、连接器或应用程序本身来安排它。

下图显示了如果成员离开组,客户端如何重新连接到备用组成员:(客户端故障转移)

  

 

组复制是一个最终一致性系统。这意味着一旦传入流量变慢或停止,所有组成员都具有相同的数据内容。

  当流量在流动时,事务可以先于其他成员在某些成员上进行外部化,特别是如果某些成员的写入吞吐量低于其他成员,从而产生过时读取的可能性。

  在多主模式下,速度较慢的成员还会积压过多的交易以进行认证和申请,从而导致更大的冲突和认证失败风险。(这也是为什么不建议用多主的原因)

  为了限制这些问题,您可以激活和调整 Group Replication 的流量控制机制,以尽量减少快速和慢速成员之间的差异。有关流量控制的更多信息,请参阅第 18.7.2 节,“流控制”

(3.2)同步限制眼球

当一个组以多主模式部署时,会检查事务以确保它们与该模式兼容。以多主模式部署 Group Replication 时,会进行以下严格的一致性检查:

  • •仅InnoDB Engine(Transactional and row level lock)

    •表必须有主键

    •gtid-mode=ON

    •binlog格式为Row-based

    •对于同一个对象执行DDL和DML应在同一成员上执行,不支持在不同服务器上执行DDL

    •不支持具有多级外键依赖关系的表,特别是已定义CASCADING外键约束的表

    •不支持“serializable”隔离级别

检查由 group_replication_enforce_update_everywhere_checks 系统变量控制。在多主模式下,系统变量通常应设置为ON,但可以通过将系统变量设置为 来选择性地停用检查OFF

在单主模式下部署时,系统变量必须设置为 OFF.

(3.3)DDL 语句不能与事务组合

在多主模式下的 Group Replication 拓扑中,执行数据定义语句时需要小心,通常也称为数据定义语言 (DDL)。

  MySQL 8.0 引入了对原子数据定义语言 (DDL) 语句的支持,其中完整的 DDL 语句作为单个原子事务提交或回滚。但是,DDL 语句,无论是原子的还是其他的,都会隐式结束当前会话中活动的任何事务,就好像您 COMMIT在执行语句之前已经完成了一样。这意味着 DDL 语句不能在另一个事务、事务控制语句(如 )中执行 START TRANSACTION ... COMMIT,或与同一事务中的其他语句组合。

  组复制基于乐观复制范式,其中语句被乐观地执行并在必要时稍后回滚。每台服务器在没有首先获得组协议的情况下执行。因此,在多主模式下复制 DDL 语句时需要更加小心。如果您对同一对象进行模式更改(使用 DDL)和对象包含的数据更改(使用 DML),则需要通过同一服务器处理更改,而模式操作尚未完成并在各处复制。当操作中断或仅部分完成时,不这样做可能会导致数据不一致。

有关 MySQL 8.0 中原子 DDL 支持的详细信息,以及复制某些语句的行为变化,请参阅第 13.1.1 节,“原子数据定义语句支持”

 

【4】组复制插件架构

(4.1)整体插件架构图

MySQL Group Replication 是一个 MySQL 插件,它建立在现有的 MySQL 复制基础设施之上,利用了二进制日志、基于行的日志记录和全局事务标识符等功能。

  

 

MySQL Group Replication 插件包括一组用于捕获、应用和生命周期的 API ,它们控制插件与 MySQL 服务器的交互方式。

(4.2)replication plugin

   

 

(4.3)Group Communication System (GCS)

组复制插件架构的最后两层是组通信系统 (GCS) API,以及基于 Paxos 的组通信引擎 (XCom) 的实现。

GCS API 是一个高级 API,它抽象了构建复制状态机所需的属性(请参阅 第 18.1 节,“组复制背景”)。因此,它将消息传递层的实现与插件的其余上层分离。组通信引擎处理与复制组成员的通信。

  

 

 

 

 

 

 

【参考文档】

官网:https://dev.mysql.com/doc/refman/8.0/en/group-replication-summary.html

MySQL并行复制,MySQL组复制,MySQL中的WriteSet,MySQL二阶段提交

(5.1)mysql高可用系列——高可用架构方案概述

posted @ 2022-05-13 11:32  郭大侠1  阅读(719)  评论(0编辑  收藏  举报