点评--day03--2. 2 Redis 缓存三大经典高并发问题

9 阅读4分钟

📚 Redis 缓存三大经典高并发问题

1. 缓存穿透 (Cache Penetration)

👉 核心定义: 请求的数据在 Redis 中不存在,在 MySQL 数据库中也不存在

💥 产生危害: 恶意用户疯狂请求不存在的 ID(如 id = -1),导致请求全部越过 Redis,直接“穿透”打在 MySQL 上,瞬间压垮数据库。

🛡️ 解决方案:

  • 方案一:缓存空对象 (Cache Empty Object)。 数据库查不到也把空结果存入 Redis,并设置极短的 TTL。 (本实战项目采用此方案,简单直接)
  • 方案二:布隆过滤器 (Bloom Filter)。 在请求到达 Redis 之前加一道基于哈希算法的拦截网,快速判断该数据“是否绝对不存在”。适用于亿级海量数据场景。

2. 缓存雪崩 (Cache Avalanche)

👉 核心定义: 指在同一时段内,大量的缓存 Key 同时失效(过期) ,或者 Redis 服务直接宕机,导致大量请求直接到达数据库,带来巨大压力。

🤔 为什么会发生?

通常是因为在做缓存预热时,给同一批商品/商户设置了完全相同的超时时间(TTL)。当这个时间一到,这批数据的缓存同时清空。

🛡️ 解决方案(多管齐下):

  1. TTL 加上随机值(最常用且有效): 在给数据设置过期时间时,不要使用固定的值(如全是 30 分钟),而是在基础时间上加上一个随机时间(如 30分钟 + 随机 1~5 分钟)。这样就能将缓存失效的时间打散,避免集体过期。
  2. 利用 Redis 高可用架构: 针对 Redis 宕机引发的雪崩,可以搭建 Redis 哨兵模式(Sentinel)或集群模式(Cluster),实现主从随时切换,避免单点故障。
  3. 多级缓存兜底: 采用 本地缓存(如 Caffeine/Guava) + Redis 分布式缓存 的架构。Redis 挂了或者失效了,还有本地内存顶着。
  4. 服务降级与限流: 在 Spring Cloud 微服务架构中,使用 Sentinel 或 Hystrix 等组件。一旦发现数据库访问压力超标,直接拒绝后续请求,返回友好提示(如“活动太火爆,请稍后再试”),牺牲部分用户体验来保全整个系统的存活。

3. 缓存击穿 (Cache Breakdown / 热点 Key 问题)

👉 核心定义:某一个被高频访问的热点 Key(例如:秒杀活动中的爆款商品),在它失效(TTL 到期)的那个瞬间,正好有无数个并发请求打过来。

💥 产生危害: 因为这一个 Key 失效了,无数个并发线程会同时发现“缓存未命中”,然后全部同时去查询 MySQL 并尝试重建缓存。数据库会在这一瞬间被这一个热点查询击穿。

💡 易混淆点区分:

  • 雪崩是“很多个不同的 Key”同时失效。
  • 击穿是“单个极度热点的 Key”突然失效。

为了解决击穿问题,业界有两种截然不同的架构设计思想:

方案 A:互斥锁 (Mutex Lock)

核心思想:强一致性。 不允许并发去查数据库。

  • 执行逻辑: 当多个线程发现热点 Key 失效时,它们不能立刻去查数据库。而是大家先去抢一把“锁”(通常利用 Redis 的 setnx 命令)。

    • 抢到锁的那个幸运儿,负责去数据库查询数据并重新写入 Redis 缓存,然后释放锁。
    • 没抢到锁的其他线程,只能乖乖休眠(如 50ms)然后重试,直到缓存被那个幸运儿建好为止。
  • 优点: 保证了数据绝对的一致性。

  • 缺点: 性能较差,因为大量线程在相互等待;如果设计不好,甚至有死锁的风险。

方案 B:逻辑过期 (Logical Expiration)

核心思想:高可用性。 宁愿返回稍微旧一点的数据,也绝不让线程等待。

  • 执行逻辑: 在往 Redis 存入热点数据时,不设置真正的 Redis TTL,而是由业务代码在 JSON 数据内部增加一个 expireTime 字段(例如:{"name":"商品", "expireTime": "2026-03-06 10:00"})。

    • 当线程查询 Redis 时,数据永远都在(因为没设物理 TTL)。
    • 线程拿出来一看,发现 expireTime 已经过期了。它不仅不会阻塞自己,还会直接把这个旧数据返回给前端
    • 同时,它会单独开启一个后台新线程,由这个新线程去默默地查询 MySQL 并更新 Redis 里的新数据和新的逻辑过期时间。
  • 优点: 性能极佳,用户几乎感受不到延迟(因为不需要等待重构缓存)。

  • 缺点: 无法保证数据的强一致性,在后台线程更新完之前,其他用户拿到的是旧数据。


📝 总结:三大问题对阵表

异常现象问题本质根本原因核心解决思路
缓存穿透Redis 无,DB 无恶意请求不存在的数据缓存空值、布隆过滤器
缓存雪崩Redis 无,DB 有批量 Key 同时过期 / 宕机随机 TTL、集群高可用、限流降级
缓存击穿Redis 无,DB 有某一个高并发热点 Key 突然过期互斥锁(强一致)、逻辑过期(高可用)