先确认VIP是否绑定成功,再检查ARP缓存、防火墙、Keepalived配置及Redis角色状态,最后优化客户端超时重试逻辑。

Keepalived 切换时 Redis 客户端连不上 192.168.10.100?先确认 VIP 真的绑上了
很多问题根本不是 Redis 本身的问题,而是 Keepalived 没把虚拟 IP 成功绑定到新主节点的网卡上。用 ip addr show 在新主上查一遍,看 192.168.10.100 是否出现在 eth0(或对应网卡)的输出里。没出现就别急着调 Redis 配置——脚本没跑、priority 设错、network namespace 隔离、甚至 SELinux 拦了 vrrp 协议都可能让 VIP 停在旧机器上不动。
常见错误现象:connect ETIMEDOUT 或 Connection refused,但 telnet 192.168.10.100 6379 在新主本机能通,在客户端不通——大概率是 ARP 缓存没刷新或防火墙 DROP 了 VRRP 包。
- 检查
/etc/keepalived/keepalived.conf中vrrp_script的weight和fall/rise是否合理,避免抖动误切 - 确认两台机器的
state配置:一台MASTER,另一台必须是BACKUP,不能都设成MASTER - 启用
notify_master /path/to/redis-failover.sh脚本前,先手动执行一遍,看是否真能redis-cli -h 127.0.0.1 shutdown或slaveof no one
Redis 主从切换后,客户端还在往旧主发写请求?靠 readonly + 连接池自动重试不够
Redis 本身不主动通知客户端“我已降级”,readonly 只防读,不拦写;连接池(比如 Jedis、Lettuce)默认也不会在 MOVED 或 ASK 错误后自动跳转——因为 Redis Sentinel 才管重定向,纯 Keepalived + VIP 方案下,客户端看到的始终是同一个 IP 地址,它根本不知道背后主库换了人。
所以关键不是“怎么让 Redis 告诉客户端”,而是“怎么让客户端感知失败并重建连接”。这得靠客户端自己做超时+重连逻辑,而不是依赖服务端返回特殊错误码。
- 把连接超时(
connectTimeout)和读超时(soTimeout)设短一点,比如 1–2 秒,避免卡在旧主 FIN_WAIT 状态里等 30 秒 - 禁用连接池的
testOnBorrow(太重),改用testWhileIdle+ 合理的timeBetweenEvictionRunsMillis(如 5000)定期探活 - 写操作必须包裹重试逻辑:捕获
IOException、JedisConnectionException,最多重试 2 次,每次间隔 100ms,别无脑循环
notify_master 脚本里该不该执行 slaveof no one?看 Redis 版本和角色状态
Redis 6.2+ 支持 ROLE 命令返回当前角色,而老版本只能靠 INFO replication 解析文本。直接硬写 redis-cli slaveof no one 很危险:如果脚本被重复触发,或者旧主还没完全下线就切回来,可能把刚升主的新实例又降成从库。
正确做法是加状态判断。不要信配置文件里的“我应该是主”,要信 redis-cli role 的实时输出。
#!/bin/bash ROLE=$(redis-cli -h 127.0.0.1 role | head -n1 | tr -d '"') if [ "$ROLE" = "slave" ]; then redis-cli -h 127.0.0.1 slaveof no one > /dev/null 2>&1 fi
- Redis 7+ 可用
replicaof no one替代slaveof,更语义清晰 - 脚本末尾加
sleep 0.5,防止 Keepalived 连续触发多次 notify - 别忘了给脚本加可执行权限:
chmod +x /opt/redis-failover.sh,否则 Keepalived 日志只报 “failed to exec” 不报具体原因
为什么 arping -U 发包后客户端还是连不上?ARP 缓存和交换机学习延迟才是真瓶颈
VIP 漂移后,即使新主绑上了 IP,客户端所在机器的 ARP 表可能还记着旧主的 MAC 地址,交换机的 MAC 地址表也可能没及时更新。这时候光靠 arping -U -I eth0 192.168.10.100 是不够的——它只告诉局域网“这个 IP 现在我用”,但不强制客户端清缓存。
真正有效的是组合动作:新主发免费 ARP(arping),同时客户端侧主动刷新(arp -d 192.168.10.100 或重启网卡),中间交换机如果启用了 ARP 学习老化时间(默认 300s),那就只能等,或者进交换机清 MAC 表。
- Keepalived 配置里加上
notify_master "/usr/sbin/arping -U -I eth0 192.168.10.100",确保每次切主都广播一次 - 测试环境可在客户端执行
watch -n1 'arp -n | grep 192.168.10.100',观察 MAC 地址是否变化 - 生产环境别指望客户端配合清 ARP,得靠连接层容错——也就是前面说的短超时 + 快重试


















