【问题标题】:Cannot get Jedis connection, Could not get a resource from the pool无法获取 Jedis 连接,无法从池中获取资源
【发布时间】:2018-03-18 06:59:19
【问题描述】:

我正在创建一个 Web 应用程序并使用 Redis 进行数据存储。 我用过 JedisPoolConfig (redis client-jedis version 2.9.0) 。 因此,当我在 Apache Jmeter 的帮助下使用以下配置测试我的应用程序时:

Number of threads(Users): 30
Ramp-Up period(in seconds) : 0
Loop-Count : 1

和 JedisPoolConfig 配置如下:

redis.sentinel.enable=true
redis.sentinel.ip=localhost
redis.sentinel.port=6379
redis.instance.account.masterName=master
redis.pool.max-active = 20
redis.pool.max-idle = 10

使用此代码(在 Spring 应用程序启动时创建为 Bean):

JedisConnectionFactory factory = new JedisConnectionFactory();
        factory.setPort(port);
        factory.setHostName(hostName);
        factory.afterPropertiesSet();
        factory.setUsePool(true);
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        jedisPoolConfig.setMaxTotal(redisPoolMaxActive);
        jedisPoolConfig.setMaxIdle(redisPoolMaxIdle);
        factory.setPoolConfig(jedisPoolConfig);
        return factory;

使用此代码在每次请求到来时获取新连接:

@Autowired
private JedisConnectionFactory redisConnectionFactory;
private StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
private RedisTemplate getNewConnection(){
        RedisTemplate redisTemplate = new RedisTemplate();
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        redisTemplate.setKeySerializer(stringRedisSerializer);
        redisTemplate.setHashKeySerializer(stringRedisSerializer);
        redisTemplate.setValueSerializer(stringRedisSerializer);
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }

编辑:我在 Redis 中对多/执行的 redisTemplate 的用法:

redisTemplate.setEnableTransactionSupport(true);

redisTemplate.multi();

for (ArrayList<Pair<String, String>> pairs : keys){
    for (Pair<String,String> pair: pairs)
        redisTemplate.opsForHash().get(makeMap(pair.getFirst(), version) , pair.getSecond());
}

return redisTemplate.exec();

我成功获得了 20 个请求的响应,但无法获得其余 10 个请求的响应。我面临的问题是前 20 个请求使用了 20 个连接后,其余 10 个请求无法从池中获取 jedis 连接,因此出现以下异常:

    2017-10-06 17:38:11.753 ERROR 3539 --- [io-8080-exec-12] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.data.redis.RedisConnectionFailureException: Cannot get Jedis connection; nested exception is redis.clients.jedis.exceptions.JedisException: Could not get a resource from the pool] with root cause

java.util.NoSuchElementException: Timeout waiting for idle object
    at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:449) ~[commons-pool2-2.4.2.jar:2.4.2]
    at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:363) ~[commons-pool2-2.4.2.jar:2.4.2]
    at redis.clients.util.Pool.getResource(Pool.java:49) ~[jedis-2.9.0.jar:na]
    at redis.clients.jedis.JedisPool.getResource(JedisPool.java:226) ~[jedis-2.9.0.jar:na]
    at redis.clients.jedis.JedisPool.getResource(JedisPool.java:16) ~[jedis-2.9.0.jar:na]
    at org.springframework.data.redis.connection.jedis.JedisConnectionFactory.fetchJedisConnector(JedisConnectionFactory.java:194) ~[spring-data-redis-1.8.6.RELEASE.jar:na]
    at org.springframework.data.redis.connection.jedis.JedisConnectionFactory.getConnection(JedisConnectionFactory.java:348) ~[spring-data-redis-1.8.6.RELEASE.jar:na]
    at org.springframework.data.redis.core.RedisConnectionUtils.doGetConnection(RedisConnectionUtils.java:129) ~[spring-data-redis-1.8.6.RELEASE.jar:na]
    at org.springframework.data.redis.core.RedisConnectionUtils.bindConnection(RedisConnectionUtils.java:67) ~[spring-data-redis-1.8.6.RELEASE.jar:na]
    at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:192) ~[spring-data-redis-1.8.6.RELEASE.jar:na]
    at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:169) ~[spring-data-redis-1.8.6.RELEASE.jar:na]
    at org.springframework.data.redis.core.RedisTemplate.multi(RedisTemplate.java:868) ~[spring-data-redis-1.8.6.RELEASE.jar:na]
    at net.media.mml.redis.repository.RedisRepository.makeTransaction(RedisRepository.java:50) ~[max-data-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
    at net.media.mml.redis.repository.RedisRepository.getFromRedis(RedisRepository.java:66) ~[max-data-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
    at net.media.mml.service.DimensionGetter.getDimensions(DimensionGetter.java:64) ~[ml-api.jar:0.0.1-SNAPSHOT]
    at net.media.mml.service.MLQueriesGetter.makeQueries(MLQueriesGetter.java:32) ~[ml-api.jar:0.0.1-SNAPSHOT]
    at net.media.mml.controller.MaxQueryController.query(MaxQueryController.java:61) ~[ml-api.jar:0.0.1-SNAPSHOT]
    at sun.reflect.GeneratedMethodAccessor270.invoke(Unknown Source) ~[na:na]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_131]
    at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_131]
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205) ~[spring-web-4.3.10.RELEASE.jar:4.3.10.RELEASE]

我已经在网上搜索但无法找到解决方案。有谁能够帮我?

【问题讨论】:

  • 请发布完整的堆栈跟踪,因为它可从您的应用程序中获得。
  • @mp911de,我已经编辑了完整的例外。
  • 我还在网上找到了这个配置:jedisPoolConfig.getBlockWhenExhausted();此参数默认为 true。但似乎 jedispoolconfig 在所有连接都在使用时实际上并没有阻止请求。
  • 有些东西不适合这里。您的 RedisTemplate 初始化代码未配置事务支持,但堆栈跟踪显示对 RedisConnectionUtils.bindConnection(…) 的调用,仅在启用事务时使用 (RedisTemplate.setEnableTransactionSupport(…))。
  • 嘿,当我调用在函数中使用 redistemplate 时,我启用了 RedisTemplate.setEnableTransactionSupport(…) 。我已经用代码更新了我对 redisTemplate 的使用。

标签: java spring jedis spring-data-redis


【解决方案1】:

使用 Redis 事务需要在回调中调用。 setEnableTransactionSupport(true) 供事务管理器/@Transactional 使用。有关详细信息,请参阅reference documentation

除非您有事务管理器,否则不要使用setEnableTransactionSupport(true)

你的代码应该是这样的:

List<Object> txResults = redisTemplate.execute(new SessionCallback<List<Object>>() {
  public List<Object> execute(RedisOperations operations) throws DataAccessException {
    operations.multi();
    operations.opsForSet().add("key", "value1");

    // This will contain the results of all ops in the transaction
    return operations.exec();
  }
});

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-06-08
    • 2016-05-06
    • 2017-09-15
    • 2012-10-14
    • 2014-03-30
    • 2015-03-02
    • 2021-01-11
    • 1970-01-01
    相关资源
    最近更新 更多