记一次生产 redis 连接全部打满错误
发现
生产的一个查询界面高延迟,后又陆续发现一些无响应的接口。
经排查出现问题的流程都有和redis交互。
咨询近一期迭代有升级redis客户端。
打开服务器。使用redis-cli命令client list
client list 命令文档 :https://redis.io/commands/client-list/
实时redis连接信息如下,观察一下几点:
addr: 地址
age: 总时间
idle: 空闲时间
发现有大量age=idle 并且cmd为cluster的无效连接
此时脑中模拟画面 ==》在某个不起眼的角落,有行代码在悄悄的不停的创建连接:我就是建着玩,你能拿我怎么样?)
打开git log 提交记录,查看近期有和 redis-cluster 有关的代码
-
发现一处可能存在问题的地方
图一 -
继续进去看getJedisResource方法
图二 -
此时可以看到明显疑问点
a. 图一中424L 代码 close是否合理(正常情况下池化思想,比如线程池,比如数据库连接池,开箱即用,不需要去手动调度)
b. 图一中在循环中操作redis可以接受。但是 操作redis的工具点进去,也就是图二是一个 new 方法。在循环中 new redis 的集群客户端的做法是否正确(这里差不多就是此次打满redis连接的元凶了)。
- 打开redis客户端的文档
- 打开redis中文网->资源->客户端-> 左侧选择java->找到jedis。
- 跳转github 。阅读readme部分片段可以得出结论
第一: 集群客户端是不需要重复创建的。可以想象一下mysql 的连接池概念,都是一个思路写出来的东西。
第二: 在使用连接完毕后,是不需要自己关闭的。
代码修改,完结发版
在有着少些代码就少出bug 的良好习惯上[dog]。上VSCODE,开整:
- 注释掉close方法
- for循环整体结构不变。getJedisR... 方法中new 改为单例。部分代码如下:
提交代码。 合并发版。通知相关小伙伴注意后期使用。
------完结撒花-----------
ps: 连接池,调度池,等等什么池, 都是类似线程池的思想。大差不差跑不了那7个入参的设计。所以当自己在工作中写池工具的时候:
首先 固定或者最少活跃数。 就像此次redis集群客户端中的那样。如果没有固定连接数的话。 也不会for循环它会把redis连接数打满。
其次 自己创建出来的线程或者对象要记得自己去管理其生命周期。 就像redis-cluster中自己封装好了close方法一样。不需要使用者去操心这个池领域内的任何事情。
最后希望 奋斗在一线的同志们写出来的代码都像 一个完整产品一样。璀璨夺目。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· .NET Core 中如何实现缓存的预热?
· 三行代码完成国际化适配,妙~啊~
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?