大家好我正在尝试使用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失败
答案 0 :(得分:1)
您是否检查过您的JedisPool只是一次而不是更多?
由于您的Spring bean是通过许多线程访问的,并且Jedis不是线程安全的,因此您可能有多个JedisPool返回奇怪的Jedis实例,或者同时由不同线程使用的jedis实例。每个线程都可以拥有此JedisPool和/或Jedis实例的本地副本,然后从中获取错误。
您有两个选择:您可以将JedisPool声明为静态final(每个类加载器只有一个值)或使用双重检查锁定(使用volatile)以确保所有线程只访问一个没有本地副本的JedisPool,一个线程使用的每个Jedis都不会被另一个线程访问。