MySQL MGR高可用集群搭建实战指南
以下内容将从概念与架构入手,逐步演示如何在三台 Linux 主机上搭建 MySQL Group Replication(简称 MGR)高可用集群。全程配有详细的配置示例、ASCII 拓扑图解以及命令演示,帮助你快速上手并深入理解。
1. 概述与背景
1.1 什么是 MySQL Group Replication
MySQL Group Replication(MGR)是 MySQL 官方提供的一种多主机间的内置复制解决方案,具备以下特性:
- 多主(Multi-primary)/单主(Single-primary)模式:支持所有节点均可写入(Multi-primary),也可切换为只有一个节点可写入(Single-primary)。
- 自动故障检测与成员剔除:一旦某个节点宕机或网络抖动,其他节点可自动剔除该节点,保持集群可用性。
- 一致性保证:使用 Paxos 类协议实现通信,每条事务在提交前会与大多数节点达成一致;可选基于组通信协议(XA Two-Phase Commit)保证更强一致性。
- 易管理:无需手动配置
master/slave
拥有者与切换,所有成员逻辑对等,自动选主或切换角色。
在 MGR 集群中,只需要向某个节点提交写请求,事务提交后会自动在组内同步,不依赖传统的主从复制拓扑。MGR 通常用于构建高度可用的数据库服务层。
1.2 集群拓扑示意(ASCII 图解)
下面以一个典型的 三节点 MGR 集群为例,展示其逻辑拓扑:
+-----------+ +-----------+ +-----------+
| Node A | | Node B | | Node C |
| (MySQL) |<----->| (MySQL) |<----->| (MySQL) |
| | | | | |
+-----------+ +-----------+ +-----------+
^ ^ ^ ^ ^ ^
| | | | | |
客户端读写 集群内部组通信 监控/管理
- 三台物理或虚拟机(节点 A、B、C),每台安装 MySQL 8.0+。
- 节点之间通过 XCom(组复制专用网络)进行心跳与事务流转。
- 客户端可分别连接到任意节点进行读写(Multi-primary 模式下),只要大多数节点在线,均可正常工作。
2. 环境与前提
2.1 环境准备
以下示例在三台 CentOS 7/8 或 Ubuntu 18.04/20.04 的服务器上演示,主机名、IP 分别如下(仅作示例,可根据实际环境修改):
Node A
- 主机名:
mysql-a
- IP:
192.168.1.101
- 主机名:
Node B
- 主机名:
mysql-b
- IP:
192.168.1.102
- 主机名:
Node C
- 主机名:
mysql-c
- IP:
192.168.1.103
- 主机名:
三台主机之间需保证互通,尤其是 3306/TCP(MySQL 服务)和 组复制组播端口 33061/TCP。为了简化部署可开启防火墙策略或临时关闭防火墙、Selinux。
2.2 安装 MySQL 8.0
以 CentOS 为例,可通过官方 Yum 源安装:
# 安装 MySQL 官方仓库
rpm -Uvh https://repo.mysql.com/mysql80-community-release-el7-3.noarch.rpm
# 安装 MySQL 8.0 Server
yum install -y mysql-community-server
# 启动并设置开机自启
systemctl enable mysqld
systemctl start mysqld
# 查看随机生成的 root 密码
grep 'temporary password' /var/log/mysqld.log
# 示例输出:
# 2023-10-10T12:00:00.123456Z 1 [Note] A temporary password is generated for root@localhost: AbCdEfGhIjKl
然后使用 mysql_secure_installation
初始化 root 密码并关闭不安全设置,或手动修改密码。确保三台节点都安装相同 MySQL 版本(8.0.x 相同大版本)。
2.3 主机名与 DNS 配置
为方便组复制内部通信,建议在三台服务器 /etc/hosts
中添加对应映射:
192.168.1.101 mysql-a
192.168.1.102 mysql-b
192.168.1.103 mysql-c
并设置主机名:
# 以 root 用户在各自节点执行
hostnamectl set-hostname mysql-a # 对应节点 B、C 分别设置 mysql-b、mysql-c
确保 ping mysql-a
能够成功解析到 192.168.1.101
。
3. MySQL 配置
接下来,在三台节点上分别配置 MySQL,关键在于 my.cnf
中启用 Group Replication 相关参数。
3.1 全局配置示例
在三台机器上编辑 /etc/my.cnf.d/group_replication.cnf
或 /etc/mysql/my.cnf
中增加以下内容(只需修改一份,三台均保持一致):
# 仅示例片段,只列出关键部分
[mysqld]
# 基础属性
server_id = 101 # Node A 配置为 101,Node B 为 102,Node C 为 103
datadir = /var/lib/mysql
socket = /var/lib/mysql/mysql.sock
log_error = /var/log/mysql/error.log
pid_file = /var/run/mysqld/mysqld.pid
port = 3306
# InnoDB 相关(建议根据实际内存调整)
innodb_buffer_pool_size = 1G
innodb_flush_log_at_trx_commit = 1
innodb_file_per_table = 1
innodb_flush_method = O_DIRECT
# Group Replication 组通信网络配置
# 注意:必须在三个节点上都启用 group_replication 组件
loose-group_replication_group_name = "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee" # 任意 UUID
loose-group_replication_start_on_boot = off
loose-group_replication_local_address = "192.168.1.101:33061" # Node A
# Node B: "192.168.1.102:33061"; Node C: "192.168.1.103:33061"
loose-group_replication_group_seeds = "192.168.1.101:33061,192.168.1.102:33061,192.168.1.103:33061"
loose-group_replication_bootstrap_group = off
# 复制插件配置
plugin_load_add = group_replication.so
# 日志格式与 GTID
log_slave_updates = ON
enforce_gtid_consistency = ON
master_info_repository = TABLE
relay_log_info_repository = TABLE
relay_log_recovery = ON
transaction_write_set_extraction = XXHASH64
# binlog 与 purging
log_bin = mysql-bin
binlog_format = ROW
binlog_row_image = FULL
gtid_mode = ON
expire_logs_days = 3
说明:
server_id
:三台节点必须唯一;示例设置为 101、102、103。group_replication_local_address
:本机组复制监听地址,格式IP:PORT
,默认为33061
,可根据需要修改。group_replication_group_seeds
:列出所有预期参与组复制的节点地址(包括自己和对端)。plugin_load_add = group_replication.so
加载插件。- 其它 InnoDB、binlog、GTID 相关参数需保证一致,否则启动组复制时会报错。
修改完成后,重启三台节点的 MySQL 服务:
systemctl restart mysqld
3.2 验证插件是否加载
在 Node A 上登录 MySQL,执行:
mysql -uroot -p
SHOW PLUGINS\G
查看列表中是否存在 group_replication
且状态为 ACTIVE
。若未加载,可执行:
INSTALL PLUGIN group_replication SONAME 'group_replication.so';
然后再次 SHOW PLUGINS
验证。
4. 初始化 MGR 集群
至此,三台节点的 MySQL 基础配置已就绪,接下来依次在每台节点上执行一系列 SQL 命令,以创建复制账户、配置组复制用户、并启动组复制。
下面示例以 Node A(IP=192.168.1.101)为例演示完整流程,并在 Node B、Node C 上做相同操作(只需要修改 server_id
与 local_address
部分)。可以通过 SSH 或 kubectl exec
(若在容器中运行)连接到三台对应 MySQL 实例。
4.1 创建复制专用用户
在 任何一个节点(例如 Node A)上执行以下 SQL,为组复制创建用户,并在三台主机上都 grant 授权:
-- 登录 MySQL
mysql -uroot -p
-- 创建组复制用户(在所有节点都执行同样语句)
CREATE USER 'rpl_user'@'%' IDENTIFIED BY 'StrongRplPassw0rd!';
GRANT REPLICATION SLAVE ON *.* TO 'rpl_user'@'%';
FLUSH PRIVILEGES;
说明:
rpl_user
是组复制内部使用的账号,用于节点之间拉取 binlog。- 请根据安全要求设置强密码,或改为仅在内部网段授信。
在 Node B、Node C 上都执行以上两条语句,确保三台共享相同的 rpl_user
密码与权限。
4.2 验证 GTID 设置
在三台节点上分别执行:
SHOW VARIABLES LIKE 'gtid_mode';
确认 gtid_mode = ON
。若不是,请检查前面 my.cnf
中是否成功生效,重启后再次检查。
4.3 查看 InnoDB 引擎状态
确保 InnoDB 正常工作:
SHOW ENGINE INNODB STATUS\G
检查启动日志中无错误。
4.4 配置组复制相关系统变量
在 Node A 上执行(后续 B、C 同理,仅需替换 local_address
):
-- 登录 MySQL
mysql -uroot -p
-- 确保 group_replication 组件已就绪
SET GLOBAL group_replication_bootstrap_group = OFF; -- 非启动节点必须 OFF
注意:只有在第一个节点启动时,需要将bootstrap_group
置为ON
,而后续节点必须为OFF
。
4.5 启动首个节点(Bootstrap Group)
在 Node A 上执行以下命令,将其作为群集的“种子”节点启动组复制:
-- 登录 MySQL
mysql -uroot -p
-- 1. 确保自己是要引导的第一个成员
SET GLOBAL group_replication_bootstrap_group = ON;
-- 2. 启动组复制插件
START GROUP_REPLICATION;
-- 3. 重置 bootstrap 设置(仅当第一节点正常加入后)
SET GLOBAL group_replication_bootstrap_group = OFF;
此时,在 Node A 的 error log 中可以看到类似:
[Note] Group Replication: local member 1d0451b8-...: ONLINE, view UUID bcd123...
并执行:
SELECT * FROM performance_schema.replication_group_members;
应能看到一条记录,对应 Node A 自己,状态 ONLINE
。示例输出:
+--------------------------------------+---------------+-----------------+-----------+----------------+
| MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE | MEMBER_ROLE |
+--------------------------------------+---------------+-----------------+-------------+--------------+
| 1d0451b8-85f2-11eb-912d-080027e58898 | mysql-a | 33061 | ONLINE | PRIMARY |
+--------------------------------------+---------------+-----------------+-------------+--------------+
4.6 启动其余节点加入集群
节点 Node B(IP=192.168.1.102):
- 确认
my.cnf
中server_id=102
,group_replication_local_address="192.168.1.102:33061"
。 - 确认已经执行过复制账号的创建。
- 确保
group_replication_bootstrap_group = OFF
。
登录后执行:
mysql -uroot -p
-- 启动组复制
START GROUP_REPLICATION;
然后查询:
SELECT MEMBER_HOST, MEMBER_STATE FROM performance_schema.replication_group_members;
此时可见 Node A、Node B 都已 ONLINE。类似:
+-----------+-------------+
| MEMBER_HOST | MEMBER_STATE |
+-------------+-------------+
| mysql-a | ONLINE |
| mysql-b | ONLINE |
+-------------+-------------+
重复Node C(IP=192.168.1.103)同样步骤:
mysql -uroot -p
START GROUP_REPLICATION;
SELECT MEMBER_HOST, MEMBER_STATE FROM performance_schema.replication_group_members;
期望结果:
+-----------+-------------+
| MEMBER_HOST | MEMBER_STATE |
+-------------+-------------+
| mysql-a | ONLINE |
| mysql-b | ONLINE |
| mysql-c | ONLINE |
+-------------+-------------+
此时,三节点 MGR 集群已建成,各自为组复制对等节点,传播事务达成一致。
5. 测试及常用操作
5.1 写入测试(Multi-primary 模式)
默认情况下,启用 MGR 后处于 Multi-primary 模式,所有节点都可写入。选择一个节点插入数据:
mysql -u root -p -h 192.168.1.101
USE testdb;
CREATE DATABASE IF NOT EXISTS testdb;
USE testdb;
CREATE TABLE t1(id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(20));
INSERT INTO t1(name) VALUES('Alice'),('Bob');
然后在其他两个节点验证是否同步:
mysql -uroot -p -h 192.168.1.102 -e "SELECT * FROM testdb.t1;"
mysql -uroot -p -h 192.168.1.103 -e "SELECT * FROM testdb.t1;"
应都能看到两条记录。
5.2 故障测试(节点下线与自动选举)
5.2.1 模拟节点挂掉
在 Node B 上停止 MySQL 服务:
ssh root@mysql-b "systemctl stop mysqld"
此时 Node B 会被剔除组复制视图,查看任意存活节点上的成员状态:
SELECT MEMBER_HOST, MEMBER_STATE FROM performance_schema.replication_group_members;
应看到 Node B 变为 OFFLINE
或直接消失,剩余两个节点仍为 ONLINE
。应用仍可继续读写。
5.2.2 恢复节点
重启 Node B MySQL:
ssh root@mysql-b "systemctl start mysqld"
之后在 Node B 上执行:
mysql -uroot -p
START GROUP_REPLICATION;
Node B 会自动拉取最新事务并回到 ONLINE 状态。最终再查询视图:
SELECT MEMBER_HOST, MEMBER_STATE FROM performance_schema.replication_group_members;
即可看到三节点均为 ONLINE
。
5.3 单主模式(Single-primary)切换
若希望整个集群只有一个节点可写入,其他节点只做只读,可在任一节点执行:
-- 将集群切换为 Single-primary
mysql> SET GLOBAL group_replication_single_primary_mode = ON;
-- 在当前节点设置其为 PRIMARY
mysql> SELECT MEMBER_HOST, MEMBER_ROLE FROM performance_schema.replication_group_members;
-- 如果当前节点不是 PRIMARY,执行:
mysql> SET GLOBAL group_replication_primary_member = 'mysql-a:33061';
此后,在 PRIMARY
节点上可执行写操作;在其他节点若尝试写,会报 “Write operations are not allowed in secondary mode” 错误。
要恢复多主模式,执行:
SET GLOBAL group_replication_single_primary_mode = OFF;
6. 常见问题与排查
在实际部署与运行中,可能会遇到以下常见问题,结合对应排查思路快速定位与解决。
6.1 无法加入集群:Member X requested state CHANGE but cannot change to JOINED
问题症状
启动第二个节点时,在 error log 中看到:
[ERROR] Group Replication: Member jklmn cannot join group.
Member jklmn requested state CHANGE but cannot change to JOINED
排查思路
- 检查网络互通:确保
33061
端口在防火墙或安全组中已开放。 - 检查账号授权:确认
rpl_user@'%'
在所有节点上已创建且拥有REPLICATION SLAVE
权限,且密码一致。 检查配置文件差异:
group_replication_group_seeds
是否包含正确的所有节点地址。server_id
、gtid_mode
、binlog_format
、transaction_write_set_extraction
等必须保持一致。
查看 error log 详细信息:
grep -i "replication" /var/log/mysql/error.log
根据提示进一步定位。
6.2 写入失败:ERROR 1845 (HY000): Access denied for user 'rpl_user'@'...'
问题症状
在 Node B 或 C 启动组复制时,报 Access denied
错误,提示 rpl_user
认证失败。
排查思路
确认复制用户密码一致:在各节点上测试:
mysql -urpl_user -pStrongRplPassw0rd! -h 192.168.1.101 -e "SELECT 1;"
若密码错误,应在所有节点上重新
ALTER USER 'rpl_user'@'%' IDENTIFIED BY '...'
并FLUSH PRIVILEGES;
。- 检查用户 Host 授权:如果授权给特定 IP,如
@'192.168.1.%'
,需确认rpl_user
在目标节点访问时 Host 匹配。 - 确认
skip_name_resolve
:若在my.cnf
中启用了skip_name_resolve=ON
,则需用纯 IP 授权('rpl_user'@'192.168.1.101'
),否则解析 Hostname 可能出错。
6.3 数据冲突:Caught exception: Group Replication conflict with ...
问题症状
在多主模式下,如果两台节点同时写入同一个主键,某节点可能会报冲突错误:
ERROR 1644 (ER_SIGNAL_EXCEPTION): Caught exception: Group Replication conflict...
解释与建议
- 这是内置冲突检测机制,当不同节点对同一行执行不一致写时,会在某个节点检测到冲突,并回滚该事务。
- 解决方案:尽量将同一数据写负载通过 Proxy 分流,或者在业务层面做分布式 ID 生成(如使用 UUID、雪花算法)避免主键冲突。
- 若业务允许一次写冲突回滚,再重试即可;否则需改为单主写或分库分表。
6.4 节点下线后无法恢复:Member X is not found in the group view
问题症状
某节点宕机后重启,执行 START GROUP_REPLICATION
时,报错提示该节点未在组视图中。
排查思路
检查 View 信息:
在存活节点上:SELECT * FROM performance_schema.replication_group_members;
确认视图中是否还存在该节点的记录,状态是否为
OFFLINE
。- 尝试更新组成员配置:
如果视图中没有该节点记录,可能是group_replication_member_expel_timeout
导致节点被踢出后未重新加入。 强制清理旧成员信息:
在目标节点上执行:STOP GROUP_REPLICATION; RESET MASTER; -- 若 GTID 与日志冲突,可考虑清空 binlog SET GLOBAL group_replication_bootstrap_group = OFF; START GROUP_REPLICATION;
或在存活节点上先使用:
-- 标记该节点为离线并剔除 CALL mysql.rds_kill_master('mysql-c', 3306);
再让目标节点重新启动加入。
7. 管理与监控
为了保证 MGR 集群长期稳定运行,需要借助一些监控与运维手段。
7.1 查看组复制状态
7.1.1 成员视图
SELECT
MEMBER_ID,
MEMBER_HOST,
MEMBER_PORT,
MEMBER_STATE,
MEMBER_ROLE
FROM performance_schema.replication_group_members;
- MEMBER\_STATE:
ONLINE
、OFFLINE
、RECOVERING
等。 - MEMBER\_ROLE:
PRIMARY
(当前写入节点)或SECONDARY
(只读节点)。
7.1.2 插件状态
SHOW STATUS LIKE 'group_replication_%';
常用字段:
group_replication_primary_members
: 当前 PRIMARY 节点列表group_replication_local_state
: 本地节点状态group_replication_group_size
: 组内成员数
7.2 高可用监控与自动故障转移
MGR 本身可自动剔除故障节点,但故障节点恢复后不会自动重新加入,需要人工或脚本触发重新 START GROUP_REPLICATION
。可以编写如下简易脚本,在节点重启后自动尝试加入:
#!/bin/bash
# mgr_auto_rejoin.sh
MYSQL_USER="root"
MYSQL_PASS="YourRootPasswd"
# 检查本机组复制状态
STATUS=$(mysql -u${MYSQL_USER} -p${MYSQL_PASS} -e "SELECT VARIABLE_VALUE FROM performance_schema.global_status WHERE VARIABLE_NAME='group_replication_local_state'" -s -N)
if [ "$STATUS" != "ONLINE" ]; then
echo "本节点非 ONLINE,尝试重新加入集群..."
mysql -u${MYSQL_USER} -p${MYSQL_PASS} -e "START GROUP_REPLICATION;"
sleep 5
NEW_STATUS=$(mysql -u${MYSQL_USER} -p${MYSQL_PASS} -e "SELECT VARIABLE_VALUE FROM performance_schema.global_status WHERE VARIABLE_NAME='group_replication_local_state'" -s -N)
if [ "$NEW_STATUS" == "ONLINE" ]; then
echo "节点成功重新加入 GROUP."
else
echo "重试失败,当前状态:$NEW_STATUS"
fi
else
echo "本节点已经在线,无需操作."
fi
可将此脚本放在节点启动后执行(如 crontab 或 systemd service),自动检测并加入集群。
8. 拓展:ZooKeeper vs Group Replication
虽然本指南专注于 MySQL 官方 MGR,但在生产环境中也常见 基于 Galera(MariaDB/Galera Cluster)或 使用 ZooKeeper 协调 的高可用方案。MGR 与它们相比的优缺点:
MGR 优点
- 原生集成 MySQL,无需额外安装 Galera 库或外部协调组件(如 ZooKeeper)。
- 使用 GTID 保证全局唯一性与一致性。
- 多主写入、自动故障剔除,可选单主模式。
MGR 缺点
- 对网络延迟敏感,推荐节点间 RTT < 5ms。
- 写冲突处理需额外关注,可能导致事务回滚。
- 配置相对复杂,资源消耗较高。
Galera 优点
- 同样支持多主热备,且同步延迟近乎为 0。
- 社区成熟,文档与平台兼容性好。
Galera 缺点
- 需安装额外 Galera 插件,且与 MySQL 官方主线版本存在分支差异。
- 对大事务群集通信压测存在瓶颈。
若已有 ZooKeeper/Kafka 等组件,或已使用 Kubernetes Operator(如 Oracle MySQL Operator 或 Vitess)管理 MGR,可考虑更进一步自动化部署与运维。
9. 小结
本文通过一个三节点的实战演练,详细介绍了:
- MySQL MGR 基本概念与优势
- 环境与前提准备:主机名、网络互通、安装 MySQL、配置
my.cnf
- 创建复制用户与 GTID 设置
- 在三台节点上加载
group_replication
插件 - 在 Node A 上引导集群(bootstrap)并在 Node B、C 上加入
- 读写测试、节点故障验证与恢复
- 单主/多主模式切换、常见问题排查与自动 rejoin 脚本
- 对比 Galera/其他 HA 方案,帮助你理解选型依据
通过本指南,你应该能在自己的实验环境或生产环境中快速搭建一个高可用的 MySQL MGR 集群,并掌握基本的运维与故障排查方法。后续可结合 Kubernetes Operator、ProxySQL 等组件,进一步实现自动化部署、读写分离与流量监控,实现更完善的 HA 架构。
评论已关闭