# Redis 中的缓存击穿、缓存穿透和缓存雪崩是什么?

9 min read
Table of Contents

Redis 中的缓存击穿、缓存穿透和缓存雪崩是什么?

Redis 缓存击穿、缓存穿透与缓存雪崩详解

【核心定义】

缓存击穿、缓存穿透和缓存雪崩是三种因缓存系统使用不当或外部异常导致的高并发场景下数据库压力激增甚至服务崩溃的典型问题。

【关键要点】

  1. 缓存击穿:某个热点Key在缓存过期瞬间,大量并发请求直接穿透到数据库。

    • 本质:单点热点失效引发的瞬时高压。
    • 典型场景:明星八卦、秒杀商品在缓存过期时被高频访问。
  2. 缓存穿透:查询一个数据库中根本不存在的数据,导致每次请求都直达数据库。

    • 本质:恶意或异常查询绕过缓存保护层。
    • 典型场景:攻击者用随机ID(-1, 0)或不存在用户名发起海量请求。
  3. 缓存雪崩:大量缓存Key在同一时间段集中过期,导致所有请求涌向数据库。

    • 本质:缓存大规模失效引发的系统性风险。
    • 典型场景:缓存服务器重启、批量缓存设置相同过期时间。

【深度推导/细节】

缓存击穿的核心矛盾与解决方案

矛盾:热点数据过期瞬间的并发竞争 vs 数据库单点承压极限。

逻辑拆解:

Step 1: 热点Key缓存过期
Step 2: 线程A发现缓存Miss,准备查询DB
Step 3: 此时线程B、C...N同时到达,均发现缓存Miss
Step 4: 所有线程同时执行DB查询,造成数据库瞬时QPS暴增

解决方案:

  • 互斥锁(分布式锁):第一个线程加锁查DB并回填缓存,后续线程等待
  • 逻辑过期:缓存值中存储过期时间,异步更新,永不过期
  • 热点Key永不过期:后台定时刷新,适用于极热点数据

缓存穿透的深度防御机制

矛盾:无效查询的过滤成本 vs 数据库被无效查询拖垮。

分层防御体系:

  1. 第一层:参数校验 - 拦截明显非法请求(ID≤0)
  2. 第二层:布隆过滤器 - 用概率数据结构判断Key是否存在
  3. 第三层:空值缓存 - 对查询结果为空也进行缓存(设置较短TTL)
  4. 第四层:限流熔断 - 对异常查询模式进行限流

布隆过滤器原理:

  • 使用k个哈希函数将元素映射到位数组的k个位置
  • 查询时若所有位置都为1,则元素可能存在;若有0,则一定不存在
  • 特点:空间效率极高,但有误判率(可通过增加数组大小降低)

缓存雪崩的系统性防护

矛盾:缓存失效时间的集中性 vs 数据库的平稳负载需求。

防护策略矩阵:

时间维度:
- 随机过期时间:基础过期时间 + 随机偏移量(如±10%)
- 分层过期:不同类型数据设置不同过期策略
架构维度:
- 多级缓存:本地缓存 + Redis集群
- 热点数据永不过期 + 异步更新
故障维度:
- 熔断降级:数据库压力过大时返回降级数据
- 服务隔离:缓存失效时限制对核心服务的冲击

【关联/对比】

维度缓存击穿缓存穿透缓存雪崩
失效范围单个热点Key不存在的Key大量Key同时
数据状态数据库中存在数据库中不存在数据库中存在
触发条件热点Key过期恶意/异常查询批量过期/宕机
影响范围局部高压持续无效查询系统性风险
防御重点热点保护无效过滤失效分散

与数据库保护机制的关联:

  • 这三种问题最终都体现为数据库保护机制的失效
  • 需要与数据库连接池、慢查询监控、读写分离等配合防御

『面试官追问』

  1. 布隆过滤器如何解决缓存穿透?它的优缺点是什么?

    • 优点:内存占用极小,查询效率O(k)
    • 缺点:有误判率,不支持删除操作
    • 改进方案:布谷鸟过滤器支持删除但更复杂
  2. 互斥锁方案中,如果第一个获取锁的线程挂了怎么办?

    • 需要设置锁超时时间,防止死锁
    • 可采用Redisson等框架的看门狗机制自动续期
    • 备选方案:使用Redis的SETNX+EXPIRE原子操作
  3. 如何识别和监控热点Key?

    • 监控方案:Redis的hotkeys参数、监控客户端访问模式
    • 识别指标:QPS突增、内存占用集中、CPU使用率异常
    • 美团开源的监控工具:CacheCloud
  4. 多级缓存如何设计?各层作用是什么?

    • L1:本地缓存(Caffeine/Guava) - 应对极热点,纳秒级响应
    • L2:Redis集群 - 分布式缓存,毫秒级响应
    • L3:数据库 - 数据持久层,最终数据源
  5. 在微服务架构中,如何全局防御缓存雪崩?

    • 服务网格层面:全链路缓存策略配置
    • 配置中心:统一管理缓存过期时间策略
    • 监控告警:实时监控缓存命中率、数据库连接数

【直击痛点:关键数字与设计合理性】

  1. 布隆过滤器的误判率与内存权衡

    • 公式:p ≈ (1 - e^(-kn/m))^k
    • 经验值:1000万元素,1%误判率约需11.4MB
    • 设计合理性:用可控的内存换取对恶意请求的有效过滤
  2. 空值缓存的TTL设置

    • 通常设置2-5分钟,既防止重复查询,又避免长期占用内存
    • 设计合理性:远短于正常缓存,平衡内存使用与保护效果
  3. 随机过期时间的偏移范围

    • 基础TTL ± 10%-20%的随机值
    • 设计合理性:足够分散请求,又不影响业务时效性
  4. 热点Key识别阈值

    • QPS > 1000 或 访问占比 > 1% 可视为热点
    • 设计合理性:基于实际业务负载和数据库承载能力

【版本差异与演进】

Redis 4.0+ 的新特性支持:

  • MEMORY USAGE命令:更精确分析Key内存占用
  • LAZY FREEING:异步删除大Key,避免阻塞
  • 模块系统:可开发自定义的缓存保护模块

Redis 6.0+ 的线程模型优化:

  • 多线程IO处理,提升高并发下的响应能力
  • 更好的配合客户端连接池,缓解击穿压力

Redis 7.0+ 的增强:

  • Function特性:可在服务端实现复杂缓存逻辑
  • 更精细的内存控制,支持按需驱逐策略

总结:三种缓存问题本质都是缓存层保护作用的失效,需要从预防、检测、缓解三个维度构建防御体系。在实际架构中,往往需要组合使用多种策略,并结合业务特点进行调优,形成从客户端到数据库的全链路保护。

My avatar

文章看完了,不打算去别的篇章转转吗?👀 感谢你的耐心阅读!如果你有问题想探讨,或者发现了文中的 Bug,请务必通过页脚的链接联系我


More Posts

Comments