redis宕机时,spring boot服务必须有兜底逻辑:默认lettuce抛redisconnectionfailureexception,jedis抛jedisconnectionexception;@cacheable无降级能力,需改用redistemplate显式操作并加try-catch fallback;本地缓存推荐caffeine而非concurrenthashmap,因其支持过期、淘汰、监控等降级关键能力。

Redis宕机时,Spring Boot服务不能直接报500或卡死——必须有兜底逻辑。核心不是“要不要降级”,而是“降级路径是否可控、可测、不污染主流程”。
Redis连接失败时,RedisTemplate抛什么异常?
默认情况下,RedisTemplate底层用的是Lettuce(Spring Boot 2.0+默认),连接失败时会抛出RedisConnectionFailureException;若用Jedis,则常见JedisConnectionException。这些异常都继承自DataAccessException,但具体类型会影响你捕获的粒度。
- 不要只捕获
Exception,否则会吞掉业务逻辑异常,建议明确捕获DataAccessException及其子类 - 连接超时(
timeout)和连接拒绝(Connection refused)触发时机不同:前者走完重试仍失败,后者可能在建立连接阶段就抛出 - 如果用了连接池(如
GenericObjectPool),还要注意CannotGetRedisConnectionException——说明池已耗尽,不只是Redis挂了
用@Cacheable时Redis不可用,缓存注解还生效吗?
不生效。@Cacheable依赖CacheManager,而Redis-backed的CacheManager(如RedisCacheManager)在初始化失败或运行时连接中断时,会直接抛异常,导致整个方法调用失败——它本身不带降级能力。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 想让
@Cacheable具备降级,必须配合@Caching+@Cacheable+@CachePut手动组合,或改用Resilience4j等框架包装方法调用 - 更现实的做法是:弃用
@Cacheable做主缓存逻辑,改用RedisTemplate显式操作,并在外层加try-catch + fallback分支 - 如果你坚持用
@Cacheable,至少把CacheManager配置成支持fail-fast但不中断业务:例如设置cacheNullValues=false,避免null被缓存,再配合本地缓存兜底
本地缓存回退为什么推荐用Caffeine而不是ConcurrentHashMap?
ConcurrentHashMap只是线程安全的Map,没有过期、淘汰、统计等能力;而Caffeine提供LRU/King-of-the-Hill淘汰、写后/访问后过期、最大容量限制、命中率监控——这些对降级场景至关重要。
- 降级时最怕“脏数据长期滞留”,
Caffeine的expireAfterWrite(5, TimeUnit.MINUTES)能自动清理陈旧数据 - 当Redis恢复后,需同步刷新本地缓存,
Caffeine支持refreshAfterWrite,而ConcurrentHashMap得自己手写定时任务 - 别忽略
maximumSize(1000)——没设上限的本地缓存,在高频降级下可能OOM
序列化不兼容导致反序列化失败,怎么让服务不崩?
新增字段后,老版本服务读取新序列化数据会抛UnrecognizedPropertyException(Jackson)或InvalidDefinitionException(默认GenericJackson2JsonRedisSerializer)。这不是连接问题,而是数据契约断裂。
- 必须关闭Jackson的
FAIL_ON_UNKNOWN_PROPERTIES:objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) - 别用
StringRedisTemplate存JSON字符串来绕过——它无法处理泛型类型擦除,反序列化时容易ClassCastException - 真正安全的做法是:所有缓存对象实现
Serializable,并显式定义serialVersionUID;同时用GenericJackson2JsonRedisSerializer替代默认序列器,并传入带宽松配置的ObjectMapper
降级不是加一层try-catch就完事。关键在于:Redis不可用时,你能否在毫秒级内切换到另一条确定路径,且这条路径的数据时效性、一致性、内存占用都在预期之内——这需要提前设计缓存层级、明确各层职责、并反复压测降级路径的真实表现。










