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

说明

  1. server_id:三台节点必须唯一;示例设置为 101、102、103。
  2. group_replication_local_address:本机组复制监听地址,格式 IP:PORT,默认为 33061,可根据需要修改。
  3. group_replication_group_seeds:列出所有预期参与组复制的节点地址(包括自己和对端)。
  4. plugin_load_add = group_replication.so 加载插件。
  5. 其它 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_idlocal_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):

  1. 确认 my.cnfserver_id=102group_replication_local_address="192.168.1.102:33061"
  2. 确认已经执行过复制账号的创建。
  3. 确保 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

排查思路

  1. 检查网络互通:确保 33061 端口在防火墙或安全组中已开放。
  2. 检查账号授权:确认 rpl_user@'%' 在所有节点上已创建且拥有 REPLICATION SLAVE 权限,且密码一致。
  3. 检查配置文件差异

    • group_replication_group_seeds 是否包含正确的所有节点地址。
    • server_idgtid_modebinlog_formattransaction_write_set_extraction 等必须保持一致。
  4. 查看 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 认证失败。

排查思路

  1. 确认复制用户密码一致:在各节点上测试:

    mysql -urpl_user -pStrongRplPassw0rd! -h 192.168.1.101 -e "SELECT 1;"

    若密码错误,应在所有节点上重新 ALTER USER 'rpl_user'@'%' IDENTIFIED BY '...'FLUSH PRIVILEGES;

  2. 检查用户 Host 授权:如果授权给特定 IP,如 @'192.168.1.%',需确认 rpl_user 在目标节点访问时 Host 匹配。
  3. 确认 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 时,报错提示该节点未在组视图中。

排查思路

  1. 检查 View 信息
    在存活节点上:

    SELECT * FROM performance_schema.replication_group_members;

    确认视图中是否还存在该节点的记录,状态是否为 OFFLINE

  2. 尝试更新组成员配置
    如果视图中没有该节点记录,可能是 group_replication_member_expel_timeout 导致节点被踢出后未重新加入。
  3. 强制清理旧成员信息
    在目标节点上执行:

    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: ONLINEOFFLINERECOVERING 等。
  • 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 OperatorVitess)管理 MGR,可考虑更进一步自动化部署与运维。


9. 小结

本文通过一个三节点的实战演练,详细介绍了:

  1. MySQL MGR 基本概念与优势
  2. 环境与前提准备:主机名、网络互通、安装 MySQL、配置 my.cnf
  3. 创建复制用户与 GTID 设置
  4. 在三台节点上加载 group_replication 插件
  5. 在 Node A 上引导集群(bootstrap)并在 Node B、C 上加入
  6. 读写测试、节点故障验证与恢复
  7. 单主/多主模式切换、常见问题排查与自动 rejoin 脚本
  8. 对比 Galera/其他 HA 方案,帮助你理解选型依据

通过本指南,你应该能在自己的实验环境或生产环境中快速搭建一个高可用的 MySQL MGR 集群,并掌握基本的运维与故障排查方法。后续可结合 Kubernetes Operator、ProxySQL 等组件,进一步实现自动化部署、读写分离与流量监控,实现更完善的 HA 架构。

最后修改于:2025年06月07日 16:34

评论已关闭

推荐阅读

DDPG 模型解析,附Pytorch完整代码
2024年11月24日
DQN 模型解析,附Pytorch完整代码
2024年11月24日
AIGC实战——Transformer模型
2024年12月01日
Socket TCP 和 UDP 编程基础(Python)
2024年11月30日
python , tcp , udp
如何使用 ChatGPT 进行学术润色?你需要这些指令
2024年12月01日
AI
最新 Python 调用 OpenAi 详细教程实现问答、图像合成、图像理解、语音合成、语音识别(详细教程)
2024年11月24日
ChatGPT 和 DALL·E 2 配合生成故事绘本
2024年12月01日
omegaconf,一个超强的 Python 库!
2024年11月24日
【视觉AIGC识别】误差特征、人脸伪造检测、其他类型假图检测
2024年12月01日
[超级详细]如何在深度学习训练模型过程中使用 GPU 加速
2024年11月29日
Python 物理引擎pymunk最完整教程
2024年11月27日
MediaPipe 人体姿态与手指关键点检测教程
2024年11月27日
深入了解 Taipy:Python 打造 Web 应用的全面教程
2024年11月26日
基于Transformer的时间序列预测模型
2024年11月25日
Python在金融大数据分析中的AI应用(股价分析、量化交易)实战
2024年11月25日
AIGC Gradio系列学习教程之Components
2024年12月01日
Python3 `asyncio` — 异步 I/O,事件循环和并发工具
2024年11月30日
llama-factory SFT系列教程:大模型在自定义数据集 LoRA 训练与部署
2024年12月01日
Python 多线程和多进程用法
2024年11月24日
Python socket详解,全网最全教程
2024年11月27日