缓存雪崩是什么
缓存雪崩指大批缓存几乎在同一时刻失效,原本被挡住的请求同时涌向数据库,造成回源流量成倍放大甚至把数据库压垮。最常见的成因是给一批数据设置了完全相同的过期时间,例如上线时集中预热、TTL 统一为 3600 秒,那么一小时后它们会同时消失。另一类成因是缓存实例整体重启或故障,所有键同时不可用,效果与批量过期相同。
基本信息
| 主要成因 | 批量键 TTL 相同、缓存实例整体重启、集中刷新 |
|---|---|
| 首选对策 | TTL 使用基础值加随机抖动,把到期时刻打散 |
| 兜底手段 | 回源限流、熔断降级、多级缓存 |
| 离线准备 | 热点数据预热与分级过期,避免上线瞬间集中重建 |
| 观测指标 | 缓存命中率骤降、数据库 QPS 突增、回源耗时上升 |
典型使用场景
- 大促前的容量评估:按最坏情况估算全部缓存失效时数据库能否顶住
- 发布上线前的预热:新版本启动时批量加载热点数据,加载顺序与 TTL 都要打散
- 缓存实例重启后的恢复:分批重启、重启后先限流放量而不是立刻全量放行
- 多级缓存设计:本地缓存兜住最热的一批键,减少对远端缓存的依赖
- 降级预案:明确缓存不可用时哪些接口直接返回默认值或兜底数据
TTL 打散写法
TTL 打散写法
# 应用侧生成 TTL:基础值加随机抖动,避免整批键同时到期
# ttl = 3600 + random(0, 600)
redis-cli SET feed:1001 '{data}' EX 4123
redis-cli SET feed:1002 '{data}' EX 3789
redis-cli TTL feed:1001 # 核对实际剩余时间
redis-cli INFO stats | grep -E 'keyspace_hits|keyspace_misses' # 命中率变化
redis-cli INFO stats | grep expired_keys # 过期键清理量分层防御
| 层次 | 手段 | 作用 |
|---|---|---|
| 缓存写入 | TTL 加随机抖动、分级过期 | 从源头避免集中失效 |
| 请求入口 | 回源限流、排队等待 | 限制同时打到数据库的请求量 |
| 应用层 | 互斥重建、逻辑过期 | 单个热点键只放一个请求回源 |
| 架构层 | 多级缓存、读写分离 | 用本地缓存与从库分摊压力 |
| 兜底 | 熔断降级返回默认值 | 保证核心链路可用而不是全部失败 |
随机抖动范围要按回源的承受力设计:抖动窗口太小起不到打散作用,太大则部分数据过早失效、整体命中率下降。常见做法是取基础 TTL 的百分之十到二十,并确保最短存活时间不低于业务能接受的下限。
回源限流会牺牲一部分请求:被限流的请求需要明确返回什么,是排队、降级到旧值还是直接报错。这个策略必须与业务方事先约定,不能等到雪崩发生时才临时决定。