博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ShardedJedisPool 中可用连接数的小bug
阅读量:5127 次
发布时间:2019-06-13

本文共 2614 字,大约阅读时间需要 8 分钟。

ShardedJedisPool中,returnBrokenResource() 及 returnResource() ,为施放资源、关闭连接的方法,若重复调用,导致 _numActive 当前活动数一直递减,会出现负数的情况。

假如在一个方法中设置了三个jedis连接,在获取第一或第二个连接时出现异常,在抛出异常或者finally中总是施放这三个资源,会导致池中的连接连续施放三次,从而变成负数。

这样会出现连接池最大连接数配置无效的情况。

 

以下片段代码:

public class RedisUtil {    public static ShardedJedisPool pool;    static {        JedisPoolConfig config = new JedisPoolConfig();// Jedis池配置        config.setMaxActive(2);// 最大活动的对象个数        config.setMaxIdle(1000 * 60);// 对象最大空闲时间        config.setMaxWait(1000 * 3);// 获取对象时最大等待时间        config.setTestOnBorrow(true);        String hostA = "192.168.0.99";        int portA = 6380;        List
jdsInfoList =new ArrayList
(1); JedisShardInfo infoA = new JedisShardInfo(hostA, portA); jdsInfoList.add(infoA); pool = new ShardedJedisPool(config, jdsInfoList); } public static void testRedis() { ShardedJedis jedis = null; ShardedJedis jedis1 = null; ShardedJedis jedis2 = null; try { // 从池中获取三次连接 jedis = pool.getResource(); jedis1 = pool.getResource(); jedis2 = pool.getResource(); String value = jedis.get("wuse"); String value1 = jedis1.get("wuse"); if (null == value || "".equals(value)) { jedis.set("wuse", "testWuse"); jedis.expire("wuse", 20); }else { System.out.println(value); } } catch (Exception e) { e.printStackTrace(); // 异常时关闭连接,此处可以注释 } finally { pool.returnBrokenResource(jedis); pool.returnBrokenResource(jedis1); pool.returnBrokenResource(jedis2); } }}

 

比如,设置的最大连接数为3,当第一次获取连接1和连接2的时候,没有问题,获取第三个连接的时候,由于最大连接数为2,所以抛异常

走finally之后,释放掉三个连接资源,这时候,pool连接池的当前活动数竟然为-1

所以,第二次再调用testRedis()方法时,由于之前pool的活动数为-1,这次三个连接都能获取成功,不抛异常。

 

-------------------------------------------------------------------------------

ShardedJedisPool类本身继承Pool类,Pool类中用了org.apache.commons.pool.impl.GenericObjectPool类来当做连接池,而Pool类初始化时,需要传入PoolableObjectFactory工厂类,在ShardedJedisPool类中自定义了一个继承BasePoolableObjectFactory类的工厂类ShardedJedisFactory,而ShardedJedisFactory类中的销毁方法destroyObject()方法中,从传进来的ShardedJedis对象里获取了镜像连接,继承的最顶层Sharded类中的getAllShards()方法,实际上只是通过Collections工具类获取了resources的value集合的镜像,所以实际上也就是说只是意义上释放了连接。 

而ShardedJedisPool类中的returnBrokenResource()方法,实际上调用的是GenericObjectPool类的invalidateObject()方法,而每次调用后,总会再去做 _numActive --,也就是说,每次调用,当前活动数都会减1,有可能最终导致负数(其实是与实际活动数不匹配),从而影响到原始设定的最大连接数会不管用。

 

 

 

转载于:https://www.cnblogs.com/anranwuse/p/3698052.html

你可能感兴趣的文章
myeclipse部署多个web工程
查看>>
tcp_协议基础
查看>>
layui弹窗 之 iframe关闭
查看>>
【BZOJ2565】最长双回文串 Manacher
查看>>
There is no PasswordEncoder mapped for the id "null"
查看>>
windows10 conda python多版本切换
查看>>
Linux配置日志服务器
查看>>
P6 EPPM 16.1 安装和配置指南 1
查看>>
C语言:九九乘法表打印
查看>>
Java_Activiti5_菜鸟也来学Activiti5工作流_之JUnit单元测试(四)
查看>>
codeforce626D (概率)
查看>>
HD1385Minimum Transport Cost(Floyd + 输出路径)
查看>>
Ajax技术
查看>>
MVC解决方案发布IIS 登录页面需要输入两次帐号问题
查看>>
Visual Studio 2017 初次体验
查看>>
zTree树
查看>>
tips 前端 点击事件
查看>>
python 学习教程
查看>>
Python下用Tkinter进行GUI编程
查看>>
Ajax异步刷新地址栏url改变(利用Html5 history.pushState实现)
查看>>