redis中 Could not get a resource from the pool 异常解决

在项目中使用redis做缓存,当运行一段时间后就会出现如下错误:Could not get a resource from the pool,然后在看具体的异常信息就是JedisPool中获取不到jedis对象,也就是说连接池中没有可用的jedis。

自己的第一反应就是把最大链接数(setMaxTotal)调大一些,刚开始设置了100、后来200、在后来2000都不行

然后上网一搜发现大家的回答也都是修改最大连接数,如下demo就是网上一篇博客的解释:

1、产生原因:客户端去redis服务器拿连接(代码描述的是租用对象borrowObject)的时候,池中无可用连接,即池中所有连接被占用,且在等待时候设定的超时时间后还没拿到时,报出此异常。

2、解决办法:调整JedisPoolConfig中maxActive为适合自己系统的阀值。

<bean id="dataJedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
        [color=red]<property name="maxActive" value="5000"/>[/color]
        <property name="maxIdle" value="5000"/>
        <property name="maxWait" value="10000"/>
        <property name="testOnBorrow" value="true"/>
</bean>
但这个自己也设置了,配置如下:

#最大活动对象数     
redis.pool.maxTotal=1000    
#最大能够保持idel状态的对象数      
redis.pool.maxIdle=100  
#最小能够保持idel状态的对象数   
redis.pool.minIdle=50    
#当池内没有返回对象时,最大等待时间    
redis.pool.maxWaitMillis=10000    
#当调用borrow Object方法时,是否进行有效性检查    
redis.pool.testOnBorrow=true    
#当调用return Object方法时,是否进行有效性检查    
redis.pool.testOnReturn=true  
#“空闲链接”检测线程,检测的周期,毫秒数。如果为负值,表示不运行“检测线程”。默认为-1.  
redis.pool.timeBetweenEvictionRunsMillis=30000  
#向调用者输出“链接”对象时,是否检测它的空闲超时;  
redis.pool.testWhileIdle=true  
# 对于“空闲链接”检测线程而言,每次检测的链接资源的个数。默认为3.  
redis.pool.numTestsPerEvictionRun=50  
#表示一个对象至少停留在idle状态的最短时间,然后才能被idle object evitor扫描并驱逐;这一项只有在timeBetweenEvictionRunsMillis大于0时才有意义
MinEvictableIdleTimeMillis=60000
#redis服务器的IP    
redis.ip=xxxxxx  
#redis服务器的Port    
redis1.port=6379   
但是这样设置后,当运行一段时候后还是会报同样的错误,说句不爱听的话最大链接数“1000”这个值真的不小,但还是错误,所以肯定不是这个值的原因。

后来在网上找到了一篇文章,文章中的jedis工具类中有三个方法,代码如下:

public class JedisUtils {
	private static Log logger = LogFactory.getLog(JedisUtils.class);

	/**
	 * 自动注入Redis连接实例对象线程池
	 */
	@Autowired
	private JedisPool jedisPool;

	/**
	 * 获取Jedis对象
	 * 
	 * @return
	 */
	public synchronized Jedis getJedis() {
		Jedis jedis = null;
		if (jedisPool != null) {
			try {
				if (jedis == null) {
					jedis = jedisPool.getResource();
				}
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
			}
		}
		return jedis;
	}

	/**
	 * 回收Jedis对象资源
	 * 
	 * @param jedis
	 */
	public synchronized void returnResource(Jedis jedis) {
		if (jedis != null) {
			jedisPool.returnResource(jedis);
		}
	}

	/**
	 * Jedis对象出异常的时候,回收Jedis对象资源
	 * 
	 * @param jedis
	 */
	public synchronized void returnBrokenResource(Jedis jedis) {
		if (jedis != null) {
			jedisPool.returnBrokenResource(jedis);
		}

	}
}

有两个回收方法发现没,一个是正常结束时调用释放jedis资源而另一个是在出现异常时调用释放jedis资源。

业务类、方法代码如下:

  Jedis jedis = jedisUtils.getJedis();  
        if(jedis == null){  
            throw new NullPointerException("Jedis is Null");  
        }  
        try{  
            long queueCurrValue = jedis.llen(messageQueueName);  
            if(queueCurrValue >= queueMaxSize){  
                return addFlag;  
            }  
            String serizlizetValue = JSON.toJSONString(message);  
            if(StringUtils.isNotBlank(serizlizetValue)){  
                long queueLength = jedis.lpush(messageQueueName, serizlizetValue);  
                 if(queueLength - queueCurrValue > 0){  
                    addFlag = true;  
                }  
            }  
        }catch(Exception e){  
            jedisUtils.returnBrokenResource(jedis);  
            logger.error(e.getMessage(), e);  
        }finally{  
            jedisUtils.returnResource(jedis);  
        }  

看到没在finally{} 代码块和 catch(){} 异常中都调用了相关方法,来释放jedis资源,这样就不会出现之前的那种异常了,当然最大链接数也不用设置那么大,下面看看修改后的配置文件

#最大链接数
MaxTotal=100
#空闲时最大链接数
MaxIdle=20
#空闲最小
MinIdle=8
#链接最大等待时间 (毫秒)
MaxWaitMillis=10000

就这值,再也没出现获取不到资源的的异常,问题解决了,所以问题不是最大链接数小了,而是没有释放资源,所以不管你设置多大的值都会出现异常而且消耗了大量的资源。

单我在项目中使用的时候有如下问题:

        // 释放资源
	public synchronized void returnResource(Jedis jedis) {
		if (jedis != null) {
			pool.returnResource(jedis);
		}
	}

	// 出现异常释放资源
	public synchronized void returnBrokenResource(Jedis jedis) {
		if (jedis != null) {
			pool.returnBrokenResource(jedis);
		}
	}

两个方法returnResource(jedis)、 和returnBrokenResource(jedis) 都被画了横线即过时废弃了,而还不知替换方法所以有知道的请指教,先谢谢了!


相关文章推荐:

http://www.codeweblog.com/redis%E6%9C%8D%E5%8A%A1%E5%99%A8%E6%90%AD%E5%BB%BA-%E9%85%8D%E7%BD%AE-%E5%8F%8Ajedis%E5%AE%A2%E6%88%B7%E7%AB%AF%E7%9A%84%E4%BD%BF%E7%94%A8%E6%96%B9%E6%B3%95/

http://www.codeweblog.com/jedis%E8%BF%9E%E6%8E%A5%E6%B1%A0%E9%85%8D%E7%BD%AE/

http://www.codeweblog.com/jedis-returnresource%E4%BD%BF%E7%94%A8%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A1%B9/

http://fengguang0051.iteye.com/blog/2237171

不过其中的两篇文章也会比自己转载做笔记的……






没有更多推荐了,返回首页