mysql双主+keepalived高可用需严控四大要点:双主同步参数(server-id、auto-increment、log_slave_updates、权限网段)必须精准;keepalived检测脚本须真实连接并设超时;virtual_router_id须一致且启用non_preemptive防vip抢夺;内核参数ip_nonlocal_bind=1及真实网卡名不可遗漏。

MySQL双主+Keepalived高可用不是“配完就能用”的组合,而是两个强耦合环节:双主同步必须数据一致,Keepalived检测必须真实有效;缺一不可,错一个就等于白配。
MySQL双主配置里最常踩的三个坑
双主不是简单互设为对方的从库,关键参数稍有偏差,就会在写入时爆 Duplicate entry 或复制中断:
-
server-id必须全局唯一——两台机器不能都是1,也不能留默认值(如 MySQL 8.0 默认是1) -
auto-increment-offset和auto-increment-increment必须配对:Node1 设offset=1, increment=2,Node2 就必须是offset=2, increment=2;反过来或值相同都会冲突 -
log_slave_updates=1必须开启——否则 A 同步了 B 的变更,但不会把这条变更再写进自己的 binlog,B 就收不到 A 的二次同步,形成断链 - 同步账号权限要带网段,比如
'repl'@'192.168.1.%',不能只写'repl'@'%',部分 MySQL 版本(尤其 5.7+)会拒绝连接
Keepalived检测脚本为什么总不触发VIP漂移
默认的 vrrp_script 如果只检查 pgrep mysqld 进程存在,MySQL 实际卡死、连接超时、复制中断都发现不了——VIP 就永远挂死在故障节点上。
必须用真实连接检测,例如:
#!/bin/bash mysql -uhealth -pcheck -h127.0.0.1 --connect-timeout=3 -e "SELECT 1" &>/dev/null
并在 keepalived.conf 中正确引用:
vrrp_script check_mysqld {
script "/etc/keepalived/check_mysql.sh"
interval 2
fall 2
rise 2
}
-
fall 2表示连续 2 次失败才降权,避免网络抖动误判 - 脚本里没加
--connect-timeout=3,一次连接卡住 10 秒,整个故障发现延迟就拉长到 20 秒以上 - 别忘了给脚本加执行权限:
chmod +x /etc/keepalived/check_mysql.sh
virtual_router_id 和 non_preemptive 配置不一致导致VIP抢来抢去
两台 Keepalived 的 virtual_router_id 必须完全相同(范围 1–255),且不能和局域网内其他 VRRP 组(比如 LVS 或其他 Keepalived 实例)重复,否则可能根本抢不到 VIP,或者抢错组。
更关键的是 non_preemptive(非抢占模式)——生产环境强烈建议启用:
- 不加这个,当原 MASTER 恢复后会立刻抢回 VIP,正在跑的应用连接瞬间中断,TCP 重连风暴风险极高
- 加了之后,只有当前 MASTER 宕机,BACKUP 才会上位;恢复的节点保持 BACKUP 状态,不再主动抢
- 注意:该选项只在 BACKUP 节点的
vrrp_instance块中生效,MASTER 节点配置无效
内核参数和网卡名这些“隐形门槛”容易被忽略
CentOS 7+/Rocky 8+ 或 systemd 网络管理环境下,interface eth0 很可能根本不存在——得先运行 ip link show 确认真实网卡名(如 ens192、enp0s3),写错就绑不上 VIP。
内核参数也必须提前设置,否则 VIP 无法绑定到本地:
net.ipv4.ip_nonlocal_bind = 1 net.ipv4.ip_forward = 1
-
ip_nonlocal_bind=1是关键,否则 Keepalived 启动时报Cannot bind socket: Cannot assign requested address - 改完记得
sysctl -p生效,不要只改文件不加载 - ARP 相关参数(
arp_ignore/arp_announce)在某些云环境或容器场景下反而引发异常,可先不配,出问题再加











