mysql主从架构如何实现高可用_Keepalived结合双主配置
Keepalived 不能直接实现 MySQL 主从高可用,因其仅负责 VIP 漂移且不感知复制状态;必须先构建双主架构并配置自检脚本、合理参数及应用层连接池校验才能真正高可用。

免费影视、动漫、音乐、游戏、小说资源长期稳定更新! 👉 点此立即查看 👈
一个常见的误解是:给 MySQL 主从架构配上 Keepalived,就万事大吉了。事实恰恰相反,Keepalived 只管 VIP 漂移,它根本不关心数据库的复制状态。真想实现高可用,必须先搭建双主(master-master)架构,再用 Keepalived 管理 VIP。否则,主库一旦宕机,从库不会自动切换为主,VIP 漂过去也是白搭,业务照样中断。
为什么不能直接在主从上配 Keepalived
Keepalived 的核心机制 vrrp_instance 只负责检测本地服务是否存活或端口是否通畅,它对 MySQL 复杂的复制状态一无所知。想象一下这个场景:VIP 绑定在主库上,从库也配置了 Keepalived 但作为 BACKUP 角色。一旦主库宕机,VIP 确实会漂移到从库。但问题来了,此时从库的复制线程(Sla ve_IO_Running 和 Sla ve_SQL_Running)很可能早已停止,或者存在几分钟甚至更久的复制延迟。如果应用直接连上这个“新主”,结果就是查不到最新数据,甚至写入会报错,数据一致性完全无法保证。
这种配置下,通常会遇到以下几种“诡异”现象:
- Keepalived 切换后,应用能通过 VIP 连上数据库,但就是读不到刚刚写入的数据。
- 切换完成后,执行
SHOW SLA VE STATUS一看,Seconds_Behind_Master这个延迟值高达几百甚至几千秒。 - 误以为“VIP 能连通就等于数据库正常可用”,结果业务接连报出主键冲突或唯一索引重复的错误。
双主 + Keepalived 的核心配置要点
搭建双主架构,可不是简单地在两台机器上互相执行 CHANGE MASTER TO 命令就完事了。关键在于配置参数必须错开,否则两边同时写入,数据冲突将不可避免:
server-id必须不同:例如,一台设为1,另一台设为2。auto_increment_offset和auto_increment_increment必须配对设置:比如,两台都设置auto_increment_increment = 2,然后一台的auto_increment_offset设为1,另一台设为2。这样能确保自增ID不会冲突。- 两台服务器都必须开启二进制日志(
log-bin),并且binlog_format建议使用ROW模式。行级复制在双主架构下比语句级复制更可靠,能避免许多潜在问题。 - 务必确认关闭了
skip_sla ve_start参数(MySQL 5.7 及以上版本默认已关闭),以确保数据库重启后,复制线程能自动恢复工作。
以下是一个配置示例片段(位于 /etc/my.cnf):
[mysqld] server-id = 1 log-bin = mysql-bin binlog-format = ROW auto_increment_offset = 1 auto_increment_increment = 2
Keepalived 配置里最容易漏掉的检测逻辑
Keepalived 默认的 TCP_CHECK 健康检查,仅仅检测 3306 端口是否能连通。这意味着,即使 MySQL 进程还在,但复制线程已经卡死或停止,Keepalived 依然会认为该节点是“健康”的。这显然不行。因此,必须添加自定义的检查脚本,来判断 MySQL 的复制状态是否真正可用:
- 脚本需要检查
Sla ve_IO_Running和Sla ve_SQL_Running是否都为Yes。 - 最好再加上对复制延迟的判断,例如
Seconds_Behind_Master <= 5(具体阈值可根据业务对数据实时性的容忍度调整)。 - 在 Keepalived 配置中,通过
vrrp_script块来定义并调用这个脚本,作为判定节点健康状态的依据。同时,利用notify_down等机制来触发故障处理。 - 强烈建议将
nopreempt参数设为yes,这可以避免原主库恢复后,重新抢回 VIP 而导致“脑裂”现象。
一个典型的错误配置是:只在 virtual_server 部分配置了 TCP_CHECK,而没有配置 vrrp_script,或者自定义脚本的返回值没有被 Keepalived 正确识别。
真实故障场景下最常被忽略的一点
即便双主架构和 Keepalived 都配置得天衣无缝,检测脚本也运行无误,还有一个环节常常在故障发生时被忽略:应用层的连接池。当主写节点宕机,VIP 成功漂移到备用节点后,应用服务器连接池里那些旧的、指向原主库的数据库连接并不会自动断开和重连。如果应用没有配置连接有效性校验(比如在每次从连接池借用连接前,执行一次 PING 或简单的 SELECT 1),那么应用就会继续向已经失效的旧主库发送请求。这些请求要么超时,要么被丢弃,直到连接池因超时回收这些旧连接。在这段“空窗期”内的所有写操作,都将丢失。
这个问题,既不是 Keepalived 的锅,也不是 MySQL 的错,而是应用层必须配合完成的“最后一公里”。解决方案是:确保数据库连接池启用了类似 testOnBorrow 的机制,并且用于测试的 SQL 语句最好能暴露复制中断的问题(例如,查询一个近期有写入的表,或者结合 SELECT @@read_only 来辅助判断节点角色)。否则,整个高可用链路就会在这最后一环功亏一篑。
游乐网为非赢利性网站,所展示的游戏/软件/文章内容均来自于互联网或第三方用户上传分享,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系youleyoucom@outlook.com。
同类文章
mysql执行sql语句时内存溢出_如何设置排序区buffer优化内存使用
MySQL排序内存溢出?别慌,先搞懂sort_buffer_size怎么调 sort_buffer_size并非越大越好,盲目调高易引发OOM;它按需分配、每连接独占,建议会话级设为4MB而非全局调整,并优先优化索引避免filesort。 MySQL排序内存不足报 Out of memory 怎么调
mysql如何清理过大的binlog日志_设置expire_logs_days自动删除
MySQL Binlog清理:为什么设置了过期天数,日志文件却纹丝不动? 不少DBA都遇到过这个令人困惑的场景:明明在配置文件里白纸黑字地设置了expire_logs_days = 7,重启后检查变量也确认生效了。可一周过去,磁盘空间告急,一查发现那些本该被自动清理的旧binlog文件,居然还老老实
mysql主从同步报错1062怎么解决_使用set global sql_slave_skip_counter跳过错误
MySQL主从同步报错1062:从应急跳转到根治数据冲突的完整指南 遇到主从同步卡在1062错误,很多DBA的第一反应就是“跳过它”。但跳过之后呢?问题往往卷土重来。今天,我们就来彻底拆解这个经典的“Duplicate entry”冲突,把应急操作和根治方案一次讲清楚。 MySQL主从同步报错106
MySQL生产环境误操作drop表_通过Binlog闪回恢复数据
MySQL生产环境误删表数据?别急,利用Binlog日志实现精准闪回恢复 在MySQL数据库运维中,最令人紧张的场景莫过于生产环境误执行了DROP TABLE命令。面对突发状况,保持冷静是关键。只要数据库满足两个核心条件,被删除的数据就有极高的恢复可能性。这两个必要条件是什么?即MySQL的二进制日
mysql如何解决由于外键导致的更新死锁_在高性能场景下拆除外键
MySQL外键:高性能场景下的隐形死锁制造者与安全拆除指南 先明确一个核心结论:在高并发写入的场景下,数据库外键约束极易成为性能瓶颈和死锁的源头。简单来说,外键的UPDATE操作会因校验参照完整性而对关联记录加共享锁(S锁);若要安全拆除,则需遵循确认依赖、手动校验、在线删除三步走;拆除后,必须通过
- 日榜
- 周榜
- 月榜
1
2
3
4
5
6
7
8
9
10
相关攻略
2015-03-10 11:25
2015-03-10 11:05
2021-08-04 13:30
2015-03-10 11:22
2015-03-10 12:39
2022-05-16 18:57
2025-05-23 13:43
2025-05-23 14:01
热门教程
- 游戏攻略
- 安卓教程
- 苹果教程
- 电脑教程
热门话题

