当前位置: 首页 > news >正文

【后端开发】(图解)面试官最爱问的缓存三连:缓存穿透/击穿/雪崩到底怎么区分、怎么治理?

文章目录

  • 前言
  • 1 缓存穿透
    • 1.1 解决方案:缓存空值
    • 1.2 解决方案:布隆过滤器
  • 2 缓存击穿
    • 2.1 解决方案:互斥锁
    • 2.2 解决方案:逻辑过期
  • 3 缓存雪崩
    • 3.2 解决方案:给过期时间加随机值
    • 3.3 解决方案:做多级缓存
  • 写在文后

🔥 个人主页:铁皮哥(欢迎关注)
📌 作者简介:28届校招生,后端开发/Agent 方向在学
📚 学习内容:Java、Python、计算机视觉、大语言模型、Agent开发
📝 专栏内容:从零开始的Claude Code零代码生活(持续更新中)
不只背八股,更想搞懂为什么这样设计

前言

缓存是后端开发中几乎绕不开的一个难题,系统一上并发,数据库扛不住,第一反应往往就是把热点数据放进 Redis;接口一追求响应速度,也总会想到“这块能不能先走缓存”。可缓存这个东西,平时用起来像是在“加速”,真到线上出问题时,很多故障却恰恰也是从缓存开始的

其中最常被放在一起讨论的,就是缓存穿透、缓存击穿、缓存雪崩。它们都和“缓存失效”有关,但成因不一样、风险级别不一样、治理思路也不一样。

这篇文章不打算停留在对缓存三剑客的概念解释上,而是想把这三个高频问题真正拆开讲清楚:

  • 它们到底怎么区分
  • 各自通常在什么场景下出现
  • 为什么会把数据库拖垮
  • 常见治理方案分别解决的又是什么问题

1 缓存穿透

先看一个最简单的读请求流程:

Client → Redis(未命中)→ MySQL(未命中)→ 返回空

如果这个请求只是偶尔发生,其实问题不大。但如果同一个不存在的数据被频繁请求,事情就不一样了:Redis 一直查不到(因为根本没有),然后每一次请求都会直接打到数据库,结果就是缓存这一层完全失去保护作用

这就是所谓的缓存穿透(Cache Penetration)。

现在想象一个更真实的场景。
假设有一个接口是查用户信息的:

GET /user?id=123456

正常情况下用户存在并且被 redis 命中就会返回数据,但如果有人恶意请求或程序出现了 bug,导致一直有无效查询发过来

GET /user?id=99999999
GET /user?id=88888888
GET /user?id=77777777

这些 ID 在数据库里根本不存在,redis 也根本命中不了,结果每一个请求都要访问数据库如果请求量一大,数据库就会被这种无效查询给拖垮

常见的解决方案有两种:缓存空值布隆过滤器

1.1 解决方案:缓存空值

缓存空值的思路是即使数据库查不到,也把“空结果”缓存起来

流程变成:

Client → Redis(未命中)→ MySQL(未命中) → Redis 写入一个空值(短 TTL) → 返回空

之后再查同一个 key:

Client → Redis(命中空值)→ 直接返回

这种方案的优点是实现起来很简单,直接减少重复请求打向 DB
但是也要注意空值一定要设置较短 TTL(比如几分钟),否则可能影响数据“从无到有”的实时性。

1.2 解决方案:布隆过滤器

布隆过滤器的思路是在请求进入缓存之前,先判断这个 Key 是否“可能存在”。如果判断一定不存在,则直接拦下;如果可能存在,再放行。

流程:

Client → Bloom Filter(判断不存在)→ 直接拒绝
→(判断可能存在)→ Redis → MySQL

这种布隆过滤器方案的优点是可以在最前面拦截大量无效请求,对恶意攻击非常有效
但是局限是布隆过滤器有误判率,可能把不存在的数据当成存在。另外也要额外维护一个数据集合,增加了复杂性

关于布隆过滤器我之前写过一篇文章,可以参考:
【后端开发】(图解/面试题)拆解布隆过滤器,为什么它能防缓存穿透?

2 缓存击穿

缓存击穿和缓存穿透名字上有些许相似,但是有很大的不同。缓存击穿查的不是不存在的数据,而是“本来存在,但刚好失效的热点数据”

典型流程是这样的:

Client → Redis(命中)→ 返回数据 ✅(正常情况)

但某一时刻,这个 Key 过期了:

Client → Redis(未命中)→ MySQL(查询)→ 回写缓存

如果只是一个请求,这依然没问题。问题在于——这个 Key 是热点数据,当它一过期,在缓存重建的过程中可能有成千上万的请求进来,直接打到数据库,数据库被瞬间打穿。

如果这个热点 key 来源于多张表共同计算的结果,那缓存重建的过程就更长了,更容易出现问题。

常见的解决方案有两个:互斥锁逻辑过期

2.1 解决方案:互斥锁

互斥锁就是在第一次查缓存未命中时,该线程取走锁,并去执行缓存重建。在重建结束之前,其他线程发现锁已被取走,就阻塞一段时间后重新查询缓存,直至命中为止。

互斥锁方案的流程是这样的:

请求A → 获取锁 → 查询DB → 回写缓存 → 释放锁
请求B/C/D →获取锁失败→ 等待

这种方案的优点是能从根本上避免“并发回源”,但是注意要防止死锁(设置过期时间),同时等待策略要设计好(自旋 / 降级)。

2.2 解决方案:逻辑过期

逻辑过期就是对于热点 key,物理上不立刻删除缓存,业务上通过过期字段判断它是否该被更新

缓存过期的方案是这样的:

读取缓存 → 判断是否逻辑过期 → 未过期 → 直接返回
→ 已过期 → 返回旧数据 + 异步更新缓存

因为对用户请求来说,缓存并没有真的在 Redis 里消失,所以不会出现“所有请求同时 miss”的情况。真正的更新动作,通常只交给少量后台线程或抢到锁的请求去做

这种方案的优点是对于高并发热点数据非常有用,但是要注意的是用户可能会在短时间内读到旧数据

互斥锁和逻辑过期通常是一起使用的。

3 缓存雪崩

缓存雪崩其实就是同一时段大量的缓存key同时过期失效,或Redis服务宕机(近似所有key都失效),导致大量请求到达数据库,带来巨大压力。大量原本应该被缓存拦住的请求,在同一时刻或极短时间内,成批地涌向下游系统

典型流程是这样的:

大量请求 → Redis(大面积 miss / 不可用)→ 全部打到 MySQL ❗

缓存雪崩通常不是“偶然事件”,而是某些设计或异常导致的结果。

经典的发生场景如大量 Key 同时过期。比如你在某次上线时,批量写入缓存,所有 Key TTL = 30 分钟,那么 30 分钟之后一大批缓存同时失效,所有请求同时 miss,数据库瞬间承压。

再比如缓存服务出现了异常。redis 宕机了,所有请求都无法命中缓存,系统等价于没有缓存层,流量全部打到数据库。这类情况比大量 Key 同时过期更危险,因为是全量失效。

常见的解决方案有两种:给过期时间加随机值做多级缓存

3.2 解决方案:给过期时间加随机值

在同一时间批量写入缓存时,不要这样设置:

所有 Key TTL = 1800s

而是这样:

TTL = 1800s + 随机值(0~300s)

这样一来原本同一时刻过期的 Key 被打散到一段时间内,请求压力从“瞬时洪峰”变成“平滑流量”,这种方案非常简单同时也很有效。

3.3 解决方案:做多级缓存

在 Redis 之外,再加一层:

Client → 本地缓存(如 Caffeine)→ Redis → MySQL

当 Redis 出问题时,本地缓存还能兜住一部分流量,这样可以避免所有请求直接打到数据库。

写在文后

期待您的一键三连!如果有什么问题或建议欢迎在评论区交流!

http://www.jsqmd.com/news/714927/

相关文章:

  • 2026 国产 EDA 工具推荐:上海弘快 RedEDA,全流程自主可控更靠谱 - 品牌2026
  • I2C控制器及其应用
  • 题解:洛谷 P7077 [CSP-S 2020] 函数调用
  • 3大核心功能解密:OpenCore Legacy Patcher如何让老旧Mac重获新生
  • CSS如何使得响应式的侧边抽屉附带遮罩渐暗效果
  • 2026年一体化预制泵站/污水提升泵站/一体式泵站实力厂家推荐:聚焦技术领先与多场景应用方案 - 泵站报价15613348888
  • 绵阳老房翻新选对公司,千川环宇帮你实现安全焕新 - 资讯焦点
  • VS Code Copilot Next 成本失控真相(2024 Q2真实账单拆解):从$287→$49/月的7类配置陷阱与修复清单
  • 2026年宁波短视频代运营与GEO优化:中小企业同城获客完全指南 - 优质企业观察收录
  • 橱柜小拉手优质厂家盘点:精选五家实力生产商推荐指南 - 品牌策略师
  • 2026年度中国房车定制游服务商综合实力TOP6推荐 - 资讯焦点
  • Omdia:2025年第四季度,中国大陆云基础设施支出增长26%,AI与智能体成主要驱动力
  • 【网络协议-10】低成本物联网产品放弃SSL加密的隐形成本与市场逻辑
  • 从零开始:手把手教你跑通、分析和“解剖”大模型
  • 深度技术解析:Windows系统工具注册表权限管理完整指南
  • 让 Claude Code : Codex: Open Code 成本爆降 92%,没早用上这款开源工具。。。
  • 可替代进口频谱分析仪推荐:安徽白鹭电子实力诠释国产崛起 - 品牌推荐大师
  • 上海强平机器人官方联系方式合作电话官方网站官网 - 资讯焦点
  • 别再死记硬背了!用这5个Mathf函数搞定Unity角色移动与旋转(附完整代码)
  • 用Verilog和DAC芯片手把手教你做个可编程波形发生器(附完整RTL代码与示波器实测)
  • 【VS Code MCP插件生态搭建权威指南】:20年IDE架构师亲授5大核心配置步骤与3个避坑红线
  • 从传感器配置到标签解析:一份给研究者的RADIal数据集深度使用指南
  • 广州市黄埔区鑫邦租赁:广州二手空压机回收推荐哪几家 - LYL仔仔
  • Biosimilar抗体选购:TargetMol保障高特异性 - 资讯焦点
  • LeetCode HOT100 - 无重复字符的最长子串
  • 告别动画蓝图复杂连线!在UE5里用Control Rig模块化重构你的Foot IK系统(含GitHub工程对比)
  • Win11Debloat:Windows系统优化与隐私保护解决方案的技术实现
  • palera1n越狱工具终极指南:解锁A8-A11设备的iOS 15+系统限制
  • Phi-mini-MoE-instruct快速上手:3步启动http://localhost:7860对话界面
  • 2026年宁波短视频代运营与GEO搜索优化:5大服务商深度横评与选购指南 - 优质企业观察收录