12.6.3 Keepalived + MySQL 主从高可用
Keepalived + MySQL 主从高可用#
架构目标与角色#
- 目标:提供对外稳定的数据库访问入口,主库故障自动切换到从库,缩短中断时间。
- 角色:
- Master:提供写入与读取。
- Slave:复制主库数据,故障时接管写入。
- Keepalived:提供 VIP 漂移与健康检查。
- 可选:ProxySQL/HAProxy 作为读写分离入口并绑定 VIP。
原理草图(VIP 漂移 + 复制)#
典型拓扑与前置条件#
- 节点A:MySQL Master + Keepalived(MASTER)
- 节点B:MySQL Slave + Keepalived(BACKUP)
- VIP:10.0.0.100/24
- 复制:A -> B
- 前置条件:
- 主从复制稳定(建议 GTID/半同步)。
- 业务仅连接 VIP。
- SSH 免密或脚本本地执行。
安装与基础配置(示例)#
1)安装 Keepalived 与 MySQL(两节点)#
# CentOS/RHEL
yum -y install keepalived mysql-server
systemctl enable mysqld keepalived
systemctl start mysqld
# Ubuntu/Debian
apt -y install keepalived mysql-server
systemctl enable mysql keepalived
systemctl start mysql
2)配置 MySQL 主从(示例使用 GTID)#
- 主库
/etc/my.cnf关键项:
[mysqld]
server-id=1
log-bin=mysql-bin
gtid_mode=ON
enforce_gtid_consistency=ON
- 从库
/etc/my.cnf关键项:
[mysqld]
server-id=2
log-bin=mysql-bin
gtid_mode=ON
enforce_gtid_consistency=ON
read_only=1
- 在主库创建复制账号:
CREATE USER 'repl'@'10.0.0.%' IDENTIFIED BY 'Repl@123';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'10.0.0.%';
FLUSH PRIVILEGES;
- 从库执行复制配置:
CHANGE MASTER TO
MASTER_HOST='10.0.0.11',
MASTER_USER='repl',
MASTER_PASSWORD='Repl@123',
MASTER_AUTO_POSITION=1;
START SLAVE;
- 复制状态检查:
SHOW SLAVE STATUS\G
-- 预期:
-- Slave_IO_Running: Yes
-- Slave_SQL_Running: Yes
-- Seconds_Behind_Master: 0
Keepalived 配置与健康检查#
1)健康检查脚本(两节点一致)#
/etc/keepalived/check_mysql.sh
#!/bin/bash
MYSQL="/usr/bin/mysql -uroot -p'Root@123' -N -e"
# 1. MySQL 进程检查
pgrep -x mysqld >/dev/null || exit 1
# 2. 主库可写 or 从库复制正常
ROLE=$($MYSQL "SELECT @@read_only;")
if [ "$ROLE" = "0" ]; then
exit 0
fi
# 从库复制检查
IO=$($MYSQL "SHOW SLAVE STATUS\G" | awk '/Slave_IO_Running/{print $2}')
SQL=$($MYSQL "SHOW SLAVE STATUS\G" | awk '/Slave_SQL_Running/{print $2}')
DELAY=$($MYSQL "SHOW SLAVE STATUS\G" | awk '/Seconds_Behind_Master/{print $2}')
[ "$IO" = "Yes" ] && [ "$SQL" = "Yes" ] && [ "${DELAY:-999}" -lt 5 ] || exit 1
exit 0
chmod +x /etc/keepalived/check_mysql.sh
2)Keepalived 配置#
- MASTER 节点
/etc/keepalived/keepalived.conf
global_defs {
router_id MYSQL_KA_1
}
vrrp_script chk_mysql {
script "/etc/keepalived/check_mysql.sh"
interval 2
timeout 2
fall 2
rise 2
}
vrrp_instance VI_1 {
state MASTER
interface eth0
virtual_router_id 51
priority 120
advert_int 1
nopreempt
authentication {
auth_type PASS
auth_pass 123456
}
virtual_ipaddress {
10.0.0.100/24
}
track_script {
chk_mysql
}
notify_master "/etc/keepalived/promote_master.sh"
}
- BACKUP 节点
/etc/keepalived/keepalived.conf
global_defs {
router_id MYSQL_KA_2
}
vrrp_script chk_mysql {
script "/etc/keepalived/check_mysql.sh"
interval 2
timeout 2
fall 2
rise 2
}
vrrp_instance VI_1 {
state BACKUP
interface eth0
virtual_router_id 51
priority 100
advert_int 1
nopreempt
authentication {
auth_type PASS
auth_pass 123456
}
virtual_ipaddress {
10.0.0.100/24
}
track_script {
chk_mysql
}
notify_master "/etc/keepalived/promote_master.sh"
}
3)切换提升脚本#
/etc/keepalived/promote_master.sh
#!/bin/bash
MYSQL="/usr/bin/mysql -uroot -p'Root@123' -e"
# 停止复制,解除只读,提升为主库
$MYSQL "STOP SLAVE; SET GLOBAL read_only=0; SET GLOBAL super_read_only=0;"
exit 0
chmod +x /etc/keepalived/promote_master.sh
systemctl restart keepalived
4)预期效果验证#
# 观察 VIP 所在节点
ip a | grep 10.0.0.100
# 模拟主库故障
systemctl stop mysqld
# 预期:VIP 漂移到从库,promote_master.sh 执行
ip a | grep 10.0.0.100
关键命令解释#
vrrp_script:周期执行健康检查脚本,返回非 0 则降权触发漂移。priority:优先级,数值高者优先成为 MASTER。nopreempt:避免恢复后的原主库抢占 VIP,降低脑裂风险。notify_master:节点成为 MASTER 时执行脚本,用于提升从库。
常见故障与排错#
1)VIP 不漂移#
# 检查 Keepalived 日志
journalctl -u keepalived -f
# 检查 VRRP 心跳端口(默认 112)
tcpdump -i eth0 vrrp
排查要点:
- virtual_router_id、auth_pass 不一致会导致不建立 VRRP。
- 健康检查脚本返回非 0 会持续触发降权。
2)从库未提升为主库#
# 手动验证脚本
bash -x /etc/keepalived/promote_master.sh
排查要点:
- root 密码错误或权限不足。
- read_only 未关闭,导致业务写入失败。
3)复制延迟过大导致误切换#
# 查看延迟
mysql -uroot -p -e "SHOW SLAVE STATUS\G" | grep Seconds_Behind_Master
建议:
- 提高 fall/rise 或放宽延迟阈值。
- 高写入场景启用半同步复制。
运维建议#
- 定期演练切换与回切。
- 监控:复制延迟、连接数、慢查询、磁盘 IO。
- 变更时同时更新健康检查脚本与 MySQL 权限。
练习#
- 将
Seconds_Behind_Master阈值改为 1 秒,观察高峰写入时是否频繁切换。 - 主库停机后,验证从库是否自动提升并可写入。
- 恢复原主库为从库,完成回切演练并记录切换耗时。