缓存击穿,缓存穿透,缓存雪崩的原因和解决方案(或者说使用缓存的过程中有没有遇到什么问题,怎么解决的)

  1. 缓存穿透:
    是指查询一个不存在的数据,由于缓存无法命中,将去查询数据库,但是数据库也无此记录,并且出于容错考虑,我们没有将这次查询的null写入缓存,这将导致这个不存在的数据每次请求都要到存储层去查询,失去了缓存的意义。在流量大时,可能DB就挂掉了,要是有人利用不存在的key频繁攻击我们的应用,这就是漏洞。

解决方案:空结果也进行缓存,可以设置一个空对象,但它的过期时间会很短,最长不超过五分钟。 或者用布隆过滤器也可以解决,Redisson框架中有布隆过滤器。

  1. 缓存雪崩:
    是指在我们设置缓存时采用了相同的过期时间,导致缓存在某一时刻同时失效,请求全部转发到DB,DB瞬时压力过重雪崩。

解决方案:原有的失效时间基础上增加一个随机值,比如1-5分钟随机,这样每一个缓存的过期时间的重复率就会降低,就很难引发集体失效的事件。

  1. 缓存击穿
    是指对于一些设置了过期时间的key,如果这些key可能会在某些时间点被超高并发地访问,是一种非常"热点"的数据。这个时候,需要考虑一个问题:如果这个key在大量请求同时进来之前正好失效,那么所有对这个key的数据查询都落到DB,我们称为缓存击穿。

解决方案:在分布式的环境下,应使用分布式锁来解决,分布式锁的实现方案有多种,比如使用Redis的setnx、使用Zookeeper的临时顺序节点等来实现

在使用缓存(如 Redis、Memcached 等)提升系统性能时,经常会遇到一些典型问题,包括 缓存击穿、缓存穿透、缓存雪崩 。这些问题如果不妥善处理,可能导致数据库压力骤增,甚至服务崩溃。下面分别介绍它们的 原因、影响及解决方案


一、缓存击穿(Cache Breakdown)

原因:

某个 热点 key(访问非常频繁的 key)在缓存中突然失效(过期),此时大量并发请求同时访问这个 key,由于缓存中没有,这些请求都会直接打到数据库,造成数据库瞬时压力过大,就像"击穿"了缓存保护层。

影响:

  • 数据库压力骤增,可能引起慢查询甚至宕机。
  • 影响系统整体响应速度与稳定性。

解决方案:

  1. 设置热点数据永不过期

    对于访问特别频繁的数据(比如热门商品信息),不设置过期时间,而是通过后台异步更新缓存,确保缓存一直有效。

  2. 使用互斥锁(Mutex Lock)

    当发现缓存未命中时,不是立即查数据库,而是先尝试获取一个分布式锁(如 Redis 的 SETNX),只有获取到锁的线程才去查数据库并重建缓存,其他线程等待或返回旧数据/默认值。

    适用于高并发且对数据实时性要求不是极端严格的场景。

  3. 逻辑过期

    不设置真正的 key 过期时间,而是在缓存 value 中维护一个逻辑过期时间,当发现逻辑过期时,使用后台线程异步更新缓存,当前请求仍可返回旧数据。


二、缓存穿透(Cache Penetration)

原因:

用户请求了一个 根本不存在的数据(比如不存在的商品 ID、非法参数等) ,导致每次请求都 穿透缓存,直接打到数据库。如果恶意用户大量发起这样的请求,数据库就会承受巨大压力。

影响:

  • 大量无效查询直接打到数据库,浪费资源。
  • 可能被恶意利用进行攻击(比如大量查询不存在的用户 ID)。

解决方案:

  1. 缓存空对象(Null Caching)

    当查询数据库也不存在该数据时,仍然将一个表示"空"的值(如 null、特殊标记)存入缓存,并设置较短的过期时间(如 30 秒 ~ 5 分钟),避免频繁查询数据库。

    注意:要防止缓存大量无意义空值占用空间。

  2. 布隆过滤器(Bloom Filter)

    在缓存层之前加一个布隆过滤器,用于快速判断某个 key 是否 可能存在。如果布隆过滤器判断该 key 一定不存在,则直接返回,不再查缓存和数据库。

    适合用于 ID 类查询,提前拦截非法或不存在的请求。

  3. 接口层校验

    加强参数校验,比如对 ID 范围、格式进行基础过滤,防止明显非法的请求进入系统。


三、缓存雪崩(Cache Avalanche)

原因:

大量缓存 key 在同一时间失效(比如设置了相同的过期时间),或者缓存服务宕机,导致大量请求直接打到数据库,造成数据库压力过大甚至崩溃,就像"雪崩"一样。

影响:

  • 数据库瞬间流量暴增,可能引发服务不可用。
  • 整个系统性能急剧下降。

解决方案:

  1. 设置不同的过期时间

    避免给大量 key 设置相同的过期时间,可以在基础的过期时间上加上随机值(如基础过期时间 30 分钟 + 随机 0~10 分钟),让缓存错峰失效。

  2. 使用高可用缓存架构

    比如 Redis 集群、主从 + 哨兵、Redis Cluster,避免单点故障导致整个缓存服务不可用。

  3. 熔断降级机制

    当数据库压力过大时,可以使用熔断器(如 Hystrix、Sentinel)暂时拦截部分请求,返回默认值或错误页,保护数据库。

  4. 多级缓存策略

    使用本地缓存(如 Caffeine、Guava Cache) + 分布式缓存(如 Redis)的多级架构,即使分布式缓存出现问题,本地缓存还能起到一定的缓冲作用。

  5. 缓存预热

    系统启动时或低峰期提前将热点数据加载到缓存中,避免刚上线或重启后大量请求直接访问数据库。


总结对比表

问题类型 原因 解决方案概要
缓存击穿 热点 key 突然失效,大量请求直接访问数据库 互斥锁、永不过期+后台更新、逻辑过期
缓存穿透 请求了不存在的数据,绕过缓存直接查库 缓存空对象、布隆过滤器、参数校验
缓存雪崩 大量 key 同时失效 / 缓存服务宕机,导致请求全部压到数据库 设置随机过期时间、高可用缓存、熔断降级、多级缓存、缓存预热

实际使用中的经验分享(补充)

在实际项目中,我们通常会 组合使用多种策略来防护以上问题,例如:

  • 对热门商品使用 永不过期 + 异步刷新 策略防止击穿;
  • 所有查询先经过 布隆过滤器缓存空对象 来防止穿透;
  • 给所有缓存 key 设置 随机过期时间 ,并采用 多级缓存 + 熔断降级 来防止雪崩;
  • 使用 Redis 哨兵或集群 提升缓存可用性;
  • 结合 监控系统(如 Prometheus + Grafana)实时观察缓存命中率、响应时间、数据库负载,及时发现异常。
相关推荐
YOU OU1 小时前
Redis基础常识与命令
数据库·redis·缓存
吳所畏惧6 小时前
宝塔面板Redis密码修改指南:SSH命令修改 vs 面板UI界面修改,哪个更靠谱?
运维·服务器·数据库·redis·缓存·ssh
Y38153266211 小时前
SERP API + Redis 缓存层:4 种方案对比与选型
数据库·redis·缓存
海兰13 小时前
【高速缓存】RedisVL 高级查询(全文搜索、混合搜索和 多向量搜索)
数据库·人工智能·redis·缓存
流星白龙1 天前
【Redis】4.基本全局命令
数据库·redis·缓存
流星白龙1 天前
【Redis】3.Redis安装与命令行客户端
数据库·redis·缓存
我不想名字重复1 天前
redis缓存和数据库数据保持一致
数据库·redis·缓存
时空无限1 天前
vllm 大模型启动缓存相关环境变量 export
linux·缓存·vllm
流星白龙2 天前
【Redis】6.计数其他命令
数据库·redis·缓存
正儿八经的少年2 天前
redis 的大 key 和热 key 详解
数据库·redis·缓存