过期缓存:如何防止缓存被流量打穿?

2024-12-12 杜世伟 Message

防止过期缓存被流量打穿(缓存雪崩或缓存穿透)是缓存设计中的一个关键问题。以下是一些有效的方法来避免这些问题:

1. 设置不同的过期时间(过期抖动)

  • 问题:如果大量缓存同时过期,可能导致瞬时高并发请求直接打到后端服务,造成压力激增。
  • 解决方案:为不同缓存键设置一个随机范围内的过期时间(如 60s + rand(0,10s)),使缓存失效时间分散,减少同一时间的大量请求同时触发缓存更新。

2. 缓存预热

  • 问题:缓存过期后,第一次请求可能会因未命中缓存导致后端压力。
  • 解决方案
    • 在缓存即将过期前,后台异步任务或定时任务预先加载并更新缓存。
    • 例如,使用类似「双写缓存」策略,定期将新的数据更新到缓存中。
    • 利用消息队列通知更新。

3. 请求锁或请求合并(Cache Stampede)

  • 问题:大量并发请求同时访问同一缓存键时,会导致所有请求同时访问后端服务。
  • 解决方案
    • 请求锁:当某个键的缓存过期时,使用分布式锁(如 Redis 的 SETNX)控制只有一个请求去加载数据并更新缓存,其他请求等待或返回旧缓存。
    • 请求合并:将多个并发请求合并为一个请求,减少对后端的压力。

4. 永不过期缓存(逻辑过期)

  • 问题:缓存失效可能造成瞬时流量打击后端。
  • 解决方案
    • 缓存层设置为永不过期,但数据过期逻辑由应用层控制。
    • 通过附加时间戳标记数据有效期,如果检测到逻辑过期,则后台异步更新缓存。

5. 限流与降级

  • 问题:当缓存打穿导致后端服务承压时,可能进一步影响整体服务稳定性。
  • 解决方案
    • 实施流量限流(如令牌桶算法)对突发流量进行限制。
    • 实施降级策略(如返回默认值或备用数据),以减少对后端的压力。

6. 多级缓存

  • 问题:单一缓存层无法有效应对高并发下的缓存击穿。
  • 解决方案
    • 增加缓存层级,如本地缓存(如 Caffeine)+ 分布式缓存(如 Redis)。
    • 本地缓存优先命中,减少对分布式缓存和后端的压力。

7. 布隆过滤器(防止缓存穿透)

  • 问题:无效或非法请求不断击打缓存,导致所有请求直接到后端。
  • 解决方案
    • 使用布隆过滤器快速判断请求是否存在合法性,拦截非法请求。
    • 例如,判断缓存键是否可能存在,如果布隆过滤器判断不存在,则直接返回,避免访问后端服务。

8. 异步重建缓存

  • 问题:同步重建缓存可能导致请求阻塞。
  • 解决方案
    • 将缓存重建任务交由后台异步任务处理,用户请求返回旧数据或占位数据,待缓存完成更新后再提供新的数据。


结合实际业务需求,推荐综合使用多种方法,例如设置随机过期时间、引入请求锁和逻辑过期机制,以及多级缓存和布隆过滤器的配合,可以最大程度地降低缓存打穿的风险。通过监控和流量分析工具,持续优化缓存策略,也是保障系统稳定性的关键步骤。

标签: 缓存 过期 穿透 重建

Powered by emlog 沪ICP备2023034538号-1