✅ 问题场景简述
- 正在生产环境不停服迁移 Redis 实例;
- 使用双写方案,同时写入老旧 Redis(A)和新 Redis(B);
- 准备下线老 Redis(A),但发现有客户端始终维持连接不释放;
- 需要找出这些客户端,确认来源,推动其断开或改配置。
🔍 如何排查连接来源
1. 使用 CLIENT LIST
命令排查连接
在老 Redis 实例中执行:
redis-cli -h OLD_REDIS_IP -p PORT CLIENT LIST
输出类似:
id=16 addr=192.168.1.101:43892 fd=8 name= db=0 idle=12 flags=N ...
id=17 addr=172.16.0.5:51234 fd=9 name=worker1 db=0 idle=0 ...
重点字段:
字段 | 说明 |
---|---|
addr | 客户端的 IP 和端口 |
name | 如果客户端设置了 CLIENT SETNAME ,可看到服务名 |
idle | 空闲秒数(idle=0 表示活跃) |
flags | N=普通连接,M=主节点等 |
2. 找出活跃连接
你可以用脚本过滤出活跃连接(idle=0
):
redis-cli CLIENT LIST | grep 'idle=0'
或者全部看一遍:
redis-cli CLIENT LIST | awk -F' ' '{for(i=1;i<=NF;i++) if($i ~ /^addr=/) print $i}'
3. 找出连接来源主机
一旦你拿到 addr=192.168.1.101:43892
,你就知道是哪个机器连接的。
进入该机器后,可以用以下方式找出进程:
sudo lsof -i :6379
或查哪个进程连接目标 Redis IP:
sudo netstat -ntp | grep 6379
你会看到输出类似:
tcp 0 0 192.168.1.101:43892 10.0.0.2:6379 ESTABLISHED 1234/php-fpm
这样你就可以精确定位是哪个服务、哪个程序、哪个端口还在连老 Redis。
🚨 强制断开连接(可选)
如果你确认某个连接不应该存在,可以使用 Redis 命令断开它:
CLIENT KILL addr IP:PORT
例:
CLIENT KILL 192.168.1.101:43892
🛡️ 最佳实践建议
- 所有服务启动时务必执行
CLIENT SETNAME your-service-name
,方便后续排查。 - 使用统一的 Redis 中间件管理连接,避免散落配置。
- Redis 连接池配置 TTL,确保老连接不会无限期持续。
- 切换前可写监控脚本观察是否还有旧地址连接。
✅ 小结
目标 | 方法 |
---|---|
找到还在连的客户端 | CLIENT LIST |
分析来源 | 提取 IP + 端口,登录源机器排查进程 |
强制断开 | CLIENT KILL |
防止类似情况 | CLIENT SETNAME + 连接池 TTL + 服务统一配置 |