特别提示:每个人导致的该报错的原因不一样。
已经做过的排查:
1.排查了地址池初始化问题
2.排查了所有调用地方是否都关闭了
3.排查了配置参数
以上步骤排查完,程序还是会报错。
通过 JedisPool 的 getNumActive 方法,知道连接数会一直增加
通过在redis控制台输入client list,获得以下信息:
每个字段含义如下:
addr:客户端的地址和端口
fd:套接字所使用的文件描述符
idle:以秒计算的空闲时长
flags:客户端 flag
db:该客户端正在使用的数据库 ID
sub:已订阅频道的数量
psub:已订阅模式的数量
multi:在事务中被执行的命令数量
qbuf:查询缓冲区的长度(字节为单位, 0 表示没有分配查询缓冲区)
qbuf-free:查询缓冲区剩余空间的长度(字节为单位, 0 表示没有剩余空间)
obl:输出缓冲区的长度(字节为单位, 0 表示没有分配输出缓冲区)
oll:输出列表包含的对象数量(当输出缓冲区没有剩余空间时,命令回复会以字符串对象的形式被入队到这个队列里)
omem:输出缓冲区和输出列表占用的内存总量
events:文件描述符事件
cmd:最近一次执行的命令
通过上图,得到以下信息:
1. idle表示空闲时长,确定未释放连接的缘故,导致连接池无空闲连接。
2.发现都是写入操作
去查找封装的jedis操作类,发现调用方基本都是调用该方法,有设置过期时间。
在set方法中添加日志,查看是写入了那些key和second值。
敲黑板:缓存失效时间小于0时,抛出异常。
到这里的时候,在日志文件中也发现了一条 ERR invalid expire time in setex 错误日志。
确定自己的怀疑,可能是某个地方调用时,会传入负数,排查到后加上非负数处理,至此问题解决。
啰嗦几句:是多线程环境,日志中只有Could not get a resource from the pool错误, ERR invalid expire time in setex 错误是唯一一条,不眼尖还发现不了。写入异常可能在深层次的代码中被处理了,没有被抛出来。