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为适合自己系统的阀值。

 
  1. [color=red][/color]

但这个自己也设置了,配置如下:

 

 

 
  1. #最大活动对象数

  2. redis.pool.maxTotal=1000

  3. #最大能够保持idel状态的对象数

  4. redis.pool.maxIdle=100

  5. #最小能够保持idel状态的对象数

  6. redis.pool.minIdle=50

  7. #当池内没有返回对象时,最大等待时间

  8. redis.pool.maxWaitMillis=10000

  9. #当调用borrow Object方法时,是否进行有效性检查

  10. redis.pool.testOnBorrow=true

  11. #当调用return Object方法时,是否进行有效性检查

  12. redis.pool.testOnReturn=true

  13. #“空闲链接”检测线程,检测的周期,毫秒数。如果为负值,表示不运行“检测线程”。默认为-1.

  14. redis.pool.timeBetweenEvictionRunsMillis=30000

  15. #向调用者输出“链接”对象时,是否检测它的空闲超时;

  16. redis.pool.testWhileIdle=true

  17. # 对于“空闲链接”检测线程而言,每次检测的链接资源的个数。默认为3.

  18. redis.pool.numTestsPerEvictionRun=50

  19. #表示一个对象至少停留在idle状态的最短时间,然后才能被idle object evitor扫描并驱逐;这一项只有在timeBetweenEvictionRunsMillis大于0时才有意义

  20. MinEvictableIdleTimeMillis=60000

  21. #redis服务器的IP

  22. redis.ip=xxxxxx

  23. #redis服务器的Port

  24. redis1.port=6379

但是这样设置后,当运行一段时候后还是会报同样的错误,说句不爱听的话最大链接数“1000”这个值真的不小,但还是错误,所以肯定不是这个值的原因。

 

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

 

 
  1. public class JedisUtils {

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

  3.  
  4. /**

  5. * 自动注入Redis连接实例对象线程池

  6. */

  7. @Autowired

  8. private JedisPool jedisPool;

  9.  
  10. /**

  11. * 获取Jedis对象

  12. *

  13. * @return

  14. */

  15. public synchronized Jedis getJedis() {

  16. Jedis jedis = null;

  17. if (jedisPool != null) {

  18. try {

  19. if (jedis == null) {

  20. jedis = jedisPool.getResource();

  21. }

  22. } catch (Exception e) {

  23. logger.error(e.getMessage(), e);

  24. }

  25. }

  26. return jedis;

  27. }

  28.  
  29. /**

  30. * 回收Jedis对象资源

  31. *

  32. * @param jedis

  33. */

  34. public synchronized void returnResource(Jedis jedis) {

  35. if (jedis != null) {

  36. jedisPool.returnResource(jedis);

  37. }

  38. }

  39.  
  40. /**

  41. * Jedis对象出异常的时候,回收Jedis对象资源

  42. *

  43. * @param jedis

  44. */

  45. public synchronized void returnBrokenResource(Jedis jedis) {

  46. if (jedis != null) {

  47. jedisPool.returnBrokenResource(jedis);

  48. }

  49.  
  50. }

  51. }


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

 

业务类、方法代码如下:

 

 
  1. Jedis jedis = jedisUtils.getJedis();

  2. if(jedis == null){

  3. throw new NullPointerException("Jedis is Null");

  4. }

  5. try{

  6. long queueCurrValue = jedis.llen(messageQueueName);

  7. if(queueCurrValue >= queueMaxSize){

  8. return addFlag;

  9. }

  10. String serizlizetValue = JSON.toJSONString(message);

  11. if(StringUtils.isNotBlank(serizlizetValue)){

  12. long queueLength = jedis.lpush(messageQueueName, serizlizetValue);

  13. if(queueLength - queueCurrValue > 0){

  14. addFlag = true;

  15. }

  16. }

  17. }catch(Exception e){

  18. jedisUtils.returnBrokenResource(jedis);

  19. logger.error(e.getMessage(), e);

  20. }finally{

  21. jedisUtils.returnResource(jedis);

  22. }


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

 

 

 
  1. #最大链接数

  2. MaxTotal=100

  3. #空闲时最大链接数

  4. MaxIdle=20

  5. #空闲最小

  6. MinIdle=8

  7. #链接最大等待时间 (毫秒)

  8. MaxWaitMillis=10000


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

 

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

 

 
  1. // 释放资源

  2. public synchronized void returnResource(Jedis jedis) {

  3. if (jedis != null) {

  4. pool.returnResource(jedis);

  5. }

  6. }

  7.  
  8. // 出现异常释放资源

  9. public synchronized void returnBrokenResource(Jedis jedis) {

  10. if (jedis != null) {

  11. pool.returnBrokenResource(jedis);

  12. }

  13. }


两个方法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


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

转自:https://blog.csdn.net/qh_java/article/details/54669973

你可能感兴趣的:(Java)