缓存雪崩与击穿

大量缓存同时失效(雪崩)或热点键失效瞬间(击穿)会把流量直压数据库;对策包括 TTL 抖动、逻辑过期、互斥重建与热点永不过期策略。

缓存雪崩与击穿是什么

缓存雪崩指大批缓存键在同一时间失效,或缓存层整体宕机,导致流量瞬间全部压向数据库;缓存击穿指单个热点键失效的刹那,大量并发请求同时回源重建同一份数据。两者的后果相同:源库被瞬时打满,进而拖垮整个链路。对策包括给过期时间加随机抖动、用互斥锁让同一时刻只有一个请求回源、逻辑过期配合后台异步刷新,以及让热点数据多副本或本地缓存承接读流量。

基本信息

雪崩大批键同时失效或缓存层不可用,流量集中打到源库
击穿单个热点键失效瞬间,大量请求并发回源重建
穿透查询不存在的数据,每次都绕过缓存直查源库
首要对策TTL 加随机抖动;互斥锁单飞重建;逻辑过期后台刷新
应急兜底回源超限时返回旧值或降级数据,保护存储层

典型使用场景

  • 首页与活动页:热点数据集中,失效瞬间最易击穿,需要提前预热
  • 缓存层维护窗口:重启或扩容时命中率骤降,要有限流与降级预案
  • 整点批量刷新:定时预热任务与集中过期叠加时容易形成雪崩
  • 刚上线的爆款商品:读流量骤增,本地缓存与热点复制可分摊压力
  • 爬虫与异常查询:不存在的键被反复查询,需空值缓存或布隆过滤器拦截
  • 促销前压测:注入批量失效场景,验证单飞重建与降级开关是否可用

三类问题与对策

问题触发条件对策
雪崩大批键同时过期或缓存集群故障TTL 加随机抖动;多级缓存;缓存不可用时限流回源
击穿热点键过期瞬间并发回源互斥锁单飞重建;逻辑过期后台刷新;热点键不过期
穿透查询不存在的数据空值缓存设短过期;布隆过滤器前置拦截;参数校验
回源风暴重建期间无并发控制单飞 + 回源限流,超出部分直接返回旧值

单飞重建与逻辑过期

单飞重建与逻辑过期
# 方案一:互斥锁单飞,保证同一键同一时刻只有一个请求回源
if not cache.get(key):
    if lock.acquire(key, timeout=1s):      # 只放一个请求去重建
        value = load_from_db(key)
        cache.set(key, value, ttl=jitter(300s))   # TTL 加随机抖动
        lock.release(key)
    else:
        sleep(50ms)                        # 其余请求短暂等待后重试
        return cache.get(key) or stale_value(key)
# 方案二:逻辑过期,值内记录过期时间,后台异步刷新,读侧先返回旧值
# 兜底:回源量超过阈值时直接返回旧值并告警,避免数据库被打满
重建必须控并发:无锁并发回源等于把数据库暴露在整个失效窗口上,键越热点破坏力越大。
缓存层自身也会故障:只设计「缓存命中」路径而没有「缓存不可用」时的限流与降级方案,等于把可用性押在缓存上。

易错点

  • TTL 统一设置:整点批量失效,数据库瞬时压力成倍上升
  • 热点键失效后无并发控制:所有请求同时回源重建同一份数据
  • 空值不缓存:查询不存在的键每次都穿透到数据库
  • 缓存层故障无降级:命中率归零后源库直接被打满
  • 重建逻辑未演练:真触发时锁失效或超时设置不当,保护形同虚设

数据来源与参考

  • AWS 白皮书:Database Caching Strategies Using Redis
  • Redis 文档:缓存问题与模式
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌