2014-02-27 55 views
0

嗨,我想要设置使用java的redis服务器。 我的Redis服务器是带有ulimit无限制的linux服务器。无法从池中获取资源JedisConnectionException

这里是我的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:从池中 在redis.clients.util.Pool.getResource无法获得的资源(池。 java:22) at com.til.ibeat.service.JedisService.recursiveRedisConnection(JedisService.java:60) at com.til.ibeat.service.JedisService.recursiveRedisConnection(JedisService.java:95) at com.til。 ibeat.service.JedisService.recursiveRedisConnection(JedisService.java:95) at com.til.ibeat.service.JedisService.validateHitsCount(JedisService.java:52) at com.til.ibeat.controller.MashupController.handleRequest(MashupController。 java:66) at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:48) at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:763) at org.springframework.web。 servlet.DispatcherServlet.doService(DispatcherServlet.java:709) at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:613) at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java: 525) at javax.servlet.http.HttpServlet.service(HttpServlet.java:621) at javax.servlet.http.HttpServlet.service(HttpServlet.java:728) at org.apache.catalina.core.ApplicationFilterChain。 internalDoFilter(ApplicationFilterChain.java:305) at 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。 (org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171) at 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) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.j ava:407) at 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源) 在java.lang.Thread.run(未知源) 引起:java.util。NoSuchElementException:无法创建经过验证的对象,原因:ValidateObject失败

回答

1

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

由于您的Spring bean通过多线程访问,并且Jedis不是线程安全的,因此您可以有多个JedisPool返回奇怪的Jedis实例或不同线程同时使用的jedis实例。每个线程都可以拥有JedisPool和/或Jedis实例的本地副本,然后从中获取错误。你有两种选择:你可以声明JedisPool为静态final(每个类加载器只有一个值),或者使用双重检查加锁(使用volatile)来确保只有一个JedisPool在没有本地拷贝的情况下被所有线程访问,根据线程使用的每个Jed都不会被另一个线程访问。