J'exécute un travail par lots toutes les 5 minutes et je ne veux pas que les autres nœuds exécutent le même travail, c'est pourquoi j'utilise le verrou Jedis pour verrouiller un objet pendant 5 minutes. Ainsi, cet autre nœud ne sera pas verrouillé s'il essaie d'exécuter le même travail. Le travail a commencé après l'acquisition du verrou et lorsque j'essaie de le lire à partir de Redis, je reçois l'exception suivante en disant
'Caused by: redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool
at redis.clients.util.Pool.getResource(Pool.Java:53)
at redis.clients.jedis.JedisPool.getResource(JedisPool.Java:226)
at redis.clients.jedis.JedisPool.getResource(JedisPool.Java:16)
at org.springframework.data.redis.connection.jedis.JedisConnectionFactory.fetchJedisConnector(JedisConnectionFactory.Java:194)
... 40 more
Caused by: redis.clients.jedis.exceptions.JedisConnectionException: Java.net.SocketTimeoutException: Read timed out
at redis.clients.jedis.Connection.disconnect(Connection.Java:224)
at redis.clients.jedis.BinaryClient.disconnect(BinaryClient.Java:941)
at redis.clients.jedis.Connection.close(Connection.Java:214)
at redis.clients.jedis.BinaryClient.close(BinaryClient.Java:947)
at redis.clients.jedis.Jedis.close(Jedis.Java:3412)
at redis.clients.jedis.JedisFactory.makeObject(JedisFactory.Java:117)
at org.Apache.commons.pool2.impl.GenericObjectPool.create(GenericObjectPool.Java:836)
at org.Apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.Java:434)
at org.Apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.Java:361)
at redis.clients.util.Pool.getResource(Pool.Java:49)'
C'est ce que le code que j'ai
@Bean
public Jedis getJedis()
{
Jedis jedis = new Jedis(this.redisHost, nteger.valueOf(this.redisPort));
jedis.auth(this.redisPassword);
return jedis;
}
fichier Application.properties de spring-boot
# DATA REDIS
spring.data.redis.repositories.enabled=true
# REDIS (RedisProperties)
spring.redis.Host=10.160.49.22
spring.redis.password=qweqewqw
spring.redis.ssl=true
#spring.redis.pool.max-active=10
#spring.redis.pool.max-idle=10
# spring.redis.pool.max-wait=30000
spring.redis.port=6379
Le travail exécute le code suivant au début pour obtenir le verrou
JedisLock jedisLock = new JedisLock(jedis, getLockName(), getTimeInMillis());
jedisLoc.acquire()
Après cela, la classe de référentiel redis tente de lire les valeurs d'un modèle particulier.
List<String> hotelCodes = redisTemplate.execute(new RedisCallback<List<String>>() {
/**
* Gets called by {@link RedisTemplate} with an active Redis connection. Does not need to care about activating or
* closing the connection or handling exceptions.
*
* @param connection active Redis connection
* @return a result object or {@code null} if none
* @throws DataAccessException
*/
@Override
public List<String> doInRedis(RedisConnection connection) throws DataAccessException {
ScanOptions options = ScanOptions.scanOptions().match(pattern).count(1).build();
Cursor<Map.Entry<byte[], byte[]>> entries = connection.hScan(HASH_KEY.getBytes(), options);
List<String> result = new ArrayList<>();
if (entries != null)
while (entries.hasNext()) {
Map.Entry<byte[], byte[]> entry = entries.next();
byte[] actualValue = entry.getValue();
result.add(new String(actualValue));
}
return result;
}
});
return hotelCodes;
Ensuite, c’est l’exception complète que je vois dans le journal.
org.springframework.data.redis.RedisConnectionFailureException: Cannot get Jedis connection; nested exception is redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool
at org.springframework.data.redis.connection.jedis.JedisConnectionFactory.fetchJedisConnector(JedisConnectionFactory.Java:204)
at org.springframework.data.redis.connection.jedis.JedisConnectionFactory.getConnection(JedisConnectionFactory.Java:348)
at org.springframework.data.redis.core.RedisConnectionUtils.doGetConnection(RedisConnectionUtils.Java:129)
at org.springframework.data.redis.core.RedisConnectionUtils.getConnection(RedisConnectionUtils.Java:92)
at org.springframework.data.redis.core.RedisConnectionUtils.getConnection(RedisConnectionUtils.Java:79)
at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.Java:194)
at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.Java:169)
at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.Java:157)
at com.hyatt.pms.jobs.dao.impl.HeartbeatRepositoryImpl.findAll(HeartbeatRepositoryImpl.Java:62)
at com.hyatt.pms.jobs.dao.impl.HeartbeatRepositoryImpl$$FastClassBySpringCGLIB$$e3fe6169.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.Java:204)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.Java:738)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.Java:157)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.Java:136)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.Java:179)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.Java:673)
at com.hyatt.pms.jobs.dao.impl.HeartbeatRepositoryImpl$$EnhancerBySpringCGLIB$$68719252.findAll(<generated>)
at com.hyatt.pms.jobs.processors.HeartbeatTestProcessor.processCluster(HeartbeatTestProcessor.Java:54)
at com.hyatt.pms.jobs.processors.TestProcessor.process(TestProcessor.Java:61)
at com.hyatt.pms.jobs.processors.HeartbeatTestProcessor.process(HeartbeatTestProcessor.Java:39)
at com.hyatt.pms.jobs.processors.HeartbeatTestProcessor$$FastClassBySpringCGLIB$$99fdfbdc.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.Java:204)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.Java:669)
at com.hyatt.pms.jobs.processors.HeartbeatTestProcessor$$EnhancerBySpringCGLIB$$860eb7e4.process(<generated>)
at com.hyatt.pms.jobs.domain.jobs.HeartbeatJob.runHealthCheck(HeartbeatJob.Java:34)
at Sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at Sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.Java:62)
at Sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.Java:43)
at Java.lang.reflect.Method.invoke(Method.Java:498)
at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.Java:65)
at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.Java:54)
at org.springframework.scheduling.concurrent.ReschedulingRunnable.run(ReschedulingRunnable.Java:81)
at Java.util.concurrent.Executors$RunnableAdapter.call$$$capture(Executors.Java:511)
at Java.util.concurrent.Executors$RunnableAdapter.call(Executors.Java)
at Java.util.concurrent.FutureTask.run$$$capture(FutureTask.Java:266)
at Java.util.concurrent.FutureTask.run(FutureTask.Java)
at Java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.Java:180)
at Java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.Java:293)
at Java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.Java:1149)
at Java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.Java:624)
at Java.lang.Thread.run(Thread.Java:748)
Caused by: redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool
at redis.clients.util.Pool.getResource(Pool.Java:53)
at redis.clients.jedis.JedisPool.getResource(JedisPool.Java:226)
at redis.clients.jedis.JedisPool.getResource(JedisPool.Java:16)
at org.springframework.data.redis.connection.jedis.JedisConnectionFactory.fetchJedisConnector(JedisConnectionFactory.Java:194)
... 40 more
Caused by: redis.clients.jedis.exceptions.JedisConnectionException: Java.net.SocketTimeoutException: Read timed out
at redis.clients.jedis.Connection.disconnect(Connection.Java:224)
at redis.clients.jedis.BinaryClient.disconnect(BinaryClient.Java:941)
at redis.clients.jedis.Connection.close(Connection.Java:214)
at redis.clients.jedis.BinaryClient.close(BinaryClient.Java:947)
at redis.clients.jedis.Jedis.close(Jedis.Java:3412)
at redis.clients.jedis.JedisFactory.makeObject(JedisFactory.Java:117)
at org.Apache.commons.pool2.impl.GenericObjectPool.create(GenericObjectPool.Java:836)
at org.Apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.Java:434)
at org.Apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.Java:361)
at redis.clients.util.Pool.getResource(Pool.Java:49)
... 43 more
Caused by: Java.net.SocketTimeoutException: Read timed out
at Java.net.SocketInputStream.socketRead0(Native Method)
at Java.net.SocketInputStream.socketRead(SocketInputStream.Java:116)
at Java.net.SocketInputStream.read(SocketInputStream.Java:171)
at Java.net.SocketInputStream.read(SocketInputStream.Java:141)
at Sun.security.ssl.InputRecord.readFully(InputRecord.Java:465)
at Sun.security.ssl.InputRecord.read(InputRecord.Java:503)
at Sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.Java:983)
at Sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.Java:1385)
at Sun.security.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.Java:757)
at Sun.security.ssl.AppOutputStream.write(AppOutputStream.Java:123)
at redis.clients.util.RedisOutputStream.flushBuffer(RedisOutputStream.Java:52)
at redis.clients.util.RedisOutputStream.flush(RedisOutputStream.Java:216)
at redis.clients.jedis.Connection.disconnect(Connection.Java:220)
... 52 more
Quelqu'un sait pourquoi j'obtiens cette exception et comment y remédier?
1. Essayez d’utiliser le pool de connexions Jedis pour obtenir l’instance Jedis au lieu d’utiliser new Jedis()
; pour cela, vous devrez configurer JedisPool dans config Étant donné que vous l’utilisez comme bean, vous devez utiliser le bean JedisPool, puis obtenir Jedis de où que vous soyez censé effectuer une opération et la fermer après avoir terminé.
2. Sinon, utilisez redisTemplate de spring avec la configuration ci-dessous
@Bean
public JedisConnectionFactory redisConnectionFactory() {
JedisConnectionFactory factory = new JedisConnectionFactory();
factory.setHostName(redisHostName);
factory.setPort(redisPort);
factory.setUsePool(true);
return factory;
}
@Bean
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory cf) {
RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<Object, Object>();
redisTemplate.setDefaultSerializer(new StringRedisSerializer());
redisTemplate.setConnectionFactory(cf);
return redisTemplate;
}
Récupérez l'instance Jedis à partir du pool de connexions Redis géré par le ressort:
Jedis jedis = (Jedis) redisTemplate.getConnectionFactory().getConnection().getNativeConnection();
Ensuite, vous pouvez l’utiliser pour instancier JedisLock.