5分ごとにバッチジョブを実行していて、他のノードで同じジョブを実行したくないので、Jedisロックを使用して5分間オブジェクトをロックしています。そのため、他のノードが同じジョブを実行しようとしても、ロックは取得されません。ロックを取得した後にジョブが開始し、Redisからそれを読み込もうとすると、次の例外が表示されます。
'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)'
これは私が持っているコードです
@Bean
public Jedis getJedis()
{
Jedis jedis = new Jedis(this.redisHost, nteger.valueOf(this.redisPort));
jedis.auth(this.redisPassword);
return jedis;
}
spring-boot Application.propertiesファイル
# 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
ジョブは最初に次のコードを実行してロックを取得します
JedisLock jedisLock = new JedisLock(jedis, getLockName(), getTimeInMillis());
jedisLoc.acquire()
その後、redisリポジトリクラスは特定のパターンの値を読み取ろうとしています。
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;
次に、これは私がログに表示する完全な例外です。
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
この例外が発生する理由と修正方法は誰でも知っていますか?
変化する bind 127.0.0.1
からbind {replace with machine ip}
in your redis。{os} .conf file of Redis
1. new Jedis()
を使用する代わりに、Jedis接続プールを使用してJedisインスタンスを取得しようとします。そのため、構成でJedisPoolを構成する必要があります。Beanとして使用しているため、JedisPool Beanを使用してから、Jedisを取得する必要があります。そこから、操作を実行するはずの場所に移動し、終了後に操作を閉じます。
2.さもなければ、以下のようにconfigでSpringのredisTemplateを使用します
@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;
}
Spring管理のredis接続プールからJedisインスタンスを取得します。
Jedis jedis = (Jedis) redisTemplate.getConnectionFactory().getConnection().getNativeConnection();
次に、それを使用してJedisLockをインスタンス化できます。