Redis集群中“僵尸连接”指服务端持续挂起但无响应的连接,表现为CLIENT LIST中idle飙升、age增长、flags为N且qbuf为空;需用CLIENT KILL ADDR或ID精准清理,避免误杀;timeout配置对已认证连接无效,依赖tcp-keepalive机制防僵尸。

Redis集群里出现“僵尸连接”,不是靠客户端感知,而是服务端持续挂着但不再响应——CLIENT LIST 里 idle 值飙升、age 持续增长、flags 仍是 N(正常)却无任何命令交互,基本就是了。
怎么看哪些连接是僵尸的?
直接运行 CLIENT LIST,重点盯三个字段:
-
idle:连接空闲秒数。超过你业务预期(比如 300 秒)还没动作,大概率已卡住 -
age:连接存活总秒数。> 3600 且idle同步高,说明连上来就没动过或中途挂了 -
cmd:最近执行命令。长期显示client或ping,没真实业务命令,值得怀疑
注意:flags 为 O(阻塞)或 B(正在执行 blocking command)不算僵尸;真正危险的是 N + 高 idle + 零 qbuf(输入缓冲区为空)的组合。
怎么安全地 kill 僵尸连接?
别用通杀脚本,先定位再动手:
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 按 IP+端口 kill:
CLIENT KILL ADDR 192.168.1.100:54321—— 最常用,精准且不影响其他连接 - 按 ID kill:
CLIENT KILL ID 12345—— 适合脚本自动化,但 ID 在连接断开后会复用,需配合age/idle判断 - 批量过滤 kill(慎用):
redis-cli client list | awk '$5 ~ /idle=[0-9]{4,}/ {print $2}' | cut -d= -f2 | xargs -r -I{} redis-cli client kill {}—— 仅限临时救火,生产环境建议加sleep和日志记录
⚠️ 不要用 CLIENT KILL TYPE normal 这类宽泛指令——它会干掉所有普通连接,包括正在跑 pipeline 的合法连接。
为什么 timeout 配置经常失效?
Redis 的 timeout 参数(如 config set timeout 300)只对 *未认证* 或 *未发任何命令* 的连接生效。一旦客户端完成 AUTH 并执行过至少一条命令,这个超时就自动失效了。
- 所以你在
CLIENT LIST里看到age=1200 idle=1190,但连接还在,不是 bug,是设计如此 - 真正起作用的是 TCP 层的
tcp-keepalive:Linux 内核每tcp_keepalive_time(默认 7200 秒)发探测包,收不到 ACK 就断链 —— 这才是防僵尸的底层防线 - 必须在 Redis 配置里显式打开:
tcp-keepalive 60(单位秒),否则内核 keepalive 不启用
集群环境下要额外注意什么?
Redis Cluster 节点间也有连接,但 CLIENT LIST 默认只显示当前节点的客户端连接,不包含 cluster bus(gossip 协议)连接。
- 查集群内部连接用:
CLUSTER NODES看各节点状态,INFO REPLICATION看主从连接健康度 - 集群中某个节点的客户端连接被 kill,不会触发 failover;但若该节点自身因网络分区失联,
cluster-node-timeout才会起作用 - 运维脚本如果跨节点操作,必须逐个节点连上去执行
CLIENT LIST和CLIENT KILL,不能只扫一个 master
最常被忽略的一点:Jedis/Lettuce 等客户端即使配置了 maxWaitMillis 和 blockWhenExhausted=false,也拦不住服务端残留的僵尸连接——它们早就不响应了,池子只是等不到归还。清理必须双管齐下:客户端代码确保 close() 落地,服务端用 tcp-keepalive + 定期 CLIENT KILL 补漏。

















