一、MySQL高可用之组复制(MGR)
1.1 组复制核心特性与优势
MySQL Group Replication(MGR)是基于分布式一致性协议(Paxos)实现的高可用集群方案,核心特性包括:
自动故障检测与恢复:集群自动检测故障节点,并通过选举机制产生新主节点(单主模式)。
数据一致性保障:读写事务需经过集群多数节点(>N/2)确认后才能提交,避免数据分裂。
弹性扩展:支持动态添加 / 移除节点,无需中断集群服务。
两种运行模式:单主模式(仅 1 个可写节点)和多主模式(所有节点可写)。
1.2 组复制架构原理
组复制依赖以下核心组件:
组通信系统(GCS):负责节点间消息传递(如事务日志、心跳检测),基于 TCP 协议实现。
一致性协议层:采用 Paxos 算法确保事务在集群中的顺序一致性。
事务验证层:检测并发事务冲突(多主模式下),避免数据不一致。
工作流程简述:
(1)主节点(单主模式)或任意节点(多主模式)接收写事务。
(2)事务执行前生成预写日志(WAL),并广播至集群所有节点。
(3)所有节点验证事务合法性(如无冲突),并通过一致性协议达成提交顺序共识。
(4)多数节点确认后,事务在所有节点提交,确保全局一致。
1.3 单主模式组复制实现(实战步骤)
环境准备
IP地址 | server-id | |
候选主节点 | 192.168.168.200 | 200 |
从节点1 | 192.168.168.129 | 129 |
从节点2 | 192.168.168.130 | 130 |
步骤1:所有节点基础配置(my.cnf)
[mysqld]
# 基础配置
server-id=200 # 每个节点唯一(200/129/130)
datadir=/data/mysql
socket=/data/mysql/mysql.sock
pid-file=/data/mysql/mysql.pid# 二进制日志与GTID(MGR依赖GTID)
log_bin=/data/mysql/binlog
binlog_format=ROW # 必须为ROW格式
log_slave_updates=ON # 从库同步的事务写入自身binlog
gtid_mode=ON # 启用GTID
enforce_gtid_consistency=ON # 强制GTID一致性# 组复制相关配置
transaction_write_set_extraction=XXHASH64 # 事务写入集提取算法
loose-group_replication_group_name="aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" # 集群UUID(自定义)
loose-group_replication_start_on_boot=OFF # 不自动启动组复制
loose-group_replication_local_address="192.168.168.200:33061" # 本节点组通信端口(每个节点修改IP)
loose-group_replication_group_seeds="192.168.168.200:33061,192.168.168.129:33061,192.168.168.130:33061" # 集群种子节点
loose-group_replication_bootstrap_group=OFF # 仅初始化集群时设为ON
loose-group_replication_single_primary_mode=ON # 启用单主模式
重启所有节点使配置生效:
systemctl restart mysqld
步骤2:创建组复制专用账户(所有节点执行)
登录MySQL,创建用于节点间通信的账户:
-- 创建复制用户(允许所有集群节点访问)
CREATE USER 'grp_user'@'192.168.168.%' IDENTIFIED BY 'Grp@123';
-- 授予复制权限
GRANT REPLICATION SLAVE ON *.* TO 'grp_user'@'192.168.168.%';
-- 刷新权限
FLUSH PRIVILEGES;
步骤3:配置复制通道(所有节点执行)
设置基于GTID的复制通道,用于组内事务同步:
-- 停止现有复制(若有)
STOP REPLICA;-- 配置组复制通道
CHANGE REPLICATION SOURCE TO
SOURCE_USER='grp_user',
SOURCE_PASSWORD='Grp@123',
SOURCE_AUTO_POSITION=1
FOR CHANNEL 'group_replication_recovery';
步骤4:安装组复制插件(所有节点执行)
-- 安装组复制插件
INSTALL PLUGIN group_replication SONAME 'group_replication.so';-- 验证插件是否安装成功
SHOW PLUGINS LIKE 'group_replication';
输出示例(状态为ACTIVE表示成功):
+-------------------+----------+--------------------+----------------------+---------+
| Name | Status | Type | Library | License |
+-------------------+----------+--------------------+----------------------+---------+
| group_replication | ACTIVE | GROUP REPLICATION | group_replication.so | GPL |
+-------------------+----------+--------------------+----------------------+---------+
步骤5:初始化集群(仅在第一个节点执行)
在 192.168.168.200(候选主节点)上引导集群:
-- 启动集群初始化(仅第一次执行)
SET GLOBAL group_replication_bootstrap_group=ON;-- 启动组复制
START GROUP_REPLICATION;-- 关闭初始化开关(避免重复初始化)
SET GLOBAL group_replication_bootstrap_group=OFF;
步骤6:添加其他节点到集群(129和130节点执行)
-- 启动组复制,自动加入集群
START GROUP_REPLICATION;
步骤7:验证集群状态
-- 启动组复制,自动加入集群 START GROUP_REPLICATION;
SELECT * FROM performance_schema.replication_group_members;
输出示例(单主模式下MEMBER_ROLE
为 PRIMARY 的是主节点):
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
| CHANNEL_NAME | MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE | MEMBER_ROLE | MEMBER_VERSION |
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
| group_replication_applier | 200e5b9a-732b-11f0-971f-000c29d6adc7 | 192.168.168.200 | 3306 | ONLINE | PRIMARY | 8.0.40 |
| group_replication_applier | 129e5b9a-732b-11f0-971f-000c29d6adc7 | 192.168.168.129 | 3306 | ONLINE | SECONDARY | 8.0.40 |
| group_replication_applier | 130e5b9a-732b-11f0-971f-000c29d6adc7 | 192.168.168.130 | 3306 | ONLINE | SECONDARY | 8.0.40 |
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
1.4 单主模式故障转移测试
1.模拟主节点故障:在主节点(200)执行停机命令:
systemctl stop mysqld
2.查看集群状态:在从节点(129)执行:
SELECT * FROM performance_schema.replication_group_members;
输出中会显示原主节点状态为UNREACHABLE
,约 30 秒后集群自动选举新主(如 129 节点变为 PRIMARY)。
3.恢复原主节点:重启 200 节点后,自动以从节点身份加入集群:
systemctl start mysqld
登录 200 节点的 MySQL,启动组复制:
START GROUP_REPLICATION;
再次查看集群状态,200 节点角色变为 SECONDARY。
1.5 多主模式组复制配置(扩展)
多主模式允许所有节点同时处理写事务,适合高并发写入场景,配置差异如下:
1.修改所有节点的my.cnf:
loose-group_replication_single_primary_mode=OFF # 关闭单主模式(启用多主)
loose-group_replication_enforce_update_everywhere_checks=ON # 强制多主更新检查
2.重启节点并重新初始化集群(参考单主模式步骤5-6):
-- 在第一个节点执行
SET GLOBAL group_replication_bootstrap_group=ON;
START GROUP_REPLICATION;
SET GLOBAL group_replication_bootstrap_group=OFF;-- 其他节点执行
START GROUP_REPLICATION;
3.验证多主模式:所有节点的MEMBER_ROLE
均为 PRIMARY:
SELECT MEMBER_HOST, MEMBER_ROLE FROM performance_schema.replication_group_members;
1.6 组复制监控与维护
1.查看集群健康状态:
-- 集群成员状态
SELECT * FROM performance_schema.replication_group_members;-- 事务冲突统计(多主模式)
SELECT * FROM performance_schema.replication_group_member_stats;
2.动态添加节点:
-- 在新节点执行(参考步骤2-4配置后)
START GROUP_REPLICATION;
3.移除节点:
-- 在待移除节点执行
STOP GROUP_REPLICATION;
4.集群重启(全部节点故障后):
-- 在任意一个节点重新引导集群
SET GLOBAL group_replication_bootstrap_group=ON;
START GROUP_REPLICATION;
SET GLOBAL group_replication_bootstrap_group=OFF;-- 其他节点直接启动
START GROUP_REPLICATION;
总结
MySQL 组复制(MGR)通过分布式一致性协议实现了自动故障转移和数据一致性,单主模式适合读多写少场景,多主模式适合高并发写入。实际部署时需注意:
节点数至少 3 个,确保多数派机制生效;
网络延迟需控制在 100ms 以内,避免影响事务提交效率;
定期监控集群状态,及时处理故障节点。
结合业务场景选择合适的高可用架构,可有效提升 MySQL 集群的稳定性和可靠性。
二、MySQL高可用之MHA(Master High Availability)
2.1 MHA核心特性与优势
MHA 是针对 MySQL 主从复制架构的高可用解决方案,通过自动监控主库状态、实现故障检测与自动切换,核心特性包括:
自动故障转移:主库宕机后 10-30 秒内完成新主库选举与切换。
数据一致性保障:通过 binlog 补传机制减少数据丢失风险。
零数据丢失:配合半同步复制可实现接近零数据丢失。
低侵入性:无需修改 MySQL 现有配置,兼容各种主从架构。
在线切换:支持手动触发主从切换(如主库升级维护)。
2.2 MHA架构原理
MHA 由两部分组成:
MHA Manager:管理节点,负责监控集群状态、触发故障转移。
MHA Node:部署在所有 MySQL 节点,提供 binlog 复制、故障检测等功能。
故障转移流程:
1.监控阶段:Manager 通过 SSH 定期(默认 3 秒)向主库发送 ping 包检测存活状态。
2.故障确认:连续 3 次 ping 失败后,Manager 通过其他从库确认主库是否真的宕机。
3.选举新主:根据从库的日志同步进度(优先选择最接近主库的从库)选举新主。
4.故障转移:隔离旧主库(如关闭 VIP、防火墙阻断);提升新主库(执行reset slave all
);其他从库指向新主库(通过 relay log 补全差异);应用层切换至新主库(如更新 VIP 指向);
2.3 MHA实战部署(单主多从架构)
环境准备
IP地址 | 主机名 | |
MHA Manager | 192.168.168.201 | mha-manager |
MySQL 主库 | 192.168.168.200 | master |
MySQL 从库 1 | 192.168.168.129 | slave1 |
MySQL 从库 2 | 192.168.168.130 | slave2 |
步骤1:配置SSH免密登录(关键)
MHA Manager 需要免密登录所有 MySQL 节点,MySQL 节点间也需要免密互通:
# 在MHA Manager节点生成密钥
[root@mha-manager ~]# ssh-keygen -t rsa -N '' -f ~/.ssh/id_rsa# 分发密钥到所有节点(包括自身)
[root@mha-manager ~]# for host in 192.168.168.200 192.168.168.129 192.168.168.130 192.168.168.201; dossh-copy-id -i ~/.ssh/id_rsa.pub root@$host
done# 验证免密登录
[root@mha-manager ~]# ssh 192.168.168.200 date
步骤2:安装MHA软件
所有节点安装MHA Node
# 安装依赖
[root@master ~]# yum install -y perl-DBD-MySQL perl-Config-Tiny perl-Log-Dispatch perl-Parallel-ForkManager# 下载并安装node包
[root@master ~]# wget https://github.com/yoshinorim/mha4mysql-node/releases/download/v0.58/mha4mysql-node-0.58-0.el7.noarch.rpm
[root@master ~]# rpm -ivh mha4mysql-node-0.58-0.el7.noarch.rpm
MHA Manager节点额外安装Manager包
[root@mha-manager ~]# wget https://github.com/yoshinorim/mha4mysql-manager/releases/download/v0.58/mha4mysql-manager-0.58-0.el7.noarch.rpm
[root@mha-manager ~]# rpm -ivh mha4mysql-manager-0.58-0.el7.noarch.rpm
步骤3:配置MySQL权限
在主库创建 MHA 专用管理用户(从库会同步该用户):
-- 创建管理用户(用于监控和故障转移)
CREATE USER 'mha_admin'@'192.168.168.%' IDENTIFIED BY 'Mha@123';
GRANT ALL PRIVILEGES ON *.* TO 'mha_admin'@'192.168.168.%' WITH GRANT OPTION;-- 确保主从复制用户已存在(参考1.2章节的rep用户)
FLUSH PRIVILEGES;
步骤4:配置MHA Manager
创建配置目录
[root@mha-manager ~]# mkdir -p /etc/mha/mysql_cluster
[root@mha-manager ~]# mkdir -p /var/log/mha/mysql_cluster
编写集群配置文件
# /etc/mha/mysql_cluster/mha.cnf
[server default]
# 管理用户
user=mha_admin
password=Mha@123
# 复制用户(主从同步用)
repl_user=rep
repl_password=rep123
# 工作目录
manager_workdir=/var/log/mha/mysql_cluster
# 日志文件
manager_log=/var/log/mha/mysql_cluster/manager.log
# SSH连接端口
ssh_port=22
# MySQL端口
mysql_port=3306
# 检测间隔(秒)
ping_interval=3
# 二次检查的从库数量
secondary_check_script=masterha_secondary_check -s 192.168.168.129 -s 192.168.168.130
# 故障转移后执行的脚本(如更新VIP)
master_ip_failover_script=/etc/mha/mysql_cluster/master_ip_failover[server1]
hostname=192.168.168.200
port=3306
# 主库故障后禁止自动启动
no_master=1[server2]
hostname=192.168.168.129
port=3306
# 候选主库权重
candidate_master=1[server3]
hostname=192.168.168.130
port=3306
candidate_master=1
步骤5:编写VIP切换脚本
创建master_ip_failover
脚本实现虚拟 IP(VIP)自动漂移:
#!/usr/bin/perl
use strict;
use warnings FATAL => 'all';
use Getopt::Long;my ($command, $ssh_user, $orig_master_host,$orig_master_ip, $orig_master_port, $new_master_host,$new_master_ip, $new_master_port, $new_master_user,$new_master_password
);# VIP配置
my $vip = '192.168.168.250/24';
my $key = '0';
my $dev = 'ens33';GetOptions('command=s' => \$command,'ssh_user=s' => \$ssh_user,'orig_master_host=s' => \$orig_master_host,'orig_master_ip=s' => \$orig_master_ip,'orig_master_port=i' => \$orig_master_port,'new_master_host=s' => \$new_master_host,'new_master_ip=s' => \$new_master_ip,'new_master_port=i' => \$new_master_port,
);exit &main();sub main {print "\n\nIN SCRIPT TEST====$command======\n\n";if ( $command eq "stop" || $command eq "stopssh" ) {my $exit_code = 1;eval {print "Disabling VIP on old master: $orig_master_host \n";&stop_vip();$exit_code = 0;};if ($@) {warn "Got Error: $@\n";exit $exit_code;}exit $exit_code;}elsif ( $command eq "start" ) {my $exit_code = 10;eval {print "Enabling VIP on new master: $new_master_host \n";&start_vip();$exit_code = 0;};if ($@) {warn $@;exit $exit_code;}exit $exit_code;}elsif ( $command eq "status" ) {print "Checking the Status of the script.. OK \n";exit 0;}else {&usage();exit 1;}
}sub start_vip() {`ssh $ssh_user\@$new_master_host \"ip addr add $vip dev $dev\"`;`ssh $ssh_user\@$new_master_host \"arping -I $dev -c 3 -s $vip 192.168.168.1 > /dev/null 2>&1\"`;
}sub stop_vip() {`ssh $ssh_user\@$orig_master_host \"ip addr del $vip dev $dev\"`;
}sub usage {print"Usage: master_ip_failover --command=start|stop|stopssh|status --orig_master_host=host --orig_master_ip=ip --orig_master_port=port --new_master_host=host --new_master_ip=ip --new_master_port=port\n";
}
赋予执行权限:
[root@mha-manager ~]# chmod +x /etc/mha/mysql_cluster/master_ip_failover
步骤6:验证MHA环境
检查SSH连通性
[root@mha-manager ~]# masterha_check_ssh --conf=/etc/mha/mysql_cluster/mha.cnf
输出All SSH connection tests passed successfully.
表示成功。
检查主从复制状态
[root@mha-manager ~]# masterha_check_repl --conf=/etc/mha/mysql_cluster/mha.cnf
输出MySQL Replication Health is OK.
表示成功。
步骤7:启动MHA Manager
# 后台启动
[root@mha-manager ~]# nohup masterha_manager --conf=/etc/mha/mysql_cluster/mha.cnf > /var/log/mha/mysql_cluster/manager.log 2>&1 &# 查看状态
[root@mha-manager ~]# masterha_check_status --conf=/etc/mha/mysql_cluster/mha.cnf
mysql_cluster (pid: 1234) is running(0:PING_OK), master:192.168.168.200
2.4 故障转移测试
1.模拟主库故障:在主库(200)执行关机命令
[root@master ~]# systemctl stop mysqld
2.观察MHA日志:
[root@mha-manager ~]# tail -f /var/log/mha/mysql_cluster/manager.log
日志会显示:检测到主库故障 → 选举新主(如 129)→ 转移 VIP → 完成切换。
3.验证结果:
查看VIP是否漂移到新主库:
[root@slave1 ~]# ip addr show ens33 | grep 192.168.168.250
检查从库是否指向新主:
mysql> show replica status\G
2.5 MHA日常维护
1.手动切换主库(如主库升级):
[root@mha-manager ~]# masterha_master_switch --conf=/etc/mha/mysql_cluster/mha.cnf \
--master_state=alive \
--new_master_host=192.168.168.129 \
--new_master_port=3306 \
--orig_master_is_new_slave
2.重启MHA Manager:
[root@mha-manager ~]# masterha_stop --conf=/etc/mha/mysql_cluster/mha.cnf
[root@mha-manager ~]# nohup masterha_manager --conf=/etc/mha/mysql_cluster/mha.cnf &
3.添加新从库:配置新从库与主库同步;修改 mha.cnf 添加新节点配置;重新检查并启动 MHA;
总结:
MHA 通过简洁的架构实现了 MySQL 主从集群的高可用,适合对成本敏感且已有主从架构的场景。部署时需注意:
严格配置 SSH 免密登录(核心前提);
配合半同步复制减少数据丢失;
编写可靠的 VIP 切换脚本(关键环节);
定期测试故障转移流程确保可用性;
根据业务规模和一致性要求,可选择 MHA(低成本)、MGR(强一致)或 Percona XtraDB Cluster(高并发)作为高可用解决方案。