Redis服务器宕机时Spring Boot应用启动失败,如何正常运行?
当本地Redis服务器正常时,应用运行无异常,但Redis宕机时启动失败,抛出连接拒绝异常。以下是配置类代码片段:
@Configuration @EnableCaching public class RedisCacheConfig extends CachingConfigurerSupport { @Bean public LettuceConnectionFactory redisConnectionFactory() { return new LettuceConnectionFactory(new RedisStandaloneConfiguration(), LettuceClientConfiguration.builder() .commandTimeout(Duration.ofMillis(1000)) .build()); } @Bean public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory) { RedisTemplate<Object, Object> template = new RedisTemplate<>(); template.setConnectionFactory(connectionFactory); return template; } //Cache manager configurations follow here... }
抛出的异常信息:
org.springframework.data.redis.RedisConnectionFailureException: Unable to connect to Redis; nested exception is io.lettuce.core.RedisConnectionException: Unable to connect to localhost:6379
at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory$ExceptionTranslatingConnectionProvider.translateException(LettuceConnectionFactory.java:1689)
at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory$ExceptionTranslatingConnectionProvider.getConnection(LettuceConnectionFactory.java:1597)
...
14 common frames omitted
Caused by: io.netty.channel.AbstractChannel$AnnotatedConnectException: Connection refused: no further information: localhost/127.0.0.1:6379
Caused by: java.net.ConnectException: Connection refused: no further information
at java.base/sun.nio.ch.SocketChannelImpl.checkConnect(Native Method)
at java.base/sun.nio.ch.SocketChannelImpl.finishConnect(SocketChannelImpl.java:777)
需求:Redis宕机时应用能继续运行,等价于未启用缓存的状态。
1. 禁用启动时的Redis连接校验
默认Lettuce连接工厂会在启动时强制校验Redis连接,这是启动失败的核心原因。修改配置关闭该校验:
@Bean public LettuceConnectionFactory redisConnectionFactory() { LettuceClientConfiguration clientConfig = LettuceClientConfiguration.builder() .commandTimeout(Duration.ofMillis(1000)) .validateConnection(false) // 关键:关闭启动阶段的连接校验 .build(); return new LettuceConnectionFactory(new RedisStandaloneConfiguration(), clientConfig); }
2. 自定义缓存异常处理器
关闭启动校验后,实际执行缓存操作时仍会抛出连接异常,需通过CacheErrorHandler捕获异常并忽略,让业务逻辑正常执行:
@Override public CacheErrorHandler errorHandler() { return new CacheErrorHandler() { @Override public void handleCacheGetError(RuntimeException exception, Cache cache, Object key) { if (exception instanceof RedisConnectionFailureException) { return; // 忽略Redis连接异常,直接走业务逻辑 } throw exception; } @Override public void handleCachePutError(RuntimeException exception, Cache cache, Object key, Object value) { if (exception instanceof RedisConnectionFailureException) { return; } throw exception; } @Override public void handleCacheEvictError(RuntimeException exception, Cache cache, Object key) { if (exception instanceof RedisConnectionFailureException) { return; } throw exception; } @Override public void handleCacheClearError(RuntimeException exception, Cache cache) { if (exception instanceof RedisConnectionFailureException) { return; } throw exception; } }; }
3. 优化缓存管理器配置(可选)
结合RedisCacheManager的配置,确保缓存操作的序列化和默认行为符合预期,配合异常处理器实现无缝降级:
@Bean public CacheManager cacheManager(RedisConnectionFactory connectionFactory) { RedisCacheConfiguration cacheConfig = RedisCacheConfiguration.defaultCacheConfig() .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer())) .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer())); return RedisCacheManager.builder(connectionFactory) .cacheDefaults(cacheConfig) .build(); }
内容的提问来源于stack exchange,提问作者Tudor Cheregi

