37

我正在运行多个工作线程(大约 10 个)来访问来自 redis Q 的数据。
因为我正在为Jedis Client使用无限超时。

Jedis jedis = pool.getResource();
jedis.getClient().setTimeoutInfinite();  

我仍然收到错误“无法从池中获取资源”。堆栈跟踪如下所示。

redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool
at redis.clients.util.Pool.getResource(Pool.java:22)
at Workers.Worker1.met1(Worker1.java:124)
at Workers.Worker1.work(Worker1.java:108)
at org.gearman.impl.worker.WorkerConnectionController$3.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)  

Caused by: redis.clients.jedis.exceptions.JedisConnectionException: java.net.SocketTimeoutException: connect timed out
at redis.clients.jedis.Connection.connect(Connection.java:124)
at redis.clients.jedis.BinaryClient.connect(BinaryClient.java:54)
at redis.clients.jedis.BinaryJedis.connect(BinaryJedis.java:1657)
at redis.clients.jedis.JedisPool$JedisFactory.makeObject(JedisPool.java:63)
at org.apache.commons.pool.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:1188)
at redis.clients.util.Pool.getResource(Pool.java:20)
... 6 more  

Caused by: java.net.SocketTimeoutException: connect timed out
at java.net.DualStackPlainSocketImpl.waitForConnect(Native Method)
at java.net.DualStackPlainSocketImpl.socketConnect(Unknown Source)
at java.net.AbstractPlainSocketImpl.doConnect(Unknown Source)
at java.net.AbstractPlainSocketImpl.connectToAddress(Unknown Source)
at java.net.AbstractPlainSocketImpl.connect(Unknown Source)
at java.net.PlainSocketImpl.connect(Unknown Source)
at java.net.SocksSocketImpl.connect(Unknown Source)
at java.net.Socket.connect(Unknown Source)
at redis.clients.jedis.Connection.connect(Connection.java:119)
... 11 more
4

9 回答 9

22

我注意到如果 Redis 没有运行,这个异常可以并且将会被抛出。只是一个抬头。

于 2013-07-17T21:31:57.767 回答
7

根据 Rick Hanlon 的回答,如果将 Redis 与 Spring Boot 一起使用,也会引发此异常。

如果你使用的是 Spring Boot,仅仅依赖 Redis 是不够的;您还需要从redis.io在您的机器上手动下载并安装 Redis ,然后从 Bash 终端运行它:

me@my_pc:/path/to/redis/dir$ ./src/redis-server ./redis.conf

运行服务器后,您需要在所有使用 Redis 的应用程序中添加相关行:

application.properties

...
spring.redis.host: <yourhost> // usually localhost, but can also be on a LAN
spring.redis.port: <yourport> // usually 6379, but settable in redis.conf

application.yml

...
spring:
  redis:
    host: <yourhost> // usually localhost, but can also be on a LAN
    port: <yourport> // usually 6379, but settable in redis.conf
于 2016-03-23T08:20:31.070 回答
7

是一直发生还是偶尔发生?如果是偶尔,您可能需要检查连接池的大小。

默认连接池大小(如果您使用JedisPoolConfig)为8。对于您的情况,这可能太小了。

JedisPoolConfig poolConfig = new JedisPoolConfig();
poolConfig.setMaxTotal(128);
jedisPool = new JedisPool(poolConfig, HOST, PORT, ...);
于 2017-03-01T23:41:47.293 回答
5

可能的原因;

1 - Redis 服务器已关闭或 Redis 应用程序没有响应。

2 - 应用程序无法连接到 Redis 服务器(防火墙等问题)。

3 - 连接到 Redis 服务器超时。

4 - (Redis) 池中的所有连接当前都忙,无法分配新连接。

案例 1 和案例 2 是相关的。

对于情况 3,必须增加连接超时(“RedisConnectionTimeout”):

pool = new pool(poolConfig, RedisIp, RedisPort, RedisConnectionTimeout);

对于情况 4,必须增加最大连接数(“RedisMaximumActiveConnectionCount”):

poolConfig.setMaxTotal(RedisMaximumActiveConnectionCount); 

假设以下或类似的实现;

private Pool<Jedis> pool =  null;   

private final String RedisIp="10.10.10.11";
private final int RedisPort=6379;
private final String RedisConnectionTimeout=2000;
private final String RedisMaximumWaitTime=1000;
private final String RedisMaximumIdleConnectionCount=20;
private final String RedisMaximumActiveConnectionCount=300;
private final String SentinelActive=false;
private final String SentinelHostList="10.10.10.10:26379,10.10.10.10:26380,10.10.10.10:26381";
private final String SentinelMasterName="sentinel-master-name";

private synchronized void initializePool()
{
    if(pool!=null) return;

    poolConfig poolConfig = new poolConfig();
    poolConfig.setMaxTotal(RedisMaximumActiveConnectionCount); 
    poolConfig.setMaxIdle(RedisMaximumIdleConnectionCount);  
    poolConfig.setMaxWaitMillis(RedisMaximumWaitTime); 

    if(SentinelActive)
    {
        String [] sentinelsArray = SentinelHostList.split(",");

        Set<String> sentinels = new HashSet<>();            
        for(String sentinel : sentinelsArray)
        {
            sentinels.add(sentinel);
        }

        String masterName = SentinelMasterName;

        pool = new JedisSentinelPool(masterName, sentinels, poolConfig, RedisConnectionTimeout);            
    }
    else
    {       
        pool = new pool(poolConfig, RedisIp, RedisPort, RedisConnectionTimeout);
    }

}           

protected Jedis getConnection()
{               
    if(pool==null)
        initializePool();

      Jedis jedis = pool.getResource();

      return jedis;     
}   
于 2019-01-23T13:33:56.337 回答
3

如果你的代码是这样的:

JedisPoolConfig jedisPoolConfig = initPoolConfig();    
jedisPool = new JedisPool(jedisPoolConfig, "*.*.*.*", 6379);  

你可以试试这个:

JedisPoolConfig jedisPoolConfig = initPoolConfig();    
jedisPool = new JedisPool(jedisPoolConfig, "*.*.*.*", 6379,10*1000); 

这是因为对于 Redis,默认的超时时间是 2 秒,但程序可能在这个时间内已经运行完毕。

于 2015-03-27T10:36:47.267 回答
1

不确定,但也许你没有将 Jedis 对象返回到池中,并且你的 redis-server 有连接限制。

每个工作线程都应该在其工作完成后将 Jedis 实例返回到池中:

Jedis jedis = jedisPool.getResource();
try {
    jedis.getClient().setTimeoutInfinite();
    // your code here...
    ...
} finally {
    jedisPool.returnResource(jedis);
}
于 2012-10-25T20:53:56.417 回答
0

当 jedis 根本无法访问所需的 redis 实例(域/IP、端口或密码)时,我遇到了该错误,如果它们是错误的,或者它们之前是正确的,现在是错误的,或者如果它们是对,但是防火墙阻止了对它们的访问,等等。

我知道 OP 已确认已运行 redis-cli 来确认连接,但如果确认这是从 jedis 呼叫来自的同一个地方完成的(这可能是一个应用服务器利用 jedis 连接到一些redis服务器)。

但是那个原始帖子是 2012 年的,所以我不希望听到更新,但我把这些留给可能找到这个帖子的其他人。

于 2020-10-27T22:08:54.090 回答
0

我只想在@mrt 和@charlie 的回答中加一点。我们需要检查redis服务器的属性。对于 redis 客户端 3.2.0 及以上版本,我们也可以设置 ssl 属性,在 JedisShardInfo 的帮助下,如下所示:

JedisShardInfo shardInfo = new JedisShardInfo(redisServer, redisServerPort, redisTimeout, redisSsl);
shardInfo.setPassword(redisPassword);
Jedis jedis = new Jedis(shardInfo);

并使用 jedisPool:

jedisPool = new JedisPool(poolConfig, redisServer, redisServerPort, redisTimeout, redisPassword, redisSsl);
jedis = jedisPool.getResource();

其中,在 中poolConfig,您可以指定各种属性,如、setMaxIdle等。setMaxWaitMillissetMaxTotal

于 2022-02-22T06:00:19.833 回答
0

我不得不努力解决“无法从池中获取资源”错误,但我终于解决了它,希望它也能解决你的问题!

将“application.properties”中的端口从“6380”更改为“6379”它应该可以正常工作!

于 2021-11-22T15:08:43.063 回答