错误信息:IllegalStateException: Invalidated object not currently part of this pool

一.问题描述

redis连接池,应用是刚重启的状态,执行操作是,开启10个线程同时执行10000次操作。

如下:


redis连接未释放 redis 连接释放_连接池

 

执行操作完毕后发现控制台输出9个下面错误信息:


redis连接未释放 redis 连接释放_无法释放_02


redis连接放回池内,放回连接池的对象是无效的对象。在网上查了很多同类错误,都说是进行了两次returnResource释放连接资源造成的,因为第一次return成功以后,第二次return就会报上面这个错误。但是显然,我翻遍了代码并没有两次调用returnResource。

redis服务端的连接数详细信息如下,前9个连接,idle=453,空闲了453秒了,依然没有释放,而连接池设置的是空闲60秒就会被释放,明显发生异常了。


redis连接未释放 redis 连接释放_连接池_03

 

redis操作,初始化redis连接池有问题。于是重启应用,先执行单线程redis操作,再执行多线程redis操作,没有发生上面的问题。redis服务端连接均能正常释放。由此得出结论,当线程池在未初始化的时候,由于多线程同时执行redis连接池初始化工作引起的问题。

RedisJedisPool未优化之前):当10个线程同时请求redis连接资源时,10个线程都发现连接池为空(因为创建连接池相比创建线程比较耗时),这时10个线程都各自初始化成功一个连接池,并从中取得redis连接,并执行了redis操作。执行完毕,returnResource的时候,由于此时pool变量的引用是最后一个线程初始化的连接池,前面9个线程获得的redis连接并不属于最后一个连接池的资源,所以抛错:IllegalStateException: Invalidated object not currently part of this pool



redis连接未释放 redis 连接释放_异常_04

 

二.报错原因分析

线程1    :  创建redis连接池1   : 获得redis连接1

线程2    :  创建redis连接池2   : 获得redis连接2

线程3    :  创建redis连接池3   : 获得redis连接3

……

线程8    :  创建redis连接池8   : 获得redis连接8

线程9    :  创建redis连接池9   : 获得redis连接9

线程10  :  创建redis连接池10 : 获得redis连接10

 

全局变量pool引用  指向   redis连接池10

 

当线程1-9 把redis连接1-9  归还给pool-redis连接池10

reds连接池10自然就报错,说:IllegalStateException: Invalidated object not currently part of this pool

 

三.解决办法

Spring容器管理,同时把初始化连接池和获取连接两个操作实现方法分离,对初始化连接池的方法加上同步锁机制,并且二次判断是否为空,就算多线程情况下,在二次判断是否为空的时候,pool已经不为空了,直接返回。现在多线程安全的问题就得以解决。 

附上,解决前后对比图:


redis连接未释放 redis 连接释放_redis连接未释放_05