Redis集群全不可用时须立即降级至本地缓存并串行重建,禁用远程调用、设缓存上限与合理过期时间、监控命中率/DB查询量/连接失败数三大指标。

Redis集群全不可用时,请求别直接打穿数据库
机房断网意味着整个Redis集群瞬间失联,所有 GET、SET 都会超时或报 redis.clients.jedis.exceptions.JedisConnectionException(Java)或 redis.ConnectionError(Python),此时若不做拦截,所有读请求将100%穿透到DB——这是雪崩最凶险的形态。
关键不是“等Redis恢复”,而是让系统在失联期间仍能扛住流量。实操上必须做两件事:
- 在缓存客户端层统一捕获连接异常,而不是让业务代码各自重试
- 立即切换至本地缓存(如Caffeine、Guava Cache)或降级策略,且该降级不能依赖任何远程调用
- 降级响应必须带明确标识(如HTTP头
X-Cache-Status: fallback),方便后续链路识别和监控
示例(Spring Boot + Jedis):
try {
String value = jedis.get(<code>"user:1001"</code>);
if (value != null) return value;
} catch (JedisConnectionException e) {
// 不抛出!不重试!直接走降级
return localCache.getIfPresent(<code>"user:1001"</code>);
}
如何让本地缓存不变成新瓶颈
很多人加了Caffeine就以为万事大吉,结果压测时发现本地缓存CPU飙升、GC频繁——因为没设限。本地缓存不是Redis的平替,它跑在应用进程里,资源是共享的。
必须控制三件事:
-
maximumSize要设硬上限(比如10_000),避免OOM;不要用无界缓存 -
expireAfterWrite时间建议设为Redis原有过期时间的1/3~1/2(例如Redis设30min,本地设10min),防止数据长期陈旧 - 禁止在本地缓存里存大对象(如完整订单JSON),只缓存ID或关键字段,查DB时再组装
错误写法:cache.put("order:123", fullOrderObject);正确做法:cache.put("order:123:status", "paid")
断网期间怎么避免缓存重建挤垮数据库
Redis一断,所有缓存miss,如果每个请求都去查DB再回填本地缓存,高并发下DB瞬间被刷爆——这叫“伪降级”。真正的保护是让重建行为串行化。
核心是加一层轻量级互斥锁,但注意:不能用Redis锁(它已经挂了),得用JVM内锁或分布式协调服务(如ZooKeeper临时节点)。简单场景推荐:
- 用
ConcurrentHashMap.computeIfAbsent+FutureTask实现本地锁(单机有效) - 对关键key(如首页配置、用户权限)预置兜底值,启动时就加载进本地缓存,断网后直接返回
- 异步触发预热:检测到Redis断连后,由后台线程按优先级拉取TOP 100热点key,而非等请求触发
别碰 synchronized 方法块——它会阻塞整个HTTP线程,QPS直接归零。
监控里哪些指标一亮红灯就得人工介入
靠日志排查雪崩太慢。必须盯死三个实时指标,它们比“Redis是否ping通”更早暴露问题:
-
cache.hit.rate突降到 85%),说明缓存层已大面积失效或绕过 -
db.query.qps在非活动时段突然翻倍,且伴随db.latency.p99 > 1000ms,基本确认击穿发生 -
redis.client.connection.failed.count每分钟持续 > 100,大概率是网络分区而非单点故障
这些指标必须接入告警通道(如企业微信+电话),延迟超过30秒就失去意义——雪崩的黄金处置窗口只有2~3分钟。
真正难的是把“随机过期时间”“本地缓存驱逐策略”“降级开关灰度”这些细节,在不同服务间对齐。一个团队里有人用Caffeine,有人用Ehcache,有人手动new HashMap,雪崩来的时候,最先崩的其实是协作一致性。










