MySQL Group Replication(MGR)它是一个MySQL插件,它建立在现有的MySQL复制基础设施上,利用二进制日志、基于行的日志和全局事务标识符等功能。MGR出来之后基本上可以替换之前的MHA之类的集群技术了。
这里简单整理一下MGR和传统的主从模式有什么区别:
对 比 特 性 | MySQL Group Replication(MGR) | 传统的主从复制 |
---|---|---|
数据同步方式 | 基于消息传递的复制机制 | 通过读取主节点的binlog进行数据复制 |
复制拓扑结构 | 对等结构,所有节点都可以接收写入操作并复制到其他节点 | 一个主节点和多个从节点 |
数据一致性 | 所有写入操作在集群中的所有节点上执行,事务在所有节点上成功应用后才提交 | 从主节点的binlog读取数据进行复制 |
自动故障转移 | 自动选择新的主节点 | 需要手动将一个从节点提升为新的主节点 |
复制延迟监控 | 提供了方便的方式来监控复制延迟 | 需要手动监控复制延迟 |
动态成员管理 | 动态添加和删除节点 | 需要在配置文件中手动添加和删除节点 |
搭建简易程度 | 中,需充分了解MGR知识点 | 简单 |
学习成本 | 中,仔细查看官方文档 | 低 |
重点说下 数据同步方式 和 复制拓扑结构:
接下来 采用3台物理主机安装具有3个节点的MGR集群,MGR集群架构为1主2从方式 ( MySQL8.0.27默认模式)
3台物理主机,按照docker环境,mysql镜像版本为 8.0.27,3台主机可相互访问且具有不同的主机名称
为了最佳的兼容性和性能,组中的所有成员应该运行相同版本的MySQL Server,
主机名称 | IP地址 | 操作系统 | Docker版本 | Mysql镜像版本 | 备注 |
---|---|---|---|---|---|
mgr-master | 172.20.167.255 | Ubuntu 22.04.2 LTS | 24.0.5 | 8.0.27 | 主节点 |
mgr-node1 | 172.20.167.253 | Ubuntu 22.04.2 LTS | 24.0.5 | 8.0.27 | 从节点 |
mgr-node2 | 172.20.167.254 | Ubuntu 22.04.2 LTS | 24.0.5 | 8.0.27 | 从节点 |
关闭SELinux
建议先关闭防火墙
【重要】各主机名称唯一
MGR各个节点之间默认采用主机名进行管理通讯。
【重要】各主机上的hosts文件中配置所有主机的名称和对应的IP地址
vim /etc/hosts
hosts文件后面追加信息:
172.20.167.253 mgr-node1 mgr-node1
172.20.167.255 mgr-master mgr-master
172.20.167.254 mgr-node2 mgr-node2
【重要】 创建Mysql Docker 容器的网络模式全部采用 host模式
为什么要用host模式?
因为MGR启动时需要验证主机IP地址和配置文件中MGR相关的IP是否一致,
如果不采用则报错无法启动MGR,否则你会看到如下错误:
... There is no local IP address matching the one configured for...
安装之前请务必参考上面的 安装环境及要求
安装之前请务必参考上面的 安装环境及要求
安装之前请务必参考上面的 安装环境及要求
三台主机上创建MySQL容器映射目录:
mkdir -p /apps/mysql/data /apps/mysql/conf /apps/mysql/files
三台主机上配置各自的 my.cnf,这里只列出和MGR配置要求相关的参数信息:文件位置: /apps/mysql/conf/my.cnf
[mysqld]
port = 3309
disabled_storage_engines="MyISAM,BLACKHOLE,FEDERATED,ARCHIVE,MEMORY"
default_time_zone = "+8:00"
transaction_isolation = READ-COMMITTED
# 请确保每一台主机上是唯一值
server-id = 1
log-bin=mysql-bin
binlog_format = ROW
binlog_row_image = FULL
binlog_expire_logs_seconds = 1209600
master_info_repository = TABLE
relay_log_info_repository = TABLE
log_replica_updates = ON
relay_log_recovery = 1
replica_skip_errors = ddl_exist_errors
innodb_flush_log_at_trx_commit = 1
sync_binlog = 1
transaction_write_set_extraction = XXHASH64
gtid_mode = on
enforce_gtid_consistency=ON
# MySQL 8.0.21可以不设置
#binlog_checksum=NONE
上面文件中的参数 确保每个主机上的 server-id 不一样
三台主机上执行docker命令创建容器
docker run \
-u root \
--network=host \
--restart=always \
--name mysql8 \
-v /apps/mysql/conf/my.cnf:/etc/mysql/my.cnf \
-v /apps/mysql/files:/var/lib/mysql-files \
-v /apps/mysql/data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=PassWord123_ \
-d mysql:8.0.27
登录mysql:
docker exec -it mysql8 /bin/bash
mysql> mysql -uroot -p -P3309
Enter password: 请输入mysql登录密码
然后执行下面的 1/2/3/4 步骤:
设置binlog 下面操作不用进入binlog
mysql> SET SQL_LOG_BIN=0;
创建用户赋予必要权限
mysql> CREATE USER rpl_user@'%' IDENTIFIED WITH mysql_native_password BY 'PassWord123_';
mysql> GRANT REPLICATION SLAVE ON *.* TO rpl_user@'%';
mysql> GRANT CONNECTION_ADMIN ON *.* TO rpl_user@'%';
mysql> GRANT BACKUP_ADMIN ON *.* TO rpl_user@'%';
mysql> GRANT GROUP_REPLICATION_STREAM ON *.* TO rpl_user@'%';
mysql> FLUSH PRIVILEGES;
注意:
官方文档上有个Bug,这里创建用户密码需要采用 mysql_native_password,否则启动或加入集群会报用户名密码连接失败
恢复binglog
mysql> SET SQL_LOG_BIN=1;
将用户凭据提供给服务器以用于分布式恢复
mysql> CHANGE REPLICATION SOURCE TO SOURCE_USER='rpl_user', SOURCE_PASSWORD='PassWord123_' FOR CHANNEL 'group_replication_recovery';
注意:
MySQL 8.0.24版本之前使用下面的SQL
mysql> CHANGE MASTER TO MASTER_USER='rpl_user', MASTER_PASSWORD='PassWord123_' FOR CHANNEL 'group_replication_recovery';
说明:
group_replication_recovery是MySQL Group Replication中的一个通道(channel),
用于执行分布式恢复操作。
在Group Replication中,每个成员(member)都可以充当复制源(replication source)
和复制目标(replication target)。当一个成员从其他成员复制数据时,
它可以使用group_replication_recovery通道来连接到复制源,并从中检索丢失的数据。
必须安装 group_replication插件之后才能启动MGR集群,安装之后 my.cnf里面才能配置 MGR相关的参数。
mysql> INSTALL PLUGIN group_replication SONAME 'group_replication.so';
mysql> SHOW PLUGINS;
+----------------------------+----------+--------------------+----------------------+-------------+
| Name | Status | Type | Library | License |
+----------------------------+----------+--------------------+----------------------+-------------+
| binlog | ACTIVE | STORAGE ENGINE | NULL | PROPRIETARY |
(...)
| group_replication | ACTIVE | GROUP REPLICATION | group_replication.so | PROPRIETARY |
+----------------------------+----------+--------------------+----------------------+-------------+
172.20.167.255 修改 my.cnf 增加如下MGR参数配置
group_replication_group_name = "7cf70110-59f9-11ee-a293-246e967fa518"
group_replication_start_on_boot = off
group_replication_local_address = "172.20.167.255:33061"
group_replication_group_seeds = "172.20.167.255:33061,172.20.167.254:33061,172.20.167.253:33061"
group_replication_bootstrap_group = off
172.20.167.254 修改 my.cnf 增加如下MGR参数配置
group_replication_group_name = "7cf70110-59f9-11ee-a293-246e967fa518"
group_replication_start_on_boot = off
group_replication_local_address = "172.20.167.254:33061"
group_replication_group_seeds = "172.20.167.255:33061,172.20.167.254:33061,172.20.167.253:33061"
group_replication_bootstrap_group = off
172.20.167.253 修改 my.cnf 增加如下MGR参数配置
group_replication_group_name = "7cf70110-59f9-11ee-a293-246e967fa518"
group_replication_start_on_boot = off
group_replication_local_address = "172.20.167.253:33061"
group_replication_group_seeds = "172.20.167.255:33061,172.20.167.254:33061,172.20.167.253:33061"
group_replication_bootstrap_group = off
docker restart mysql8
登录mysql之后执行查看语句
mysql> SHOW VARIABLES LIKE 'group_replication%';
注意:
千万不要在创建mysql容器时添加这些参数,这样mysql启动不了,因为还没安装这个插件,这些参数Mysql启动时候不认识
相关参数说明:
启动一个引导实例
引导应该只由一个服务器完成,即启动群组的服务器,并且只能执行一次
这次我们选择在 172.20.167.255 这台主机上执行启动集群操作:
mysql> SET GLOBAL group_replication_bootstrap_group=ON;
mysql> START GROUP_REPLICATION USER='rpl_user', PASSWORD='PassWord123_';
mysql> SET GLOBAL group_replication_bootstrap_group=OFF;
查看集群成员状态
mysql> SELECT * FROM performance_schema.replication_group_members;
+---------------------------+--------------------------------------+-------------+-------------+---------------+-------------+----------------+----------------------------+
| CHANNEL_NAME | MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE | MEMBER_ROLE | MEMBER_VERSION | MEMBER_COMMUNICATION_STACK |
+---------------------------+--------------------------------------+-------------+-------------+---------------+-------------+----------------+----------------------------+
| group_replication_applier | ce9be252-2b71-11e6-b8f4-00212844f856 | s1 | 3306 | ONLINE | | | XCom |
+---------------------------+--------------------------------------+-------------+-------------+---------------+-------------+----------------+----------------------------+
1 row in set (0.0108 sec)
创建DDL事务后查看binlog 事件
mysql> SHOW BINLOG EVENTS;
另外两台服务器上,登录MySQL后执行如下操作:
SET SQL_LOG_BIN=0;
CREATE USER rpl_user@'%' IDENTIFIED WITH mysql_native_password BY 'PassWord123_';
GRANT REPLICATION SLAVE ON *.* TO rpl_user@'%';
GRANT CONNECTION_ADMIN ON *.* TO rpl_user@'%';
GRANT BACKUP_ADMIN ON *.* TO rpl_user@'%';
GRANT GROUP_REPLICATION_STREAM ON *.* TO rpl_user@'%';
FLUSH PRIVILEGES;
SET SQL_LOG_BIN=1;
CHANGE MASTER TO MASTER_USER='rpl_user', MASTER_PASSWORD='PassWord123_' FOR CHANNEL 'group_replication_recovery';
Or from MySQL 8.0.23:
CHANGE REPLICATION SOURCE TO SOURCE_USER='rpl_user', SOURCE_PASSWORD='PassWord123_' FOR CHANNEL 'group_replication_recovery';
mysql> START GROUP_REPLICATION USER='rpl_user', PASSWORD='PassWord123_';
mysql> SELECT * FROM performance_schema.replication_group_members;
mysql> SHOW BINLOG EVENTS;
如果 START GROUP_REPLICATION 时出现以下错误:
....
[ERROR] [MY-011526] [Repl] Plugin group_replication reported: 'This member has more executed transactions than those present in the group. Local transactions: ae6b26d7-5dc0-11ea-9d16-000c29b33fcb:1 > Group transactions: 043887ba-5ce8-11ea-8f3a-000c29d3fc7e:1,
043887ba-5ce8-11ea-8f3a-000c29d3fc7e'
....
这个错误的原因是MGR中的成员拥有比组中存在的事务更多的已执行事务。
这种情况通常发生在MGR集群中的成员之间的数据同步出现问题时。可能的原因包括网络故障、成员崩溃或其他同步问题。
当一个成员拥有比组中其他成员更多的已执行事务时,可能会导致数据不一致的情况。这是因为在MGR中,所有成员都应该具有相同的已执行事务,以保持数据的一致性。
执行下面SQL清空Executed_Gtid_Set解决问题:
mysql> reset master
SELECT * FROM performance_schema.replication_group_members;
以下是 replication_group_members
表格中每个字段的含义:
字段名 | 描述 |
---|---|
MEMBER_ID | 成员的唯一标识符 |
MEMBER_HOST | 成员的主机名或 IP 地址 |
MEMBER_PORT | 成员的端口号 |
MEMBER_STATE | 成员的状态 |
MEMBER_ROLE | 成员的角色 |
MEMBER_VERSION | 成员的版本号 |
MEMBER_SSL | 成员是否使用 SSL 连接 |
MEMBER_SSL_VERSION | 成员使用的 SSL 版本 |
MEMBER_SSL_CIPHER | 成员使用的 SSL 加密算法 |
MEMBER_SSL_STATE | 成员 SSL 连接的状态 |
MEMBER_CONNECTIONS | 成员当前连接的数量 |
MEMBER_UUID | 成员的 UUID |
MEMBER_PRIMARY | 成员是否为主节点 |
MEMBER_AUTOPROTECT | 成员是否启用自动保护模式 |
MEMBER_PRIMARY_UUID | 成员所属的主节点的 UUID,如果成员本身是主节点,则该字段为 NULL |
MEMBER_PRIMARY_HOST | 成员所属的主节点的主机名或 IP 地址,如果成员本身是主节点,则该字段为 NULL |
MEMBER_PRIMARY_PORT | 成员所属的主节点的端口号,如果成员本身是主节点,则该字段为 NULL |
注意:该表格中的字段可能会因为 MySQL 版本的不同而略有差异。
SELECT * FROM performance_schema.replication_group_member_stats
字段名 | 描述 |
---|---|
VIEW_ID | 视图的唯一标识符 |
MEMBER_ID | 成员的唯一标识符 |
MEMBER_HOST | 成员的主机名或 IP 地址 |
MEMBER_PORT | 成员的端口号 |
MEMBER_STATE | 成员的状态 |
MEMBER_ROLE | 成员的角色 |
MEMBER_VERSION | 成员的版本号 |
COUNT_TRANSACTIONS_IN_QUEUE | 当前队列中的事务数 |
COUNT_TRANSACTIONS_CHECKED | 已经检查的事务数 |
COUNT_TRANSACTIONS_QUEUED | 已经排队的事务数 |
COUNT_TRANSACTIONS_COMMITTED | 已经提交的事务数 |
COUNT_TRANSACTIONS_ROLLED_BACK | 已经回滚的事务数 |
COUNT_TRANSACTIONS_UNKNOWN | 未知状态的事务数 |
COUNT_RECEIVED_HEARTBEATS | 接收到的心跳数 |
COUNT_RECEIVED_TRANSACTION_SETS | 接收到的事务集数 |
COUNT_APPLIED_TRANSACTION_SETS | 应用的事务集数 |
COUNT_COMMITTED_TRANSACTIONS | 提交的事务数 |
COUNT_ROLLEDBACK_TRANSACTIONS | 回滚的事务数 |
COUNT_RECEIVED_TRANSACTION_SETS_TO_COMMIT | 待提交的事务集数 |
COUNT_RECEIVED_TRANSACTION_SETS_TO_ROLLBACK | 待回滚的事务集数 |
COUNT_TRANSACTIONS_GTID_EXECUTED | 已经执行的 GTID 事务数 |
COUNT_TRANSACTIONS_GTID_EXECUTED_ALL_MEMBERS | 所有成员已经执行的 GTID 事务数 |
COUNT_TRANSACTIONS_GTID_EXECUTED_LOCAL | 本地成员已经执行的 GTID 事务数 |
COUNT_TRANSACTIONS_GTID_IN_QUEUE | 当前队列中的 GTID 事务数 |
COUNT_TRANSACTIONS_GTID_IN_QUEUE_ALL_MEMBERS | 所有成员当前队列中的 GTID 事务数 |
COUNT_TRANSACTIONS_GTID_IN_QUEUE_LOCAL | 本地成员当前队列中的 GTID 事务数 |
COUNT_TRANSACTIONS_GTID_PURGED | 已经清除的 GTID 事务数 |
COUNT_TRANSACTIONS_GTID_PURGED_ALL_MEMBERS | 所有成员已经清除的 GTID 事务数 |
COUNT_TRANSACTIONS_GTID_PURGED_LOCAL | 本地成员已经清除的 GTID 事务数 |
COUNT_TRANSACTIONS_WITHOUT_CONFLICTS | 不冲突的事务数 |
COUNT_TRANSACTIONS_WITH_CONFLICTS | 冲突的事务数 |
COUNT_TRANSACTIONS_WITHOUT_CONFLICTS_ALL_MEMBERS | 所有成员不冲突的事务数 |
COUNT_TRANSACTIONS_WITH_CONFLICTS_ALL_MEMBERS | 所有成员冲突的事务数 |
COUNT_TRANSACTIONS_WITHOUT_CONFLICTS_LOCAL | 本地成员不冲突的事务数 |
COUNT_TRANSACTIONS_WITH_CONFLICTS_LOCAL | 本地成员冲突的事务数 |
LAST_CONFLICT_FREE_TRANSACTION | 最后一个不冲突的事务 |
LAST_CONFLICT_TRANSACTION | 最后一个冲突的事务 |
LAST_ERROR_TRANSACTION | 最后一个出错的事务 |
LAST_ERROR_NUMBER | 最后一个错误的编号 |
LAST_ERROR_MESSAGE | 最后一个错误的消息 |
在MGR中使用除了InnoDB
之外的存储引擎会导致集群错误,最好版本是禁用其他
disabled_storage_engines="MyISAM,BLACKHOLE,FEDERATED,ARCHIVE,MEMORY"
所有表必须有主键或者非空唯一索引
保证集群中的mysql相互之间可以通讯
保证 server-id值唯一
保证binlog打开,默认情况是打开的
设置log_replica_updates=ON(从MySQL 8.0.26开始)或log_slave_updates=ON(在MySQL 8.0.26之前)默认情况是打开
设置 binlog_format=row
set binlog_checksum=NONE
在MySQL 8.0.20及之前的版本中,设置binlog_checksum=NONE,不过从MySQL 8.0.21开始,Group Replication支持校验和,因此群组成员可以使用默认设置binlog_checksum=CRC32
全局事务标识启用。设置gtid_mode=ON和enforce_gtid_consistency=ON。这些设置不是默认值
针对大小写是否敏感设置请保持所有实例配置一样
多线程设置
Group Replication成员可以配置为多线程副本,从而实现并行应用事务。从MySQL 8.0.27开始,默认情况下所有副本都配置为多线程。对于系统变量replica_parallel_workers(从MySQL 8.0.26开始)或slave_parallel_workers(在MySQL 8.0.26之前),非零值启用了成员上的多线程应用程序。从MySQL 8.0.27开始,默认值为4个并行应用程序线程,最多可以指定1024个并行应用程序线程。对于多线程副本,还需要以下设置,这些设置是从MySQL 8.0.27开始的默认设置:
replica_preserve_commit_order=ON(从MySQL 8.0.26开始)或slave_preserve_commit_order=ON(在MySQL 8.0.26之前) 此设置要求确保并行事务的最终提交与原始事务的顺序相同。Group Replication依赖于围绕所有参与成员按相同顺序接收和应用已提交事务的一致性机制。
replica_parallel_type=LOGICAL_CLOCK(从MySQL 8.0.26开始)或slave_parallel_type=LOGICAL_CLOCK(在MySQL 8.0.26之前) 此设置要求使用replica_preserve_commit_order=ON或slave_preserve_commit_order=ON。它指定了在副本上允许并行执行哪些事务的策略
设置replica_parallel_workers=0或slave_parallel_workers=0将禁用并行执行,并为副本提供单个应用程序线程和无协调器线程
为了降低间隙锁的概率,强烈建议配置事务级别为 READ COMMITTED
集群不支持 事务级别为最高级别:序列化
在多主模式下,不支持在不同服务器上同时执行针对相同对象的并发数据定义DDL语句和数据操作DML语句
不建议使用外键功能
多主模式死锁。当一个组以多主模式运行时,SELECT … FOR UPDATE语句可能会导致死锁。这是因为锁不在组的成员之间共享,因此可能无法达到对这样的语句的期望。
在配置为群组复制的MySQL服务器实例上无法使用全局复制过滤器,因为在某些服务器上过滤事务会导致群组无法达成一致状态协议
一个复制组中的MySQL服务器成员的最大数量为9。如果有更多成员尝试加入该组,它们的请求将被拒绝。这个限制是通过测试和基准测试确定的,被认为是一个安全的边界,在稳定的局域网上该组能够可靠地运行。
事务太大以至于在5秒的时间窗口内无法在群组成员之间通过网络进行复制,那么成员可能会被怀疑已经失败,并因此被驱逐。
如果由于大型消息而发生不必要的驱逐,请使用系统变量group_replication_member_expel_timeout,在怀疑已经失败的成员被驱逐之前,允许额外的时间。
使用系统变量group_replication_transaction_size_limit来指定群组接受的最大事务大小。在MySQL 8.0中,该系统变量的默认值为150000000字节(约143 MB)的最大事务大小。超过此大小的事务将被回滚,并且不会发送到Group Replication的Group Communication System(GCS)以分发给群组.
使用系统变量group_replication_compression_threshold来指定应用压缩的消息大小上限。该系统变量的默认值为1000000字节(1 MB),因此会自动压缩大型消息。当Group Replication的Group Communication System(GCS)接收到一个由group_replication_transaction_size_limit设置允许但超过group_replication_compression_threshold设置的消息时,将执行压缩
使用系统变量group_replication_communication_max_message_size来指定消息大小,超过此大小的消息将被分段。该系统变量的默认值为10485760字节(10 MiB),因此大型消息将自动被分段。如果压缩后的消息仍然超过group_replication_communication_max_message_size限制,则GCS将在压缩后执行分段。为了让复制群组使用分段,所有群组成员必须使用MySQL 8.0.16或更高版本,并且群组使用的Group Replication通信协议版本必须允许分段
总之记住:你的应用程序中的事务尽可能的小
变量: MySQL :: MySQL 8.0 Reference Manual :: 18.9.1 Group Replication System Variables
状态:MySQL :: MySQL 8.0 Reference Manual :: 18.9.2 Group Replication Status Variables