秒级切换双机热备的核心是Keepalived检测节奏压缩(advert_int=1、fail_count/rise_count=2)、Nginx健康接口精准反馈(/healthz联动upstream状态)、网络层ARP优化与平滑重启(worker_shutdown_timeout=3s),三者协同确保1–3秒内完成业务无感切流。

要实现秒级切换的双机热备,核心不是堆组件,而是让 Keepalived 的检测足够快、Nginx(或数据库/Redis等服务)的状态反馈足够准、网络层响应足够及时。主备之间不靠“猜”,而靠可验证的健康信号驱动切换。
Keepalived 必须调紧检测节奏
默认配置下,Keepalived 通常每3秒发一次 VRRP 通告,连续3次失败才切换——这已超5秒,远达不到秒级要求。必须主动压缩:
- advert_int 设为 1:VRRP 通告间隔压到每秒1次
- fail_count 和 rise_count 均设为 2:连续2次检测失败即降级,2次成功即升回,避免抖动误切
-
禁用 preempt(备机侧):加
nopreempt,防止主节点恢复后抢 VIP 导致反复漂移 - priority 差值 ≥ 50:主备优先级拉开差距,配合 nopreempt 更稳
健康检查不能只看端口通不通
用 kill -0 或 nc -z 检查 Nginx 进程或端口,只能说明“进程活着”或“端口开着”,但无法反映业务是否就绪。真实场景中,Nginx 可能卡在 reload、上游全挂、限流触发等状态,此时它仍监听6379或80端口,却无法正常服务。
-
Nginx 配置暴露 /healthz:添加
location /healthz { return 200 'ok'; },确保该路径不受鉴权、限流、upstream 异常影响 -
Keepalived 调用 curl 检查该接口:脚本中用
curl -f -s http://127.0.0.1:80/healthz -o /dev/null,非200即判为异常 -
若代理后端服务,建议 healthz 联动 upstream 状态:例如用
ngx_http_upstream_check_module或轻量健康探针服务返回真实就绪态
服务重启必须平滑,避免切流丢请求
切换瞬间如果旧 Nginx worker 还在处理连接,而新实例尚未承接,就会丢包。这不是 Keepalived 的问题,而是服务自身未做好退出准备。
-
永远用
nginx -s reload,不用 stop/start:保证旧 worker 继续处理已有连接 -
配置
worker_shutdown_timeout 3s:给旧 worker 最多3秒完成存量请求再退出 -
操作系统层面关闭 ARP 干扰:执行
echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore和echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce,让 VIP 的 ARP 响应更准确及时
验证必须实测业务流量中断时间
日志里看到 “Transition to MASTER” 不代表业务已恢复。真正关键的是客户端感知到的中断时长。
-
用 watch + curl 持续探测:例如
watch -n 0.2 'curl -I -s -w "%{http_code}\n" -o /dev/null http://VIP/healthz 2>/dev/null' - 模拟主节点宕机(如 systemctl stop keepalived),观察从第一个非200到下一个200之间的时间差
- 压测时同步抓包:确认 TCP RST 或重传是否发生在切换窗口内,排除客户端重试掩盖真实延迟

















