Redis怎样排查Spring项目中的Redis连接泄露

张开发
2026/4/12 9:09:23 15 分钟阅读

分享文章

Redis怎样排查Spring项目中的Redis连接泄露
connected_clients持续上涨是Redis连接泄露的最直接信号需多次执行info clients观察趋势结合CLIENT LIST查idle过大或来源集中的异常连接并检查Jedis手动获取是否漏close、Lettuce是否误new客户端、线程是否阻塞在getResource。看 connected_clients 是否持续上涨这是最直接的信号如果 Redis 服务端的连接数只增不减基本坐实了泄露。用 redis-cli -a yourpass info clients 查看 connected_clients 字段隔几十秒多跑几次观察趋势。别只看一次——有些泄露是缓慢积累的尤其低并发内部系统可能几天才涨到几千。顺手再跑 CLIENT LIST重点关注 idle 值极大比如 3600 秒或 addr 来源集中在某台应用机器的连接。这些大概率是“借出去没还”的连接。运维常忽略一点Spring Boot 默认启用 Lettuce 客户端它底层是基于 Netty 的连接复用connected_clients 上涨 ≠ 每次操作都建新连接但若持续上涨说明连接未被正确回收或连接池未生效如果用的是老项目配的 Jedisconnected_clients 几乎等于活跃连接数上涨就更危险注意区分连接数突增也可能是短时压测或主从切换重连风暴要结合时间点和业务变更日志交叉判断查 Spring 中 RedisTemplate 或 Jedis 获取逻辑是否漏 closeSpring 管理的 RedisTemplate 本身不涉及手动释放但一旦你绕过它、直接从 JedisPool 拿连接就必须确保归还——哪怕在异常分支里。典型错误写法public void badExample() { Jedis jedis jedisPool.getResource(); try { jedis.set(key, val); } catch (Exception e) { log.error(e); // ? 忘了 close连接永远卡在 borrowed 状态 }}正确做法必须带 finally 或用 try-with-resourcespublic void goodExample() { Jedis jedis null; try { jedis jedisPool.getResource(); jedis.set(key, val); } finally { if (jedis ! null) jedis.close(); // ? 归还给池不是销毁 }}jedis.close() 在 Jedis 3.x 中等价于 returnResource不是关 TCPJedis 2.x 需显式调用 returnResource否则会报错用 Autowired RedisTemplate 是安全的但若项目混用了 StringRedisTemplate 手动 Jedis容易在同一个 Bean 里漏掉清理特别警惕 RedisMessageListenerContainer它内部持有一个长期连接若配置了错误的重试策略如无限重连会在后台偷偷建大量连接抓线程堆栈看是不是卡在 Pool.getResource当应用变慢、CPU 不高但线程数飙升时立刻 jstack pid jstack.txt然后搜 getResourcecat jstack.txt | grep getResource | wc -l如果返回几百甚至上千说明大量线程堵在取连接这一步——不是没连接可用就是连接池满了根源还是已有连接没归还。 唱鸭 音乐创作全流程的AI自动作曲工具集 AI 辅助作词、AI 自动作曲、编曲、混音于一体

更多文章