MySQL集群高可用架构

一、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  # 启用单主模式

重启所有节点使配置生效:

bash 复制代码
systemctl restart mysqld

步骤2:创建组复制专用账户(所有节点执行)

登录MySQL,创建用于节点间通信的账户:

sql 复制代码
-- 创建复制用户(允许所有集群节点访问)
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的复制通道,用于组内事务同步:

sql 复制代码
-- 停止现有复制(若有)
STOP REPLICA;

-- 配置组复制通道
CHANGE REPLICATION SOURCE TO
SOURCE_USER='grp_user',
SOURCE_PASSWORD='Grp@123',
SOURCE_AUTO_POSITION=1
FOR CHANNEL 'group_replication_recovery';

步骤4:安装组复制插件(所有节点执行)

bash 复制代码
-- 安装组复制插件
INSTALL PLUGIN group_replication SONAME 'group_replication.so';

-- 验证插件是否安装成功
SHOW PLUGINS LIKE 'group_replication';

输出示例(状态为ACTIVE表示成功):

bash 复制代码
+-------------------+----------+--------------------+----------------------+---------+
| Name              | Status   | Type               | Library              | License |
+-------------------+----------+--------------------+----------------------+---------+
| group_replication | ACTIVE   | GROUP REPLICATION  | group_replication.so | GPL     |
+-------------------+----------+--------------------+----------------------+---------+

步骤5:初始化集群(仅在第一个节点执行)

在 192.168.168.200(候选主节点)上引导集群:

sql 复制代码
-- 启动集群初始化(仅第一次执行)
SET GLOBAL group_replication_bootstrap_group=ON;

-- 启动组复制
START GROUP_REPLICATION;

-- 关闭初始化开关(避免重复初始化)
SET GLOBAL group_replication_bootstrap_group=OFF;

步骤6:添加其他节点到集群(129和130节点执行)

sql 复制代码
-- 启动组复制,自动加入集群
START GROUP_REPLICATION;

步骤7:验证集群状态

-- 启动组复制,自动加入集群 START GROUP_REPLICATION;

sql 复制代码
SELECT * FROM performance_schema.replication_group_members;

输出示例(单主模式下MEMBER_ROLE为 PRIMARY 的是主节点):

bash 复制代码
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
| 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)执行停机命令:

bash 复制代码
systemctl stop mysqld

2.查看集群状态:在从节点(129)执行:

sql 复制代码
SELECT * FROM performance_schema.replication_group_members;

输出中会显示原主节点状态为UNREACHABLE,约 30 秒后集群自动选举新主(如 129 节点变为 PRIMARY)。

3.恢复原主节点:重启 200 节点后,自动以从节点身份加入集群:

bash 复制代码
systemctl start mysqld

登录 200 节点的 MySQL,启动组复制:

sql 复制代码
START GROUP_REPLICATION;

再次查看集群状态,200 节点角色变为 SECONDARY。

1.5 多主模式组复制配置(扩展)

多主模式允许所有节点同时处理写事务,适合高并发写入场景,配置差异如下:

1.修改所有节点的my.cnf:

sql 复制代码
loose-group_replication_single_primary_mode=OFF  # 关闭单主模式(启用多主)
loose-group_replication_enforce_update_everywhere_checks=ON  # 强制多主更新检查

2.重启节点并重新初始化集群(参考单主模式步骤5-6):

sql 复制代码
-- 在第一个节点执行
SET GLOBAL group_replication_bootstrap_group=ON;
START GROUP_REPLICATION;
SET GLOBAL group_replication_bootstrap_group=OFF;

-- 其他节点执行
START GROUP_REPLICATION;

3.验证多主模式:所有节点的MEMBER_ROLE均为 PRIMARY:

sql 复制代码
SELECT MEMBER_HOST, MEMBER_ROLE FROM performance_schema.replication_group_members;

1.6 组复制监控与维护

1.查看集群健康状态:

sql 复制代码
-- 集群成员状态
SELECT * FROM performance_schema.replication_group_members;

-- 事务冲突统计(多主模式)
SELECT * FROM performance_schema.replication_group_member_stats;

2.动态添加节点:

sql 复制代码
-- 在新节点执行(参考步骤2-4配置后)
START GROUP_REPLICATION;

3.移除节点:

sql 复制代码
-- 在待移除节点执行
STOP GROUP_REPLICATION;

4.集群重启(全部节点故障后):

sql 复制代码
-- 在任意一个节点重新引导集群
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 节点间也需要免密互通:

bash 复制代码
# 在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; do
    ssh-copy-id -i ~/.ssh/id_rsa.pub root@$host
done

# 验证免密登录
[root@mha-manager ~]# ssh 192.168.168.200 date

步骤2:安装MHA软件

所有节点安装MHA Node

bash 复制代码
# 安装依赖
[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包

bash 复制代码
[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 专用管理用户(从库会同步该用户):

bash 复制代码
-- 创建管理用户(用于监控和故障转移)
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

创建配置目录

bash 复制代码
[root@mha-manager ~]# mkdir -p /etc/mha/mysql_cluster
[root@mha-manager ~]# mkdir -p /var/log/mha/mysql_cluster

编写集群配置文件

bash 复制代码
# /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)自动漂移:

bash 复制代码
#!/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";
}

赋予执行权限:

bash 复制代码
[root@mha-manager ~]# chmod +x /etc/mha/mysql_cluster/master_ip_failover

步骤6:验证MHA环境

检查SSH连通性

bash 复制代码
[root@mha-manager ~]# masterha_check_ssh --conf=/etc/mha/mysql_cluster/mha.cnf

输出All SSH connection tests passed successfully.表示成功。

检查主从复制状态

bash 复制代码
[root@mha-manager ~]# masterha_check_repl --conf=/etc/mha/mysql_cluster/mha.cnf

输出MySQL Replication Health is OK.表示成功。

步骤7:启动MHA Manager

bash 复制代码
# 后台启动
[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)执行关机命令

bash 复制代码
[root@master ~]# systemctl stop mysqld

2.观察MHA日志:

bash 复制代码
[root@mha-manager ~]# tail -f /var/log/mha/mysql_cluster/manager.log

日志会显示:检测到主库故障 → 选举新主(如 129)→ 转移 VIP → 完成切换。

3.验证结果:

查看VIP是否漂移到新主库:

bash 复制代码
[root@slave1 ~]# ip addr show ens33 | grep 192.168.168.250

检查从库是否指向新主:

sql 复制代码
mysql> show replica status\G

2.5 MHA日常维护

1.手动切换主库(如主库升级):

bash 复制代码
[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:

bash 复制代码
[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(高并发)作为高可用解决方案。

相关推荐
TG_yunshuguoji2 小时前
阿里云国际代理:稳定、高效、便捷的数据库服务-云数据库RDS
运维·服务器·数据库·阿里云·云计算
·云扬·2 小时前
MySQL 日志全解析:Binlog/Redo/Undo 等 5 类关键日志的配置、作用与最佳实践
android·mysql·adb
一个帅气昵称啊2 小时前
C#,RabbitMQ从入门到精通,.NET8.0(路由/分布式/主题/消费重复问题 /延迟队列和死信队列/消息持久化 )/RabbitMQ集群模式
分布式·微服务·架构·rabbitmq·.net
danns8883 小时前
neo4j数据库创建范例(SQL文)
数据库·sql·neo4j
歪歪1003 小时前
Redux和MobX在React Native状态管理中的优缺点对比
前端·javascript·react native·react.js·架构·前端框架
程序新视界3 小时前
一篇文章全面重温MySQL的join操作
mysql
失散133 小时前
分布式专题——6 Redis缓存设计与性能优化
java·redis·分布式·缓存·架构
BYSJMG3 小时前
计算机毕设选题:基于Python+MySQL校园美食推荐系统【源码+文档+调试】
大数据·开发语言·python·mysql·django·课程设计·美食
不爱洗脚的小滕3 小时前
【Redis】Scan 命令使用教程:高效遍历海量数据
数据库·redis·bootstrap