Redis服务端tcp-keepalive是通过setsockopt(SO_KEEPALIVE)控制TCP保活的参数,默认为0(禁用),需设为60等合理值以适配中间设备300–900秒超时,避免连接静默中断导致集群异常。

Redis 集群节点间默认使用长连接,但若中间存在 NAT、防火墙或负载均衡器(如 AWS NLB、阿里云 SLB),连接可能在空闲时被强制中断;根本解法是启用并调大 tcp-keepalive,而非依赖客户端重连。
Redis 服务端的 tcp-keepalive 是什么,为什么必须设
这是 Redis 内部调用 setsockopt(SO_KEEPALIVE) 控制 TCP 连接保活的行为,和客户端的 keepalive 无关。集群节点(redis-server)之间、以及客户端与服务端之间,只要走 TCP,就受此参数影响。默认值为 0(禁用),意味着操作系统按自身策略决定是否发 keepalive 包(Linux 默认 2 小时才探测),远超大多数中间设备的空闲超时阈值(常见 300–900 秒)。
不开启或设得太小会导致:
- 集群节点握手后看似正常,但某次长时间无命令交互后,中间设备静默丢弃连接,后续通信失败,出现
Connection refused或read: connection reset by peer - 客户端报
READONLY You can't write against a read only replica等异常,实则是连接已断但客户端未感知,误将请求发到旧连接 - 运维排查时发现
CLUSTER NODES显示节点状态为fail,但 ping 和端口检测都通——本质是 TCP 连接已死,心跳包没发出去
如何正确配置 tcp-keepalive 参数
该参数单位是秒,在 redis.conf 中设置,需同时满足:「探测间隔 × 探测次数 ≤ 中间设备超时时间」。典型配置如下:
tcp-keepalive 60
这表示:连接空闲 60 秒后开始发送 keepalive 探测包,系统默认最多重试 9 次(Linux),每次间隔约 75 秒,总探测窗口约 12 分钟,足够覆盖绝大多数设备的 5–10 分钟超时。
关键注意事项:
- 必须在所有集群节点(包括 master 和 replica)上统一配置,否则链路中任一节点未启用,整条路径仍可能中断
- 不要设为小于 30:部分云厂商设备对过于频繁的 keepalive 包会限速或丢弃
- 无需修改内核参数(如
net.ipv4.tcp_keepalive_time),Redis 自己控制 socket 层行为,优先级更高 - 配置后需
redis-cli CONFIG REWRITE或重启生效;用CONFIG GET tcp-keepalive可验证是否加载成功
客户端连接也得配 keepalive,但逻辑不同
服务端 tcp-keepalive 保障的是节点间通信链路存活;而客户端(如 Python 的 redis-py、Node.js 的 ioredis)需单独配置自己的 TCP keepalive,防止客户端→服务端单向断连。
例如 ioredis:
const redis = new Redis({
host: 'xxx',
port: 6379,
enableReadyCheck: false,
keepAlive: 60000 // ms,即每 60 秒发一次 TCP keepalive
});
注意点:
-
keepAlive是客户端库的选项,和 Redis 服务端的tcp-keepalive无关联,不能互相替代 - Java 的 Jedis 默认不启用 socket keepalive,需手动调用
setSoKeepAlive(true) - 若使用连接池(如
lettuce),keepalive 需在ClientResources中配置,而非单个连接
真正容易被忽略的是:集群模式下,tcp-keepalive 对 gossip 协议通信同样生效。哪怕你只做读操作,只要节点间有定期 CLUSTER PING 流量,底层 TCP 连接仍可能因空闲被斩断——所以不是“用了集群就自动高可用”,而是每个环节的保活都要对齐中间设备的脾气。











