redis使用中经常出现 Could not get a resource from the pool 异常,解决办法总结

1 篇文章 0 订阅
1 篇文章 0 订阅

背景:

最近使用jedis(redis)开发一项功能,查阅日志发现,服务运行一段时间之后,就会出现

redis.clients.jedis.exceptions.JedisException: Could not get a resource from the pool 的异常,

重启就好了,但是过一段时间又出现这种情况;

我这里问题比较简单,释放连接的方法忘记调用了,应该是没有及时释放连接造成的连接池内无连接可用。


但是关于这个问题,发现网上有种种说法,主要是连接池配置释放连接,关于这个问题,我们不妨深入思考下:

 

一、连接池配置参数怎么设置?这些参数跟什么有关系?

         1、最大连接数:MAX_ACTIVE,指的是支持同时在使用的最大的连接数量:

              参数的设置并不是越大越好,而是要看自己的实际使用情况,也就是需要的并发数是多少?

              比如,系统并发量一般100,但是你的设置是50,显然这个时候加大设置是很有用的。

              但是,又比如这个业务最大可能并发100个链接,那么就没必要设置成2000,设置太大也可能会浪费系统性能;

              如果这时候设置远远高于实际了,还是出现连接不够用的情况,那么基本上就是你使用后忘记释放了。

         2、等待可用连接的最大时间:MAX_WAIT,这个时间设置,要结合最大连接数、实际并发数、还有系统性能一起考虑,一般不宜过大,否则会导致请求响应时间过长,甚至请求失败。但是也不能过小,如果系统资源比较富裕没什么影响,但是相反的话,过小的情况也可能造成较多的请求失败

               比如,设置成1分钟,那么假设此时并发数较高(MAX_ACTIVE一直占用着),一直没有得到可用连接,那么这个请求就会出现一直等待的情况,可能会出现给客户的感觉上系统反应卡顿的不良体验。

       3、有时为了保证请求快速得到响应,保持一定的空闲连接(setMinIdle)。在连接池饱和状态,最多有(MAX_ACTIVE-MinIdle)个连接数;

       4、如果并发数很大呢?大到超过redis支持的最大连接数?

           在 Redis2.4 中,最大连接数是被直接硬编码在代码里面的,而在2.6版本中这个值变成可配置的。maxclients 的默认值是 10000.也就是说,redis默认最多允许10000个连接。当然这还要看硬件环境,CPU/内存情况;

           真的有再大的需求,就只能是分布式/集群了,这里暂时不讨论。

          附上jedis工具类中的获取连接方法:

    private static String ADDR = "****";
    private static int PORT = 6379;
    
    //访问密码
    private static String AUTH = "****";
    
    //可用连接实例的最大数目,默认值为8;
    //如果赋值为-1,则表示不限制;如果pool已经分配了maxActive个jedis实例,则此时pool的状态为exhausted(耗尽)。
    private static int MAX_ACTIVE = 100;
    
    //控制一个pool最多有多少个状态为idle(空闲的)的jedis实例,默认值也是8。
    private static int MAX_IDLE = 10;
    
    //等待可用连接的最大时间,单位毫秒,默认值为-1,表示永不超时。如果超过等待时间,则直接抛出JedisConnectionException;
    private static int MAX_WAIT = 1000;
    
    private static int TIMEOUT = 10000;
    
    //在borrow一个jedis实例时,是否提前进行validate操作;如果为true,则得到的jedis实例均是可用的;
    private static boolean TEST_ON_BORROW = true;
    
    private static JedisPool jedisPool = null; 

//获取链接
    public static synchronized Jedis getJedis(){
        if(jedisPool==null){
        	log.info("jedisPool==null , to reGet ");
        	try {
                JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
                //指定连接池中最大空闲连接数
                jedisPoolConfig.setMaxIdle(MAX_IDLE);
                //链接池中创建的最大连接数
                jedisPoolConfig.setMaxTotal(MAX_ACTIVE);
                //设置创建链接的超时时间
                jedisPoolConfig.setMaxWaitMillis(MAX_WAIT);
                //表示连接池在创建链接的时候会先测试一下链接是否可用,这样可以保证连接池中的链接都可用的。
                jedisPoolConfig.setTestOnBorrow(true);
                jedisPool = new JedisPool(jedisPoolConfig,ADDR, PORT, TIMEOUT, AUTH);
                
			} catch (Exception e) {
				log.error("jedisPool get error "+e.toString());
			}
        }
        return jedisPool.getResource();
    }

二、释放连接的替代方法

          在网上的资料,很多都是已经废弃不用的方法,我这把替代方法贴一下:

          starting from Jedis 3.0 this method will not be exposed. Resource cleanup should be done using @see {@link redis.clients.jedis.Jedis#close()} (废弃方法returnResource和returnBrokenResource的注释)

   //回收链接 
    public static synchronized void returnResource(Jedis jedis){
    	try {
    		if(jedis!=null){
    			/*
    			 * 这些方法已经废弃
    			 */
        		jedisPool.returnResource(jedis);
//        		jedisPool.returnBrokenResource(jedis);
        		log.info("returnResource success ");
        	}
		} catch (Exception e) {
			log.error("returnResource error "+e.toString());
		}
    }
    
    //释放链接
    public static synchronized void returnToPool(Jedis jedis){
    	try {
    		if(jedis!=null){
    			jedis.close();//替代方法
        		log.info("returnToPool success ");
        	}
		} catch (Exception e) {
			log.error("returnToPool error "+e.toString());
		}
    }

 

 

这次就总结到这儿,下次需要更深入研究下redis分布式缓存。

 

  • 5
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值