传统MySQL主从复制需要手动切换故障节点,无法满足高可用场景下"秒级自动恢复"的需求。MySQL Group Replication(MGR,组复制)基于Paxos协议实现多节点数据同步与自动故障切换,无需依赖Keepalived、MHA等第三方工具,是MySQL官方推荐的高可用解决方案。
一、MGR核心认知
1.1 MGR对比传统主从的优势
| 特性 | 传统主从复制 | MySQL Group Replication |
|---|---|---|
| 故障切换 | 手动切换 | 自动选举新主节点,秒级恢复 |
| 数据一致性 | 异步/半同步,易不一致 | 强一致性(基于Paxos协议) |
| 集群管理 | 依赖第三方工具 | 原生支持集群管理,无需额外组件 |
| 节点角色 | 主从固定 | 单主/多主模式,角色自动切换 |
| 脑裂风险 | 高 | 低(奇数节点仲裁) |
1.2 MGR核心原理
MGR集群由至少3个节点组成(奇数节点,保证投票仲裁),单主模式下:
- 集群选举出1个主节点(Primary) 处理所有写入操作,其余为从节点(Secondary) 只读;
- 主节点将事务同步到集群,所有节点通过组通信协议(XCom)达成共识后,才提交事务,保证数据一致性;
- 主节点故障时,集群自动检测并通过投票选举新主节点,从节点无缝接管写入,无需人工干预。
1.3 环境规划(单主模式)
| 节点角色 | 服务器IP | MySQL版本 | 核心配置 | 端口说明 |
|---|---|---|---|---|
| MGR节点1(初始主) | 192.168.1.30 | 8.0.36 | 4核8G,500G硬盘 | 3306(MySQL服务)、33061(MGR通信) |
| MGR节点2 | 192.168.1.31 | 8.0.36 | 4核8G,500G硬盘 | 3306、33061 |
| MGR节点3 | 192.168.1.32 | 8.0.36 | 4核8G,500G硬盘 | 3306、33061 |
1.4 前置准备
-
所有节点操作系统:CentOS 7.x(关闭SELinux、防火墙开放3306/33061端口);
-
同步系统时间:
ntpdate ntp.aliyun.com; -
禁用AppArmor/SELinux:
setenforce 0 && sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config; -
开放端口:
bashfirewall-cmd --add-port=3306/tcp --permanent firewall-cmd --add-port=33061/tcp --permanent firewall-cmd --reload
二、第一步:所有节点安装并配置MySQL 8.0
MGR对MySQL版本要求严格(推荐8.0.20+),以下步骤需在所有3个节点执行。
2.1 安装MySQL 8.0
bash
# 1. 安装MySQL YUM源
wget https://dev.mysql.com/get/mysql80-community-release-el7-7.noarch.rpm
rpm -ivh mysql80-community-release-el7-7.noarch.rpm
# 2. 安装MySQL服务器(忽略GPG检查,避免版本兼容问题)
yum install -y mysql-community-server --nogpgcheck
# 3. 启动MySQL并设置开机自启
systemctl start mysqld
systemctl enable mysqld
# 4. 获取初始密码
initial_pass=$(grep 'temporary password' /var/log/mysqld.log | awk '{print $NF}')
echo "初始密码:$initial_pass"
2.2 初始化MySQL(修改密码、配置权限)
bash
# 1. 登录MySQL并修改root密码(需符合复杂度:大小写+数字+特殊字符)
mysql -u root -p"$initial_pass" -e "ALTER USER 'root'@'localhost' IDENTIFIED BY 'MySQL@123456'; FLUSH PRIVILEGES;"
# 2. 远程访问授权(生产环境建议限制IP,此处为测试放开)
mysql -u root -p"MySQL@123456" -e "CREATE USER 'root'@'%' IDENTIFIED BY 'MySQL@123456'; GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' WITH GRANT OPTION; FLUSH PRIVILEGES;"
2.3 配置MGR核心参数(修改my.cnf)
编辑/etc/my.cnf,替换原有配置为以下内容(注意替换server-id和group_replication_local_address为节点对应值):
节点1(192.168.1.30)my.cnf配置
ini
[mysqld]
# 基础配置
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
lower_case_table_names=1
character-set-server=utf8mb4
collation-server=utf8mb4_unicode_ci
# MGR核心配置
server-id=30 # 每个节点唯一,建议用IP最后一段
gtid_mode=ON # 开启GTID,MGR必需
enforce_gtid_consistency=ON
master_info_repository=TABLE
relay_log_info_repository=TABLE
binlog_checksum=NONE
log_slave_updates=ON
binlog_format=ROW
transaction_write_set_extraction=XXHASH64 # MGR用于检测冲突的哈希算法
loose-group_replication_group_name="aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" # 固定UUID,所有节点一致
loose-group_replication_start_on_boot=OFF # 不随MySQL启动自动启动MGR
loose-group_replication_local_address="192.168.1.30:33061" # 当前节点MGR通信地址
loose-group_replication_group_seeds="192.168.1.30:33061,192.168.1.31:33061,192.168.1.32:33061" # 所有节点通信地址
loose-group_replication_bootstrap_group=OFF # 仅初始化集群时设为ON
loose-group_replication_single_primary_mode=ON # 单主模式(核心:自动故障切换依赖此模式)
loose-group_replication_enforce_update_everywhere_checks=OFF # 单主模式设为OFF
loose-group_replication_auto_increment_increment=7 # 避免主键冲突
节点2(192.168.1.31)my.cnf配置
仅修改以下2处,其余与节点1一致:
ini
server-id=31
loose-group_replication_local_address="192.168.1.31:33061"
节点3(192.168.1.32)my.cnf配置
仅修改以下2处:
ini
server-id=32
loose-group_replication_local_address="192.168.1.32:33061"
2.4 重启MySQL并验证配置
bash
# 重启MySQL
systemctl restart mysqld
# 验证GTID是否开启(输出ON即正常)
mysql -u root -p"MySQL@123456" -e "SHOW VARIABLES LIKE 'gtid_mode';"
三、第二步:搭建MGR集群(单主模式)
3.1 步骤1:在所有节点创建MGR专用用户
MGR需要专用用户用于节点间通信,登录每个节点执行:
bash
mysql -u root -p"MySQL@123456" << EOF
# 创建MGR通信用户
CREATE USER 'mgr_repl'@'%' IDENTIFIED BY 'MGR@123456';
# 授予MGR所需权限
GRANT REPLICATION SLAVE ON *.* TO 'mgr_repl'@'%';
GRANT GROUP_REPLICATION_ADMIN ON *.* TO 'mgr_repl'@'%';
FLUSH PRIVILEGES;
# 配置MGR插件使用该用户
CHANGE MASTER TO MASTER_USER='mgr_repl', MASTER_PASSWORD='MGR@123456' FOR CHANNEL 'group_replication_recovery';
EOF
3.2 步骤2:初始化MGR集群(仅节点1执行)
节点1作为初始主节点,负责引导集群创建:
bash
mysql -u root -p"MySQL@123456" << EOF
# 加载MGR插件(8.0+默认内置,无需手动安装)
INSTALL PLUGIN group_replication SONAME 'group_replication.so';
# 启动集群引导(仅第一次执行)
SET GLOBAL group_replication_bootstrap_group=ON;
START GROUP_REPLICATION;
SET GLOBAL group_replication_bootstrap_group=OFF;
# 验证集群状态(输出ON即正常)
SELECT * FROM performance_schema.replication_group_members;
EOF
执行后查看replication_group_members,节点1状态应为ONLINE,角色为PRIMARY。
3.3 步骤3:节点2、3加入集群
节点2执行:
bash
mysql -u root -p"MySQL@123456" << EOF
# 加载MGR插件
INSTALL PLUGIN group_replication SONAME 'group_replication.so';
# 加入集群
START GROUP_REPLICATION;
# 验证节点状态
SELECT * FROM performance_schema.replication_group_members;
EOF
节点3执行:
与节点2命令完全一致,执行后验证节点状态。
3.4 验证集群搭建成功
在任意节点执行以下命令,查看集群成员状态:
bash
mysql -u root -p"MySQL@123456" -e "SELECT MEMBER_HOST, MEMBER_ROLE, MEMBER_STATE FROM performance_schema.replication_group_members;"
正常输出示例:
| MEMBER_HOST | MEMBER_ROLE | MEMBER_STATE |
|---|---|---|
| 192.168.1.30 | PRIMARY | ONLINE |
| 192.168.1.31 | SECONDARY | ONLINE |
| 192.168.1.32 | SECONDARY | ONLINE |
3个节点均为ONLINE,且节点1为PRIMARY,说明集群搭建成功。 |
四、第三步:验证自动故障切换
4.1 前置测试:主节点写入数据
在节点1(主节点)插入测试数据,验证从节点同步:
bash
# 节点1执行:创建测试库和表
mysql -u root -p"MySQL@123456" << EOF
CREATE DATABASE IF NOT EXISTS mgr_test;
USE mgr_test;
CREATE TABLE user (id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(50));
INSERT INTO user (name) VALUES ('MGR测试用户1'), ('MGR测试用户2');
EOF
# 节点2/3执行:查询数据(应同步成功)
mysql -u root -p"MySQL@123456" -e "SELECT * FROM mgr_test.user;"
4.2 模拟主节点故障(停止节点1的MySQL)
bash
# 节点1执行:停止MySQL服务,模拟故障
systemctl stop mysqld
4.3 验证自动选举新主节点
等待5~10秒(MGR故障检测默认超时约5秒),在节点2执行以下命令:
bash
mysql -u root -p"MySQL@123456" -e "SELECT MEMBER_HOST, MEMBER_ROLE, MEMBER_STATE FROM performance_schema.replication_group_members;"
预期输出(节点2或3被选举为新主):
| MEMBER_HOST | MEMBER_ROLE | MEMBER_STATE |
|---|---|---|
| 192.168.1.30 | UNREACHABLE | OFFLINE |
| 192.168.1.31 | PRIMARY | ONLINE |
| 192.168.1.32 | SECONDARY | ONLINE |
4.4 验证新主节点写入功能
在新主节点(如节点2)插入数据,验证写入正常:
bash
# 节点2执行:插入数据
mysql -u root -p"MySQL@123456" << EOF
USE mgr_test;
INSERT INTO user (name) VALUES ('故障切换后写入');
EOF
# 节点3执行:查询数据(应同步新数据)
mysql -u root -p"MySQL@123456" -e "SELECT * FROM mgr_test.user;"
4.5 故障节点恢复后重新加入集群
节点1修复后,重启MySQL并重新加入集群:
bash
# 节点1执行:重启MySQL
systemctl start mysqld
# 重新加入集群
mysql -u root -p"MySQL@123456" << EOF
START GROUP_REPLICATION;
# 验证状态(此时节点1为SECONDARY)
SELECT MEMBER_HOST, MEMBER_ROLE FROM performance_schema.replication_group_members;
EOF
五、MGR集群生产环境优化
5.1 配置自动重启MGR
编辑/etc/my.cnf,添加以下配置(所有节点),确保MySQL重启后MGR自动启动:
ini
loose-group_replication_start_on_boot=ON
5.2 监控集群状态
5.2.1 核心监控SQL
bash
# 1. 集群成员状态
SELECT MEMBER_HOST, MEMBER_ROLE, MEMBER_STATE FROM performance_schema.replication_group_members;
# 2. MGR运行状态
SHOW STATUS LIKE 'group_replication%';
# 3. 事务冲突(生产环境需监控)
SELECT * FROM performance_schema.replication_group_conflicts;
5.2.2 结合Prometheus+Grafana监控
- 安装MySQL Exporter,配置监控指标;
- 导入MGR专用监控模板(Grafana ID:14050),重点监控:
- 节点在线状态、角色;
- 事务同步延迟;
- 集群冲突数;
- MGR通信端口连通性。
5.3 数据备份策略
MGR仅保证集群内数据一致,仍需定期备份:
-
开启binlog日志,设置过期时间:
binlog_expire_logs_seconds=604800(7天); -
每天在从节点执行全量备份:
bashmysqldump -u root -p"MySQL@123456" --all-databases --single-transaction --master-data=2 > /backup/mysql_full_$(date +%Y%m%d).sql
5.4 权限最小化(生产环境必做)
-
MGR通信用户仅授予必要权限,取消远程全量授权:
sqlREVOKE ALL PRIVILEGES ON *.* FROM 'mgr_repl'@'%'; GRANT REPLICATION SLAVE, GROUP_REPLICATION_ADMIN ON *.* TO 'mgr_repl'@'192.168.1.%'; FLUSH PRIVILEGES; -
root用户限制IP访问:
CREATE USER 'root'@'192.168.1.%' IDENTIFIED BY 'MySQL@123456';。
六、常见问题与解决
6.1 节点加入集群失败(MEMBER_STATE=ERROR)
- 原因:节点server-id重复、GTID不一致、防火墙未开放33061端口;
- 解决:
- 检查
server-id是否唯一; - 重置GTID:
RESET MASTER;; - 验证33061端口连通性:
telnet 192.168.1.30 33061。
- 检查
6.2 故障切换后新主节点无法写入
-
原因:单主模式未开启、
super_read_only未自动关闭; -
解决:
sqlSET GLOBAL group_replication_single_primary_mode=ON; SET GLOBAL super_read_only=OFF;
6.3 集群脑裂(节点状态不一致)
- 原因:网络分区、节点数量为偶数;
- 解决:
- 保证集群节点数为奇数(3/5/7);
- 配置
group_replication_member_expel_timeout=5(缩短节点驱逐超时)。