note4cs/技术/Redis/缓存设计.md
2025-03-20 18:27:05 +08:00

4.9 KiB
Raw Blame History

缓存穿透、缓存击穿、缓存雪崩

1. 缓存穿透

定义:查询一个不存在的数据(如数据库中无对应记录),导致请求绕过缓存直接访问数据库,可能对数据库造成压力。
解决方案

  • 缓存空值:即使查询结果为空,也将空值写入缓存并设置短过期时间,避免重复查询数据库。
  • 布隆过滤器:通过概率数据结构拦截不存在的查询请求,减少无效数据库访问。
  • 请求校验对用户输入参数进行合法性校验如ID格式过滤非法请求。

2. 缓存击穿

定义:某个热点数据的缓存失效,导致大量并发请求直接冲击数据库。
解决方案

  • 热点数据永不过期:物理上不设置过期时间,通过后台异步更新缓存。
  • 分布式锁:缓存失效时,仅允许一个线程回源数据库更新缓存,其他线程等待。
  • 预加载:在缓存失效前主动加载数据,避免空窗期。

3. 缓存雪崩

定义:大量缓存同时失效(如设置了相同过期时间),导致请求集中冲击数据库。
解决方案

  • 过期时间随机化:为缓存设置基础过期时间+随机值如1-5分钟分散失效时间。
  • 服务熔断与限流:当数据库压力过大时,触发熔断机制或限制请求速率,保护后端系统。
  • 多级缓存:使用主备缓存(如本地缓存+Redis主缓存失效时从备缓存或数据库加载。
  • 高可用架构构建Redis集群或主从架构避免单点故障导致的雪崩。

总结

  • 穿透:防无效查询,用空值缓存+布隆过滤器。
  • 击穿:保热点数据,用永不过期+锁/预加载。
  • 雪崩:分散失效时间+熔断限流+多级缓存。

缓存一致性

一、缓存一致性问题的定义与风险

缓存与数据库数据不一致的核心矛盾在于:非原子操作导致中间状态暴露
典型问题场景

  1. 并发写冲突多个请求同时修改数据缓存与数据库更新顺序不一致如A请求更新数据库B请求删除缓存
  2. 读写分离延迟:数据库主从架构中,从库同步延迟导致缓存更新读取到旧数据。
  3. 缓存失效窗口:缓存删除后、新数据加载前的短暂时间内,请求可能读取到旧数据。

二、优化与解决方案

1. 延迟双删策略

  • 操作流程:更新数据库后,延迟删除缓存(如等待几百毫秒),确保数据库事务提交且从库同步完成后再清理缓存,避免旧数据残留。
  • 适用场景:对一致性要求较高且能容忍短暂延迟的场景(如电商库存更新)。

2. 分布式锁控制并发

  • 实现方式在写操作前加锁如Redis分布式锁确保同一时间只有一个线程执行“更新数据库+删除缓存”的流程,防止并发冲突。
  • 缺点:可能降低系统吞吐量,需权衡性能与一致性。

3. 异步消息队列更新

  • 方案设计:将数据库变更事件(如增删改)发布到消息队列,由消费者异步更新缓存,通过最终一致性降低直接耦合。
  • 优势:解耦系统组件,提升高并发场景下的稳定性。

4. 版本号/时间戳控制

  • 实现逻辑:为数据添加版本号或时间戳,缓存更新时校验版本,仅当缓存版本低于数据库时才更新,避免覆盖最新数据。
  • 适用场景:需要精确控制数据版本的场景(如金融交易系统)。

5. 多级缓存协同更新

  • 架构设计结合本地缓存如Caffeine与分布式缓存如Redis通过层级失效机制如先更新数据库再逐级删除本地缓存和分布式缓存减少不一致窗口。
  • 示例:更新数据库后,先删除本地缓存,再通过发布-订阅模式通知其他节点删除缓存。

6. 物理删除代替更新缓存

  • 核心思想:避免直接更新缓存(可能导致脏数据),而是通过删除缓存触发后续请求自动从数据库加载新数据。
  • 实践建议:优先使用“先更新数据库,再删除缓存”的顺序,降低数据不一致概率。

三、总结与权衡

  • 强一致性 vs 性能:无法完全避免短暂不一致,需根据业务需求选择策略(如金融交易需分布式锁,电商促销可接受最终一致性)。
  • 监控与优化:通过监控缓存命中率、数据库负载等指标,动态调整过期时间、锁粒度等参数。
  • 技术选型结合分布式缓存如Redis集群、消息队列如Kafka和一致性协议如CPU缓存MESI协议提升系统整体一致性。