当前位置: 首页 > 知识库问答 >
问题:

无法从池JedisConnectionException获取资源

倪棋
2023-03-14

大家好,我正在尝试使用Java建立redis服务器。我的Redis服务器是linux服务器,ulimit无限。

这里是创建连接的spring bean

公共类JedisService实现IJedisService,InitializingBean,DisposableBean{private JedisPool JedisPool;

public JedisService() {

}

public JedisPool getJedisPool() {
    return jedisPool;
}

@Override
public void destroy() throws Exception {
    if(jedisPool != null){
        jedisPool.destroy();
    }

}

@Override
public void afterPropertiesSet() throws Exception {
    JedisPoolConfig poolConfig = new JedisPoolConfig();
    poolConfig.setMaxActive(1000);
    poolConfig.setMaxIdle(10);
    poolConfig.setMinIdle(1);
    poolConfig.setMaxWait(30000);
    poolConfig.setNumTestsPerEvictionRun(10);
    poolConfig.setTestOnBorrow(true);
    poolConfig.setTestOnReturn(true);
    poolConfig.setTestWhileIdle(true);
    poolConfig.setTimeBetweenEvictionRunsMillis(30000);

    jedisPool = new JedisPool(poolConfig,Config.REDIS_HOST,
            RestrictionUtils.REDIS_PORT,RestrictionUtils.REDIS_CONNECTION_TIMEOUT);

}

public boolean validateHitsCount(String hostKey,String urlKey,int hostHitsCount, int urlHitsCount, long timeKey,Map<String, Object> overLimit){
    int retryCount = 0;
    return recursiveRedisConnection(retryCount,hostKey,urlKey,hostHitsCount,urlHitsCount,timeKey,overLimit);
}

private boolean recursiveRedisConnection(int retryCount,String hostKey,String urlKey,int hostHitsCount, int urlHitsCount, long timeKey,Map<String, Object> overLimit){
    Jedis jedis = null;
    boolean returnObj = true;
    try {
        //Connection
        jedis = getJedisPool().getResource();
        jedis.connect();

        //Delete previous keys
        try {
            deletePreviouskeys(jedis, urlKey, hostKey, timeKey);
        } catch (Exception e) {
        }

        //Validation
        String value = jedis.get(hostKey+timeKey);
        if(value != null){
            try {
                int count = Integer.parseInt(value);
                System.out.println("HostCount: "+hostKey+ "    "+count);
                if(count < hostHitsCount){
                    jedis.incr(hostKey+timeKey);
                    returnObj = validateURLHits(jedis, urlKey, urlHitsCount, timeKey, overLimit);
                }else{
                    returnObj = false;
                    overLimit.put("Data", "You have reached maximum limit for hits---"+hostKey);
                }
            } catch (Exception e) {
            }

        }else{
            value = 1+"";
            jedis.set(hostKey+timeKey, value);
            jedis.expire(hostKey+timeKey, 60);
            returnObj = validateURLHits(jedis, urlKey, urlHitsCount, timeKey, overLimit);
        }

    } catch (Exception e) {
        retryCount ++;
        if(retryCount < 3){
            recursiveRedisConnection(retryCount,hostKey,urlKey,hostHitsCount,urlHitsCount,timeKey,overLimit);
        }else{
            e.printStackTrace();
            returnObj = false;
        }
    }finally{
        if(jedis != null && jedis.isConnected()){
            getJedisPool().returnResource(jedis);
        }
    }
    return returnObj;
}

private boolean validateURLHits(Jedis jedis,String urlKey, int urlHitsCount, long timeKey,Map<String, Object> overLimit){
    boolean returnObj = true;
    String value = jedis.get(urlKey+timeKey);
    if(value != null){
        try {
            int count = Integer.parseInt(value);
            System.out.println("URLCount: "+urlKey+ "    "+count);
            if(count < urlHitsCount){
                jedis.incr(urlKey+timeKey);
            }else{
                returnObj = false;
                overLimit.put("Data", "Reached maximum limit of hits for this URL");
            }
        }catch(Exception e){
        }
    }else{
        jedis.set(urlKey+timeKey, 1+"");
        jedis.expire(urlKey+timeKey, 60);
    }
    return returnObj;
}

private void deletePreviouskeys(Jedis jedis,String urlKey, String hostKey, long timeKey){
    /*Set<String> keys = jedis.keys("*");
    for(String key :  keys){
        if(!key.equalsIgnoreCase(urlKey+timeKey)){
            if(!key.equalsIgnoreCase(hostKey+timeKey)){
                jedis.del(key);
            }
        }

    }*/
}

共有1个答案

杜辰龙
2023-03-14

您是否检查了JedisPool仅实例化一次而不是更多次?

由于Spring bean是通过许多线程访问的,并且Jedis不是线程安全的,因此可能有多个JedisPool返回奇怪的Jedis实例,或者不同线程同时使用的Jedis实例。每个线程都可以拥有这个JedisPool和/或Jedis实例的本地副本,然后从中获取错误。

您有两个选项:您可以声明JedisPool为static final(每个类加载器只有一个值),或者使用双重检查锁定(使用volatile)来确保所有线程只有一个JedisPool可访问,而不需要本地复制,因为线程使用的每个Jedi不会被另一个线程访问。

 类似资料:
  • 我正在尝试来自Jedis(Redis for Java)的“基本用法示例”https://github.com/xetorthio/jedis/wiki/Getting-started但我得到了以下错误: 我正在用Jedis-2.4.2,Commons-pool2-2.0在OSX 10.9.2上尝试这个

  • 我正在尝试从一个运行在Windows10上的Java应用程序使用Jedis客户端连接到一个远程Redis实例。我的程序以异常JeDisConnectionException失败。 环境 null null 还有其他人碰到这个吗? 感谢您的任何帮助。-)

  • Redis.Properties spring-redis.xml 代码 控制器

  • 我正在运行多个工作线程(大约10个)来访问redis Q的数据。 我正在使用infinte timeout For Jedis客户端。 但我仍然收到错误“无法从池中获取资源”。stacktrace如下所示。

  • 问题内容: 我已经在几个线程中看到了答案,但对我却没有解决,而且由于我的问题偶尔发生,因此问这个问题是否有人有任何想法。 我正在使用jedis版本2.8.0,Spring Data Redis版本1.7.5。和redis服务器版本2.8.4用于我们的缓存应用程序。 我有多个缓存保存在redis中,并且从redis获得请求。我正在使用spring数据redis API保存和获取数据。 所有保存和获取

  • 我每5分钟运行一次批处理作业,我不希望其他节点运行同一个作业,因此我使用绝地锁将一个对象锁定5分钟。这样,如果另一个节点试图运行同一个作业,它们就不会得到锁。工作是在获得锁后开始的,当我试图从Redis读取它时,我得到以下异常情况: 这是我的密码 spring启动应用程序。属性文件 作业在开始时执行以下代码以获得锁 之后,redis仓库类试图读取特定模式的值... 这就是我在日志中看到的完全例外。