在项目中遇到一个问题:当SpringBoot连接Redis时,长时间不使用会报错,提示Redis命令超时
Caused by: io.lettuce.core.RedisCommandTimeoutException: Command timed out after 10 second(s)
at io.lettuce.core.internal.ExceptionFactory.createTimeoutException(ExceptionFactory.java:59)
at io.lettuce.core.internal.Futures.awaitOrCancel(Futures.java:246)
at io.lettuce.core.LettuceFutures.awaitOrCancel(LettuceFutures.java:74)
at org.springframework.data.redis.connection.lettuce.LettuceConnection.await(LettuceConnection.java:1083)
这表示Redis命令在指定时间内没有返回,通常可能是由于网络中断、空闲连接断开等原因导致的。
问题分析
主要是因为Redis连接长时间处于空闲状态后被断开,导致下一次访问时发生超时错误。
解决方案
1. 定时任务
使用了Spring的@Scheduled
注解来定期执行一个Redis的PING
命令,以检测并保持连接的活跃。
2. 控制心跳检测的启用
为了使这个心跳检测更加灵活,配置文件中自定义了一个配置用来控制是否开启
spring.redis.keep-alive=true
通过@ConditionalOnProperty
注解控制心跳检测任务的启用。
代码实现
@EnableScheduling
@Component
@ConditionalOnProperty(name = "spring.redis.keep-alive", havingValue = "true")
public class RedisHealthCheck {
@Resource
private StringRedisTemplate springbRedisTemplate;
// 每分钟执行一次
@Scheduled(fixedRate = 60000)
public void keepAlive() {
try {
// 执行Redis PING命令,检测连接是否活跃
String result = Objects.requireNonNull(springbRedisTemplate.getConnectionFactory()).getConnection().ping();
System.out.println("Redis PING Response: " + result);
} catch (Exception e) {
// 处理Redis连接异常
System.err.println("Redis heartbeat failed: " + e.getMessage());
}
}
}
总结
通过这种方式,问题得到了彻底解决。使用定时任务向Redis发送PING
命令,确保了长时间不使用Redis的情况下,连接不会断开。