写作背景:MySQL用传统的主从比较麻烦,用MGR可以一次性搞定。

一、MGR是什么?能解决什么问题?

MGR(MySQL Group Replication)是MySQL官方推出的组复制方案,说白了就是把多台MySQL服务器组成一个“小团队”,数据在团队成员之间实时同步,有人挂了也不影响业务 。

传统主从复制有哪些坑?

以前我们做高可用,基本就是主从复制那一套:

问题表现后果
复制延迟从库数据落后主库读写分离读到旧数据
主库挂了需要手动选主、切换业务中断几分钟起
数据不一致主从数据对不上切换后丢数据或错乱
脑裂两个库都以为自己是主数据写花了

MGR就是来填这些坑的 。

MGR的核心优势

  1. 数据强一致性:事务提交前,必须经过多数派节点确认(Paxos协议),保证数据不丢、不乱 

  2. 自动故障切换:主节点挂了,集群自动选新主,RTO通常在30秒内 

  3. 多节点写入(可选):支持多主模式,所有节点都能写(但有冲突风险,慎用)

  4. 弹性扩缩容:节点加入或退出,集群自动感知、重新配置

什么时候用MGR?

推荐场景 :

  • 金融交易、电商订单等核心业务(对数据一致性要求高)

  • SaaS多租户平台(需要高可用+数据隔离)

  • 跨机房部署(需要强同步复制)

不推荐场景

  • 单表日增量>1TB(大事务会拖垮集群)

  • 跨公网部署(网络延迟高,性能下降明显)

  • 业务有大量无主键表(MGR强制要求主键)

单主模式 vs 多主模式

我的建议:除非你是高手,否则只用单主模式 。

模式原理优点缺点
单主一个节点可写,其他只读稳定、冲突少、好管理写入有瓶颈
多主所有节点都能写扩展写能力冲突检测复杂,网络抖动就炸

阿里云官方文档都明确说:“多主模式下集群的稳定性很差,任意节点的抖动或故障,都会影响整个集群的可用性” 。所以下面我只讲单主模式。


二、从零搭建三节点MGR集群(单主模式)

环境规划

三台服务器(CentOS/Rocky/Ubuntu都行):

节点IP地址主机名角色
节点1192.168.1.10mgr01初始主节点
节点2192.168.1.11mgr02从节点
节点3192.168.1.12mgr03从节点

MySQL版本:8.0.22+(太老的版本有bug,建议用最新稳定版)

第一步:环境准备(三台都做)

1. 配置主机名解析

cat >> /etc/hosts << EOF
192.168.1.10 mgr01
192.168.1.11 mgr02
192.168.1.12 mgr03
EOF

2. 关闭防火墙或放行端口

MGR需要两个端口:

  • 3306:MySQL服务端口

  • 33061:MGR内部通信端口

# 简单粗暴关防火墙(生产环境建议只放行端口)
systemctl stop firewalld
systemctl disable firewalld

# 或者只放行端口
firewall-cmd --permanent --add-port=3306/tcp
firewall-cmd --permanent --add-port=33061/tcp
firewall-cmd --reload

第二步:安装MySQL(三台都做)

1. 添加MySQL官方yum源

# CentOS/Rocky
yum install -y https://dev.mysql.com/get/mysql80-community-release-el7-3.noarch.rpm

# Ubuntu
wget https://dev.mysql.com/get/mysql-apt-config_0.8.24-1_all.deb
dpkg -i mysql-apt-config_0.8.24-1_all.deb
apt update

2. 安装MySQL

yum install -y mysql-server

3. 初始化并启动

systemctl start mysqld
systemctl enable mysqld

# 查看初始密码
grep 'temporary password' /var/log/mysqld.log
# 输出类似: root@localhost: h<GL%Lr:v66W

4. 修改root密码并配置基础参数

mysql -uroot -p'初始密码'
ALTER USER 'root'@'localhost' IDENTIFIED BY '你的强密码123!';

第三步:配置MGR参数(三台都做)

编辑 /etc/my.cnf,在 [mysqld] 段下添加以下配置:

# 基础复制配置
server_id = 1   # 节点1设为1,节点2设为2,节点3设为3
gtid_mode = ON
enforce_gtid_consistency = ON
binlog_format = ROW
binlog_checksum = NONE
log_slave_updates = ON
log_bin = binlog
relay_log_info_repository = TABLE
master_info_repository = TABLE

# MGR核心配置
transaction_write_set_extraction = XXHASH64
loose-group_replication_group_name = "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"  # 所有节点相同
loose-group_replication_start_on_boot = OFF
loose-group_replication_local_address = "192.168.1.10:33061"  # 节点1写自己IP
loose-group_replication_group_seeds = "192.168.1.10:33061,192.168.1.11:33061,192.168.1.12:33061"
loose-group_replication_bootstrap_group = OFF
loose-group_replication_single_primary_mode = ON  # 单主模式
loose-group_replication_enforce_update_everywhere_checks = OFF

# 其他优化
disabled_storage_engines = "MyISAM,BLACKHOLE,FEDERATED,ARCHIVE,MEMORY"
binlog_transaction_dependency_tracking = WRITESET
slave_parallel_type = LOGICAL_CLOCK
slave_parallel_workers = 4

注意:三台服务器的 server_id 和 group_replication_local_address 要分别改成自己的。

改完后重启MySQL:

systemctl restart mysqld

第四步:安装MGR插件(三台都做)

mysql -uroot -p
INSTALL PLUGIN group_replication SONAME 'group_replication.so';
SHOW PLUGINS;  -- 看到 group_replication 状态为 ACTIVE 就对了

第五步:创建复制用户(三台都做)

-- 先临时关闭二进制日志记录,避免创建用户的操作被同步
SET SQL_LOG_BIN = 0;

-- 创建MGR内部通信用户
CREATE USER repl@'%' IDENTIFIED BY '你的密码123!';
GRANT REPLICATION SLAVE ON *.* TO repl@'%';
GRANT CONNECTION_ADMIN ON *.* TO repl@'%';
GRANT BACKUP_ADMIN ON *.* TO repl@'%';
GRANT GROUP_REPLICATION_STREAM ON *.* TO repl@'%';
FLUSH PRIVILEGES;

-- 恢复二进制日志
SET SQL_LOG_BIN = 1;

-- 配置复制通道
CHANGE MASTER TO MASTER_USER='repl', MASTER_PASSWORD='你的密码123!' FOR CHANNEL 'group_replication_recovery';

踩坑提醒:如果提示 super_read_only 相关错误,先执行 SET GLOBAL super_read_only = OFF; 再试 。

第六步:启动MGR集群

先在节点1(主节点)执行

-- 引导集群(只在第一个节点执行)
SET GLOBAL group_replication_bootstrap_group = ON;
START GROUP_REPLICATION;
SET GLOBAL group_replication_bootstrap_group = OFF;

-- 查看集群状态
SELECT * FROM performance_schema.replication_group_members;

如果正常,应该看到类似输出:

+---------------------------+--------------------------------------+-------------+-------------+--------------+
| CHANNEL_NAME              | MEMBER_ID                            | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| group_replication_applier | xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx | mgr01       |        3306 | ONLINE       |
+---------------------------+--------------------------------------+-------------+-------------+--------------+

然后在节点2和节点3(从节点)执行

START GROUP_REPLICATION;

-- 再次在主节点查看状态,应该三个都是 ONLINE
SELECT * FROM performance_schema.replication_group_members;

第七步:验证集群功能

1. 检查谁是主节点

SHOW VARIABLES LIKE 'read_only';
-- 主节点应为 OFF,从节点应为 ON

2. 测试同步

在主节点创建数据库和表:

CREATE DATABASE test;
USE test;
CREATE TABLE t1 (id INT PRIMARY KEY, name VARCHAR(20));
INSERT INTO t1 VALUES (1, 'mgr test');

在从节点查询:

USE test;
SELECT * FROM t1;  -- 应该能看到刚插入的数据

3. 测试只读限制

在从节点尝试写入:

USE test;
INSERT INTO t1 VALUES (2, 'write on slave');  
-- 应该报错:ERROR 1290 (HY000): The MySQL server is running with the --super-read-only option

4. 测试故障切换

模拟主节点宕机:

# 在节点1上
systemctl stop mysqld

在节点2或3上查看集群状态:

SELECT * FROM performance_schema.replication_group_members;
-- 会看到节点1状态变成 UNREACHABLE,然后被移除
-- 剩下两个节点中,其中一个会变成新的主节点(read_only变为OFF)

三、日常运维与监控

常用监控SQL

-- 查看所有成员状态
SELECT * FROM performance_schema.replication_group_members;

-- 查看成员统计信息
SELECT * FROM performance_schema.replication_group_member_stats\G

-- 查看各节点事务延迟
SELECT MEMBER_ID, COUNT_TRANSACTIONS_IN_QUEUE, COUNT_TRANSACTIONS_CHECKED
FROM performance_schema.replication_group_member_stats;

添加新节点

-- 在新节点上
-- 1. 配置好my.cnf,server_id唯一
-- 2. 安装插件
-- 3. 创建repl用户
-- 4. CHANGE MASTER TO ...
-- 5. START GROUP_REPLICATION;

删除节点

-- 在要删除的节点上
STOP GROUP_REPLICATION;

-- 如果想彻底清理,可以删除数据目录重新初始化

四、避坑指南

1. 表必须有主键

MGR强制要求所有表必须有显式主键,否则同步会失败。检查无主键表:

SELECT 
  t.table_schema, t.table_name
FROM 
  information_schema.tables t
LEFT JOIN information_schema.columns c 
  ON t.table_schema = c.table_schema 
  AND t.table_name = c.table_name 
  AND c.column_key = 'PRI'
WHERE 
  t.table_type = 'BASE TABLE'
  AND t.table_schema NOT IN ('information_schema', 'performance_schema', 'mysql', 'sys')
  AND c.table_name IS NULL;

2. 网络必须稳定

MGR对网络延迟非常敏感,实测跨机房延迟超过50ms,性能下降30%以上 。建议同机房部署,用专线。

3. 大事务是杀手

单个事务太大(>100MB)会阻塞整个集群,因为要等所有节点确认。拆分大事务,或者考虑用pt-archiver分批处理。

4. 内存要够

MGR的XCom层会占用额外内存(约1GB),认证信息数组也会占内存。官方建议内存≥8GB,否则容易OOM 。

5. 不建议用多主模式

别问我怎么知道的,网上那些吹多主的文章,写的人自己生产环境都不敢用。单主模式+读写分离,够用了。


五、总结

MGR是MySQL官方给出的高可用答案,核心优势就三点:

  1. 数据不丢:多数派确认机制

  2. 切换自动:不用半夜爬起来手动选主

  3. 运维简单:官方原生支持,不用套一堆外部脚本

适不适合你?

  • 如果你的业务对数据一致性要求高(钱、订单、库存),值得上

  • 如果只是个人博客、低并发内部系统,传统主从复制也能用

下一步

  • 搭好MGR后,可以搭配 MySQL Router 实现应用端自动读写分离 

  • 或者直接上 MySQL InnoDB Cluster,官方全套解决方案

1、MySQL Router:读写分离+自动故障转移

它是啥?

一个轻量级中间件(几百KB),部署在应用服务器上(和应用同机部署)。不存数据,只做转发。

有啥用?
  1. 读写分离:自动识别SQL是读还是写

    • INSERT/UPDATE/DELETE → 发到主节点

    • SELECT → 轮询发到从节点

  2. 自动故障转移:主库挂了,Router自动把写请求切到新主,应用只需要重试连接,不用改代码

  3. 端口隔离

    • 默认6446端口:写请求(连主库)

    • 默认6447端口:读请求(连从库)

怎么用?

你搭好MGR后,装个Router,执行一条命令让它“认识”你的集群:

mysqlrouter --bootstrap root@你的某个节点IP:3306

Router会自动从集群拉取拓扑信息,生成配置文件,然后你应用里改一下连接IP为Router的地址、端口6446/6447就行。

2、MySQL InnoDB Cluster:官方全家桶

它是啥?

MySQL官方出的一体化高可用解决方案。可以理解为:

text

InnoDB Cluster = MGR(你已搭好的) + MySQL Shell + MySQL Router
有啥用?
  1. 一键部署:用MySQL Shell几条命令,就能把MGR+Router全配好,不用你手动改那么多配置文件

  2. 自动运维

    • 添加节点:cluster.addInstance()

    • 移除节点:cluster.removeInstance()

    • 故障自动切换:MGR负责选主,Router负责切流量

  3. 统一管理:用Shell的cluster.status()就能看整个集群健康状态

3、现在的状态

已经手动搭好MGR了,其实就相当于InnoDB Cluster的“内核”已经跑起来了。接下来两条路:

  • 轻量级方案:只加个Router,实现读写分离+自动切换(半小时搞定)

  • 完整方案:用MySQL Shell把现有MGR“纳管”成InnoDB Cluster,以后加节点、做备份都更规范(适合生产环境)

可以先加个Router试试——装个Router,配一下,改应用连接IP,观察读写分离和故障切换效果。跑熟了之后,如果想更规范,再用MySQL Shell把现有集群“转正”成InnoDB Cluster。

结束语:本人写一些笔记记录,以及工作中遇到的一些问题,方便之后重复阅读,每个人的搭建和操作都不一样,但是可以参考一下,感谢您的点击和阅读。
Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐