问题分析redis客户端连接数过多大量空闲连接和readonly连接

2次阅读

共计 1311 个字符,预计需要花费 4 分钟才能阅读完成。

问题

运维反应 redis 客户端连接数太多,超过默认最大限制 1W。
执行命令

./redis-cli –h host –p port info clients

查看 redis 客户端连接数,共 6 个节点每个节点都是 2000+

分析

执行命令

./redis-cli –h host –p port client list

查看具体连接信息,有大量空闲连接,主节点大量 cmd=null,从节点大量 cmd=readonly,且 idle 时间和 age 时间差不多大的连接


说明大部分连接都是没有用到的。

发现 Jedis 连接池的 minEvictableIdleTimeMillistimeBetweenEvictionRunsMillis都配置成了 -1,是不是 Jedis 连接池未及时回收连接的问题呢?但 maxTotal 配置的是 20,一共 30+ 个组件,不应该超过这个值啊!
写个脚本,先用 jps 查看组件 pid,再

netstat –tanlp | grep pid | wc -l

统计每个组件的连接,发现每个组件都已经十倍超出这个值,平均 200+。

打断点进入 Jedis 连接池中实现空闲连接检测的 GenericObjectPool.evict()方法,发现 IdleObjects 一直是 0,并没有需要丢弃的空闲连接。
基于对 commons-pool2 的信任,而且同个组件的 druid 连接池并没有出问题(两者用的都是用 commons-pool2 实现自己的连接池),我觉得问题应该出现在其他地方。

打开 java 进程的 jmx 功能(或者使用 idea 的 remote 远程调试功能),进一步分析,配置如下(看 key 就能明白作用):

-Djava.rmi.server.hostname=IP
-Dcom.sun.management.jmxremote.port=Port
-Dcom.sun.management.jmxremote.ssl=false 
-Dcom.sun.management.jmxremote.authenticate=false

用 jvisualvm 连接目标组件,发现 commons-pool-evictor-thread 线程在空闲着


可以确定 Jedis 连接池并没有多余的连接需要丢弃。

一顿分析,再重新看一次,发现有很多 redisson-netty 开头的线程一直在运行

框架中确实使用了 redisson,而且大部分配置项都是用的默认值,打个断点,SpringContextUtil.getBean(RedissonClient.class)获取 RedissonClient 到处看看,发现!
connectionManager 下面的 connectionWatcher 记录了使用到的 Redis 连接!

太多了,而且 lastUsageTime 都是组件刚启动的时候,说明并没有使用过!而且 6 个节点每个 32 个连接,再加上 Pubsub 连接的数量和 Jedis 连接池的数量,正好和统计出来的数量差不多!

解决方案

问题应该就在这里,将 Redisson 的 SlaveConnectionMinimumIdleSize 和 MasterConnectionMinimumIdleSize 设置成 1,重启组件再对比一下连接数

O~K~
还是配置的坑啊 – -!

正文完
 0