无法从池JedisConnectionException获取资源

时间:2014-02-27 05:12:19

标签: java redis jedis

大家好我正在尝试使用java设置redis服务器。 我的Redis服务器是linux服务器,ulimit无限制。

这是我的spring bean创建连接

公共类JedisService实现IJedisService,InitializingBean,DisposableBean {     私人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);
            }
        }

    }*/
}

}

在控制器中调用validateURLHits方法。 但是当我在多个线程中运行此代码时,我收到此错误

redis.clients.jedis.exceptions.JedisConnectionException:无法从池中获取资源     at redis.clients.util.Pool.getResource(Pool.java:22)     在com.til.ibeat.service.JedisService.recursiveRedisConnection(JedisService.java:60)     在com.til.ibeat.service.JedisService.recursiveRedisConnection(JedisService.java:95)     在com.til.ibeat.service.JedisService.recursiveRedisConnection(JedisService.java:95)     在com.til.ibeat.service.JedisService.validateHitsCount(JedisService.java:52)     在com.til.ibeat.controller.MashupController.handleRequest(MashupController.java:66)     在org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:48)     在org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:763)     在org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:709)     在org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:613)     在org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:525)     在javax.servlet.http.HttpServlet.service(HttpServlet.java:621)     在javax.servlet.http.HttpServlet.service(HttpServlet.java:728)     在org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)     在org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)     在org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)     在org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)     在org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)     at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)     在org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)     在org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:936)     在org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)     在org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)     在org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1004)     at org.apache.coyote.AbstractProtocol $ AbstractConnectionHandler.process(AbstractProtocol.java:589)     at org.apache.tomcat.util.net.JIoEndpoint $ SocketProcessor.run(JIoEndpoint.java:310)     at java.util.concurrent.ThreadPoolExecutor $ Worker.runTask(Unknown Source)     at java.util.concurrent.ThreadPoolExecutor $ Worker.run(Unknown Source)     在java.lang.Thread.run(未知来源) 引起:java.util.NoSuchElementException:无法创建经过验证的对象,原因:ValidateObject失败

1 个答案:

答案 0 :(得分:1)

您是否检查过您的JedisPool只是一次而不是更多?

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

您有两个选择:您可以将JedisPool声明为静态final(每个类加载器只有一个值)或使用双重检查锁定(使用volatile)以确保所有线程只访问一个没有本地副本的JedisPool,一个线程使用的每个Jedis都不会被另一个线程访问。