Java Jedis:无法从池中获取资源

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/23233673/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 21:26:50  来源:igfitidea点击:

Jedis : Could not get a resource from the pool

javaredisjedisnosql

提问by WoooHaaaa

Background

背景

Our application uses Jedis-2.2.1and connects to Redis-2.6, here's how I get jedis resource :

我们的应用程序使用Jedis-2.2.1并连接到Redis-2.6,这是我获取 jedis 资源的方式:

protected static JedisWrapper getRedisUserWrite(String UDID) {
        if (redisUserWritePools.get(0) == null) init();

        int hash = hash(UDID);
        Jedis jedis = redisUserWritePools.get(hash).getResource();
        jedis.select(dbs.get("redisUserWritePools" + hash));

        return new JedisWrapper(jedis, redisUserWritePools.get(hash));
    }

And this is my JedisWrapper(Unify the management of resources):

这是我的JedisWrapper(统一资源管理):

public class JedisWrapper {
    private Jedis jedis;
    private JedisPool pool;

    public JedisWrapper(Jedis jedis, JedisPool pool) {
        this.jedis = jedis;
        this.pool = pool;
    }

    public Jedis get(){
        return this.jedis;
    }

    public void returnResource() {
        if(null != this.jedis){
            this.pool.returnResource(this.jedis);
        }
    }

    public void returnBrokenResource() {
        if(null != this.jedis) {
            this.pool.returnBrokenResource(this.jedis);
        }
        this.jedis = null;
    }
}

JedisWrapperis the container if Jedis instance, here's how I use it :

JedisWrapper是容器如果 Jedis 实例,这是我如何使用它:

private static void cacheSDKIDs(String UDID, String[] SDKIDs) {

        JedisWrapper wrapper = getRedisUserWrite(UDID);
        try {
            if (SDKIDs != null) {
                wrapper.get().del(UDID);
                wrapper.get().sadd(UDID, SDKIDs);
            }
        } catch (JedisConnectionException e) {
            e.printStackTrace();
            wrapper.returnBrokenResource();
        }catch (Exception e) {
            e.printStackTrace();
        } finally {
            wrapper.returnResource();
        }
    }

Note that, SKDIDsmaybe very large(e.g. could reach the maximum of 8KB).

请注意,SKDIDs可能非常大(例如可能达到 8KB 的最大值)。

Here's the problem

问题来了

Every time I restart our application, all redis connections are normal, but several hours later, the Could not get a resource from the poolException comes out. And frequency become higher and higher, then all the connections to Redis are disconnected and can create new connection.

每次重启我们的应用程序,所有redis连接都正常,但是几个小时后,Could not get a resource from the pool异常就出来了。并且频率越来越高,然后所有到Redis的连接都断开了,可以创建新的连接。

Here's my configuration :

这是我的配置:

<bean id = "redisConfig" class="redis.clients.jedis.JedisPoolConfig">
    <property name="maxActive"  value="400" />
    <property name="maxIdle" value="100" />
    <property name="minIdle" value="20" />
    <property name="maxWait" value="4000" />
    <property name="testOnBorrow"  value="true"/>
    <property name="testOnReturn" value="true" />
  </bean>

Exception Stacktrace:

异常堆栈跟踪:

Caused by: redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool
    at redis.clients.util.Pool.getResource(Pool.java:40)
    at com.xxxice.redis.BaseRedis.getRedisUserWrite(BaseRedis.java:158)
    at com.xxx.service.redis.DeviceRedis.cacheSDKIds(DeviceRedis.java:128)
    at com.xxx.redis.DeviceRedis.cacheDevice(DeviceRedis.java:65)
    at com.xxx.service.DeviceService.update(DeviceService.java:88)
    at com.xxx.controller.Devices.update(Devices.java:25)
    ... 32 more
Caused by: java.util.NoSuchElementException: Timeout waiting for idle object
    at org.apache.commons.pool.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:1174)
    at redis.clients.util.Pool.getResource(Pool.java:38)
    ... 37 more

回答by Remya

In your JedisWrapper, the Jedis is created as a class variable which gets instantiated once. Please declare it inside the methods getJedis, then the problem will be solved

在您的 JedisWrapper 中,Jedis 被创建为一个实例化一次的类变量。请在getJedis方法里面声明一下,问题就解决了

回答by samith kumarasingha

check whether you have permission to access redis through code

检查是否有权限通过代码访问redis