MySQL数据库(七)—— 基于主主复制与 Keepalived 非抢占模式的高可用方案
MySQL 主主复制 + Keepalived 高可用集群方案 本文介绍了一种基于MySQL主主复制和Keepalived的高可用数据库集群实现方案。该方案通过双向主从复制确保数据冗余,利用Keepalived管理虚拟IP(VIP)实现故障自动转移。环境规划包括两个节点(Node1和Node2)及一个VIP(192.168.10.180),采用非抢占模式确保稳定性。 配置要点:1)MySQL双向主
前言
在生产环境中,数据库高可用性是系统稳定运行的关键保障。MySQL 主从复制提供了数据冗余和读写分离的能力,但单点故障问题仍然存在。
本文将详细介绍通过 MySQL 主主复制 + Keepalived 实现高可用数据库集群的方案,使用 VIP(虚拟 IP)作为应用的统一访问入口,实现故障自动转移与恢复,并采用非抢占模式确保集群稳定性。
在上一篇博客中MySQL数据库(六)—— MHA集群搭建与故障切换,我们介绍了MHA集群,这也是一种成熟的MySQL高可用解决方案。二者核心区别如下:
主主复制+Keepalived与MHA的核心区别对比表
| 对比维度 | 主主复制+Keepalived | MHA |
|---|---|---|
| 架构基础 | 双节点互为主从,依赖Keepalived管理VIP | 一主多从,依赖MHA Manager和Node组件管理集群 |
| 故障检测粒度 | 节点级(服务器/网络故障),需额外脚本检测服务 | 服务级(MySQL进程/复制异常),原生支持精细检测 |
| 故障转移速度 | 秒级(VIP快速漂移) | 10-30秒(需选新主、补全数据) |
| 数据一致性 | 依赖复制同步,存在延迟和冲突风险 | 自动选最新从库并补全数据,一致性更优 |
| 扩展性 | 差,仅支持双节点 | 好,可扩展多从库提升读性能 |
| 脑裂风险 | 较高 | 较低 |
| 运维复杂度 | 低(架构简单) | 高(需维护额外组件) |
- 主主复制+Keepalived是简单快速、成本低但数据一致性风险较高的双节点方案,适合中小规模非核心业务。
- MHA是架构复杂、切换稍慢但数据可靠性更强的一主多从方案,适合对一致性要求高的核心业务。
一、环境规划
1.1 节点信息
| 节点名称 | IP 地址 | 角色 | 服务组件 |
|---|---|---|---|
| Node1 | 192.168.10.14 | 初始主节点 | MySQL + Keepalived |
| Node2 | 192.168.10.15 | 初始备节点 | MySQL + Keepalived |
| VIP | 192.168.10.180 | 应用访问入口 | 虚拟 IP(由 Keepalived 管理) |
| 客户端 | 192.168.10.120 | 测试客户端 | MySQL |
+-------------------------------------------------------+
| 应用服务器 |
| |
| 访问: 192.168.10.180 |
+--------------------------|----------------------------+
|
| VIP: 192.168.10.180
|
+-----------------+------------------+
| |
| |
+--------|---------+ +---------|--------+
| Node1 | | Node2 |
| IP: 192.168.10.14| | IP: 192.168.10.15|
| | | |
| MySQL (Master1) |<-------------->| MySQL (Master2) |
| Keepalived (MASTER) | Keepalived (BACKUP)|
| | | |
+------------------+ +-------------------+
说明:
MySQL双向复制:Node1和Node2之间互相复制数据。
Keepalived:Node1初始为MASTER状态,持有VIP;Node2为BACKUP状态。
当Node1的MySQL服务失败,Keepalived会将VIP转移到Node2,同时应用服务器访问VIP的请求会被路由到Node2
1.2 服务版本
- 操作系统: CentOS 7.9
- MySQL: 5.7
- Keepalived: 1.3.5(yum 安装版本)
1.3 搭建思路
(1)安装 MySQL 数据库;
(2)配置 MySQL 互为主从;
(3)安装 keepalived 软件并配置故障转移;
(4)模拟 master 故障切换
(5)实现故障恢复
1.4 基础环境配置
# 关闭防火墙和增强功能
systemctl stop firewalld.service
setenforce 0
二、MySQL 主主复制配置
MySQL 主主复制实质上是双向的主从复制,两台服务器互为 Master 和 Slave。
MySQL的安装步骤可以参考:MySQL安装管理指南
2.1 修改 MySQL 配置文件
两台服务器均需进行以下配置,注意 server-id 和 auto_increment_offset 的区别:
2.1.1 Node1 (192.168.10.14) 配置
# /etc/my.cnf
[mysqld]
# 服务器唯一标识,Node1 设为 1,Node2 设为 2
server-id = 1
# 开启二进制日志
log-bin = mysql-bin
# 中继日志配置
relay-log = relay-log
# 自增步长设为2,避免主键冲突
auto_increment_increment = 2
# Node1 自增起始值为1
auto_increment_offset = 1
# 行级复制,保证数据一致性
binlog_format = ROW
# 开启 GTID
gtid_mode = ON
enforce_gtid_consistency = ON
# 禁止 Slave 自动启动,需手动开启
skip_slave_start = 1
# 可选:减少复制错误风险
log_slave_updates = ON

2.1.2 Node2 (192.168.10.15) 配置
# /etc/my.cnf
[mysqld]
server-id = 2
log-bin = mysql-bin
relay-log = relay-log
auto_increment_increment = 2
auto_increment_offset = 2 # Node2 自增起始值为2
binlog_format = ROW
gtid_mode = ON
enforce_gtid_consistency = ON
skip_slave_start = 1
log_slave_updates = ON
配置修改完成后,重启两台 MySQL 服务:
systemctl restart mysqld
2.2 创建复制账户和安全检查账户
在两台 MySQL 服务器上执行以下 SQL 命令,创建用于复制的账户:
-- 创建复制用户
CREATE USER IF NOT EXISTS 'myslave'@'%' IDENTIFIED BY '123456';
-- 授权复制权限
GRANT REPLICATION SLAVE ON *.* TO 'myslave'@'%';
-- 创建检查用户
CREATE USER IF NOT EXISTS 'checker'@'localhost' IDENTIFIED BY 'CheckPass123';
-- USAGE权限表示"无权限",仅用于连接验证,是最安全的选项。
GRANT USAGE ON *.* TO 'checker'@'localhost';
-- 创建测试用户
CREATE USER IF NOT EXISTS 'test'@'%' IDENTIFIED BY '123456';
-- 授权
GRANT ALL ON *.* TO 'test'@'%';
-- 刷新权限
FLUSH PRIVILEGES;

2.3 配置双向同步
2.3.1 在 Node1 上配置到 Node2 的复制
CHANGE MASTER TO
MASTER_HOST = '192.168.10.15',
MASTER_USER = 'myslave',
MASTER_PASSWORD = '123456',
MASTER_AUTO_POSITION = 1;
START SLAVE;
2.3.2 在 Node2 上配置到 Node1 的复制
CHANGE MASTER TO
MASTER_HOST = '192.168.10.14',
MASTER_USER = 'myslave',
MASTER_PASSWORD = '123456',
MASTER_AUTO_POSITION = 1;
START SLAVE;
2.4 验证复制状态
在两台服务器上执行以下命令,检查复制状态:
SHOW SLAVE STATUS\G;
确认以下关键指标:
Slave_IO_Running: YesSlave_SQL_Running: YesSeconds_Behind_Master: 0(表示无延迟)

三、Keepalived 非抢占模式配置
3.1 安装 Keepalived
在两台服务器上安装 Keepalived:
yum install -y keepalived

3.2 配置 Keepalived
3.2.1 Node1 配置 (192.168.10.14)
创建或编辑 vim /etc/keepalived/keepalived.conf:
! Configuration File for keepalived
global_defs {
smtp_server 127.0.0.1
# 路由器标识,每个节点唯一
router_id MYSQL_HA_14
# 必须注释
#vrrp_strict
}
# MySQL 健康检查脚本配置
vrrp_script chk_mysql {
# 检查脚本路径
script "/etc/keepalived/check_mysql.sh"
# 每 2 秒检查一次
interval 2
# 连续 2 次失败视为故障
fall 2
# 1 次成功视为恢复
rise 1
}
# 虚拟路由配置
vrrp_instance VI_1 {
# 两台均设为 BACKUP(非抢占关键)
state BACKUP
# 网卡名(根据实际系统情况修改)
interface ens33
# 虚拟路由 ID(两台必须相同)
virtual_router_id 51
# Node1 初始优先级 100(高于 Node2)
priority 100
# 非抢占模式(故障恢复不抢回 VIP)
nopreempt
# VRRP 通告间隔
advert_int 1
# 认证配置
authentication {
auth_type PASS
auth_pass 1111 # 认证密码(两台相同)
}
# 虚拟 IP 配置
virtual_ipaddress {
192.168.10.180/24 # VIP
}
# 关联健康检查脚本
track_script {
chk_mysql
}
}
3.2.2 Node2 配置 (192.168.10.15)
创建或编辑 vim /etc/keepalived/keepalived.conf:
global_defs {
smtp_server 127.0.0.1
router_id MYSQL_HA_15
#vrrp_strict
}
vrrp_script chk_mysql {
script "/etc/keepalived/check_mysql.sh"
interval 2
fall 2
rise 1
}
vrrp_instance VI_1 {
state BACKUP
interface ens33
virtual_router_id 51
# Node2 初始优先级低于 Node1
priority 90
# 非抢占模式
nopreempt
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.10.180/24
}
track_script {
chk_mysql
}
}
3.3 MySQL 健康检查脚本
在Node1和Node2上创建配置文件存储密码(避免明文)
# (权限设为 600,属主 root)
vim /etc/keepalived/.my.cnf
[client]
user=checker
password=CheckPass123
# 设置文件属主为 root(默认创建可能已是 root,但明确执行更稳妥)
chown root:root /etc/keepalived/.my.cnf
# 设置权限为 600(仅 root 可读可写,其他用户无任何权限)
chmod 600 /etc/keepalived/.my.cnf


在Node1和Node2上创建健康检查脚本
vim /etc/keepalived/check_mysql.sh
#!/bin/bash
# 尝试连接 MySQL 并执行简单查询(如 SELECT 1)
if /usr/local/mysql/bin/mysql --defaults-extra-file=/etc/keepalived/.my.cnf -e "SELECT 1;" >/dev/null 2>&1; then
exit 0 # MySQL 可正常使用
else
exit 1 # MySQL 无法连接或查询失败
fi
给脚本添加执行权限:
chmod +x /etc/keepalived/check_mysql.sh
3.4 启动 Keepalived 服务
在两台服务器上启动 Keepalived 并设置开机自启:
systemctl start keepalived
systemctl enable keepalived
检查服务状态:
systemctl status keepalived

3.5 验证 VIP 绑定
在初始状态下,VIP 应该绑定在优先级较高的 Node1 上。可以使用以下命令验证:
ip addr show ens33
应该可以看到 VIP 192.168.10.180 绑定在 Node1 的网卡上。

3.6 测试使用VIP连接MySQL
# 在客户端使用vip连接mysql,测试能否正常使用
mysql -utest -p -h192.168.10.180 -P3306
show databases;
use test;
select * from test.info;


# 测试数据能否正常插入
insert into info values(3,'this is client');
# 在Node1和Node2上查看数据是否同步
select * from test.info;


四、故障转移与恢复流程
4.1 故障转移(Node1 节点故障)
当当前主节点(Node1)发生故障时,系统会自动进行故障转移:
# 关闭Node1节点mysql服务
systemctl stop mysqld
# 观察vip是否漂移到node2
ip addr show ens33

# 在客户端测试使用vip是否可以正常访问数据库
mysql -utest -p -h192.168.10.180 -P3306
show databases;
insert into info values(4,'this is client_2');
# 在node2(新主库)上查看数据是否正常插入
select * from test.info;

4.2 故障恢复(原主节点恢复)
当原主节点(Node1)故障修复后重新上线:
-
健康恢复:Node1 的 MySQL 服务恢复正常,健康检查脚本返回成功(exit 0)
-
非抢占行为:由于配置了
nopreempt参数,Node1 不会主动抢回 VIP -
状态维持:VIP 仍然保留在 Node2,Node1 作为热备节点运行
-
数据同步:Node1 自动从 Node2 同步故障期间的数据更新,保持数据一致性
# node1上恢复mysql
systemctl start mysqld
# 查看Node1节点数据
select * from info;

# 在node1上手动开启slave
start slave;
# 观察Node1数据是否同步
select * from info;

4.3 强制切换回原主(可选操作)
如果需要在原主节点恢复后手动将 VIP 切换回 Node1,可以执行以下操作:
在 Node2 上执行(主动放弃 VIP):
systemctl restart keepalived
在非抢占模式下,通常需要重启 Keepalived 服务来触发切换。

五、方案优势与注意事项
5.1 方案优势
-
高可用性:自动故障检测和转移,确保数据库服务持续可用
-
无缝切换:VIP 机制使应用无需修改配置即可实现故障转移
-
数据一致性:基于 GTID 的主主复制保证数据双向同步
-
防止脑裂:VRRP 协议和优先级机制确保同一时间只有一台主节点
-
故障恢复安全:非抢占模式避免原主恢复后抢回 VIP 导致的服务波动
-
灵活可扩展:可轻松添加更多节点或扩展为多层级复制架构
5.2 注意事项
-
网络配置:确保防火墙允许 VRRP 协议(IP 协议号 112)和 MySQL 端口(3306)通信
-
复制监控:定期检查主主复制延迟和状态,确保数据同步正常
-
数据初始化:使用 mysqldump 或 XtraBackup 初始化数据时确保数据一致性
-
密码安全:脚本中的 MySQL 密码应妥善保管,建议使用权限受限的专用监控账户
-
脑裂预防:确保 Keepalived 配置中的
virtual_router_id在同一网段内唯一 -
性能考虑:主主复制会增加服务器负载,需监控系统资源使用情况
六、一些踩过的坑
6.1 将vrrp_strict注释
- 在 Keepalived 配置中,vrrp_strict 是一个严格模式开关,当它未被注释(启用)时,会导致一些网络限制。
- vrrp_strict 启用时,会强制开启多项安全限制,其中 最关键的一项是 “禁止响应来自非 VRRP 成员的 IP 数据包”,包括 ICMP(ping)请求。
- 因此,在需要通过 VIP 对外提供服务的架构中,必须注释掉 vrrp_strict,否则 VIP 将无法承担业务流量的转发功能。如果有安全需求,建议通过防火墙规则(如 iptables)手动限制 VIP 的访问来源,而非依赖 vrrp_strict 的强制限制。
6.2 非抢占模式下不要配置weight
- 抢占模式记牢“必须加weight”:核心是通过动态调整优先级触发备节点主动抢占,否则无法检测“应用故障但节点存活”。
- 非抢占模式记牢“必须删weight”:核心是通过“失效判定”让备节点被动接管,加了weight会导致主节点仍发心跳,阻碍切换。
- 状态配置建议:抢占模式主节点设
MASTER、备节点设BACKUP;非抢占模式建议均设BACKUP(靠优先级决定初始主备)+nopreempt,避免逻辑混乱。
可参考博客:Keepalived核心配置解析:抢占/非抢占模式与weight参数的适配方案。
6.3 健康检查脚本中使用绝对路径
-
现象描述:
- 使用相对路径时,健康检查脚本返回status 1(失败)
- 手动执行同一脚本返回0(成功)
-
问题根源:
- 编译安装MySQL时,将/usr/local/mysql/bin/添加到了PATH环境变量
- keepalived执行脚本时的环境变量与用户终端环境变量不一致
-
解决方案:
- 使用绝对路径调用命令
- 创建软链接到系统标准路径
总结
本文详细介绍了基于 MySQL 主主复制和 Keepalived 非抢占模式的高可用数据库集群方案。通过双向数据同步和虚拟 IP 漂移机制,实现了数据库服务的自动故障转移和恢复。非抢占模式的配置确保了故障恢复过程中的系统稳定性,避免了频繁的主备切换带来的风险。
此方案适用于对数据库可用性要求较高的生产环境,提供了无缝故障转移能力,同时保证了数据一致性。实际部署时,需要根据具体业务需求和系统环境进行适当调整和优化,并建立完善的监控告警机制,确保整个数据库集群的稳定运行。
更多推荐
所有评论(0)