服务项目背景
一个查询服务,使用到了两个redis,一个做查询缓存,一个做查询统计,使用了线程池处理,并动态切换。
异常现象与初步分析
使用2000并发测试接口,发现查询到第10万次的时候,连接全部堵塞了。
1.以为是redis线程池配置问题
2.怀疑是程序死锁,
3.查看日志发现全部报错
Cannot get Jedis connection; nested exception is redis.clients.jedis.excepti (
因设置的线程池超时时间为三秒,当设置成-1的时候会全部堵塞在此处)
源码分析
jeidis 2.9.1
JedisSentinelPool.getResource(
)
jedis.close()
分析:
In the case of concurrency
Thread A return an object but not run to “this.dataSource = null” yet
Thread B borrow an object and set dataSource to this;
And Then Thread A run this.dataSource = null;
Finally Thread A will never returnResource because dataSource is null
简化版本: 线程A先将连接还给了连接池,最后对象置为null,如果在 A线程归还给线程池时,B线程瞬间获取到此连接,随后线程A将此连接置为null,就永远不会被回收给线程池
官方解读:
官方修订版
升级方案
<dependencies>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.10.2</version>
</dependency>
</dependencies>
评论区