无法获取Jedis连接;无法从池中获取资源

6

我每隔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应用程序属性文件

# 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

有人知道我为什么会得到这个异常并如何修复它吗?


可能是[SocketTimeoutException: Read time out]的重复问题。(链接:https://dev59.com/u4Tca4cB1Zd3GeqPA-ox) - mp911de
不,我的问题不同,因为我使用的库不同。 - gcpdev-guy
4个回答

3

1. 尝试使用Jedis连接池获取Jedis实例,而不是使用new Jedis()。为此,您需要在配置中配置JedisPool。由于您将其用作bean,因此应该使用JedisPool bean,然后在执行操作的任何地方获取Jedis,并在完成后关闭它。

2. 或者使用以下配置的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;
}

请问您能否指导一下这个问题:https://stackoverflow.com/questions/51408969/nested-exception-is-redis-clients-jedis-exceptions-jedisconnectionexception-cou? - Jeff Cook

1

在Redis的redis.{os}.conf文件中,将bind 127.0.0.1更改为bind {替换为机器IP}


1
从Spring管理的Redis连接池中获取Jedis实例:
Jedis jedis = (Jedis) redisTemplate.getConnectionFactory().getConnection().getNativeConnection();

然后您可以使用它来实例化JedisLock。

0

在创建Jedis池时,如果传递的密码为空,请传递null而不是空引号。例如:""

return new JedisPool(new JedisPoolConfig(), redisHost, redisPort, 600000, StringUtils.isEmpty(redisPassword) ? null : redisPassword);


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接