
🎬 HoRain云小助手:个人主页
🔥 个人专栏: 《Linux 系列教程》《c语言教程》
⛺️生活的理想,就是为了理想的生活!
⛳️ 推荐
前些天发现了一个超棒的服务器购买网站,性价比超高,大内存超划算!忍不住分享一下给大家。点击跳转到网站。
专栏介绍
| 专栏名称 | 专栏介绍 |
| 本专栏主要撰写C干货内容和编程技巧,让大家从底层了解C,把更多的知识由抽象到简单通俗易懂。 | |
| 本专栏主要是注重从底层来给大家一步步剖析网络协议的奥秘,一起解密网络协议在运行中协议的基本运行机制! | |
| 全面深入解析 docker 容器,从基础到进阶,涵盖原理、操作、实践案例,助您精通 docker。 | |
| 本专栏主要撰写Linux干货内容,从基础到进阶,知识由抽象到简单通俗易懂,帮你从新手小白到扫地僧。 | |
| 本专栏着重撰写Python相关的干货内容与编程技巧,助力大家从底层去认识Python,将更多复杂的知识由抽象转化为简单易懂的内容。 | |
| 本专栏主要是发布一些考试和练习题库(涵盖软考、HCIE、HRCE、CCNA等) |
目录

缓存穿透、缓存击穿和缓存雪崩是缓存系统设计中三个关键又容易混淆的概念。它们都描述了缓存失效导致数据库压力激增的场景,但根源和应对策略各有侧重。为了让你快速抓住核心区别,下表提供了一个清晰的对比。
| 维度 | 缓存穿透 | 缓存击穿 | 缓存雪崩 |
|---|---|---|---|
| 问题本质 | 查询数据库中根本不存在的数据 | 某个热点数据在缓存中过期失效 | 大量缓存数据在同一时间点大面积失效或缓存服务宕机 |
| 触发条件 | 查询不存在的数据(如非法ID、恶意攻击) | 高并发访问的热点Key突然过期 | 1. 缓存设置了相同的过期时间 |
| 缓存状态 | 缓存和数据库均无此数据 | 缓存中数据过期,但数据库中存在 | 大量缓存数据集体过期或缓存服务不可用 |
| 对数据库影响 | 持续对数据库进行无效查询,可能耗尽连接资源 | 数据库瞬间承受针对单条数据的高并发查询 | 数据库瞬间承受针对大量不同数据的海量查询,极易被压垮 |
| 类比形象 | 试图寻找一个不存在的地址,每次都要查遍全网 | 一家极度火爆的店铺开门瞬间,人群蜂拥而入 | 城市中心大片区域同时停电,导致所有人群涌向少数几个发电站 |
| 核心解决方案 | 1. 布隆过滤器 | 1. 互斥锁 | 1. 设置随机过期时间 |
🔍 深入理解每种情况
🕳️ 缓存穿透
这指的是查询一个根本不存在于数据库中的数据。由于缓存中自然也没有该数据,每次请求都会穿透缓存,直接落到数据库上。如果短时间内有大量此类恶意或无效的请求,数据库就会不堪重负 。
解决方案的核心思路是“拦截”和“标记”:
- •
布隆过滤器:这是一种非常高效的数据结构,用于判断 “某样东西一定不存在” 。将所有可能存在的键预先存入布隆过滤器。在查询缓存前,先由此过滤器把关。如果过滤器说键不存在,那就直接返回,有效阻挡大部分非法请求 。需要注意的是,它可能会产生微小的误判(即判断某个存在的键为不存在,但概率极低),且通常不支持删除操作。
- •
缓存空对象:即使数据库查询结果为空,也将这个空结果(例如
null)进行缓存,并设置一个较短的过期时间。这样,后续相同的请求在缓存层就能拿到结果(哪怕是空结果),从而保护数据库。缺点是会占用少量缓存空间,并可能存在短时间的数据不一致(如果这个空值后来在数据库中有对应数据了)。 - •
严格的参数校验:在API入口处对请求参数进行合法性验证,例如检查ID是否为正整数、字段长度是否合规等,从源头拦截明显异常的请求 。
💥 缓存击穿
这种情况通常发生在某个访问极其频繁的热点数据上(比如明星八卦、爆款商品)。当这个热点Key在缓存中过期的瞬间,海量的并发请求会像洪水一样找不到缓存数据,于是全部涌向数据库,导致数据库瞬间压力巨大 。
解决方案的核心思路是“防止并发”和“避免失效”:
- •
互斥锁:当缓存失效时,不是所有线程都去查询数据库。而是让只有一个线程(如通过Redis的
SETNX命令获取锁)有权去数据库加载数据并回填缓存。其他线程则等待锁释放后,直接读取缓存中的新数据。这能确保数据库面前只有一个查询请求 。 - •
逻辑过期:不依赖Redis的物理过期时间,而是在写入缓存时,在Value中封装一个逻辑过期时间。业务线程从缓存中拿到数据后,会检查是否逻辑过期。如果已过期,业务线程会尝试获取锁并异步更新缓存,同时先返回旧的、略微过期的数据。这种方式用户体验更好,但实现稍复杂,且存在短暂的数据不一致 。
- •
热点数据永不过期:对于极热点且不常变动的数据,可以直接设置为永不过期。然后通过后台任务或消息队列在数据变更时主动更新缓存。这种做法简单有效,但需要关注内存管理和数据更新的及时性 。
❄️ 缓存雪崩
这是最严重的一种情况,指的是大量的缓存数据在同一时刻集体失效,或者整个Redis缓存服务突然宕机。这会导致所有请求瞬间全部转向数据库,数据库几乎必定会因为无法处理如此高的并发而崩溃,引发“雪崩”式的连锁反应 。
解决方案的核心思路是“分散”和“冗余”:
- •
设置随机过期时间:在为缓存数据设置过期时间时,不要设置相同的值。而是在基础值之上加上一个随机偏差值(例如,基础1小时,随机范围1-10分钟),让缓存键在不同时间点陆续失效,从而分散对数据库的冲击 。
- •
构建高可用缓存集群:通过Redis的哨兵模式或集群模式,避免因单点故障导致整个缓存服务不可用,提升系统的容灾能力 。
- •
数据预热:在系统高峰期来临前(或系统启动时),提前将主要的数据加载到缓存中,并设置好随机的过期时间,避免“冷启动”时的问题 。
- •
服务降级与限流:在雪崩真的发生时,作为最后的保护手段。可以启用熔断机制,直接返回默认值或友好提示,保护数据库不被冲垮。同时,使用限流工具(如令牌桶、漏桶算法)控制到达数据库的请求速率 。
💎 总结与实践建议
简单来说:
- •
缓存穿透是查没有的东西。
- •
缓存击穿是查一个刚丢了的热门东西。
- •
缓存雪崩是一大堆东西同时丢了。
在实际项目中,这些策略往往需要根据业务场景组合使用。例如,针对热点数据,可以采用 互斥锁 + 随机过期时间 的策略;对于可能不存在的键查询,布隆过滤器 是第一道高效防线。理解它们的本质区别,能帮助你在系统设计初期就做出更合理的架构选择,构建出既高效又健壮的应用系统。
希望这个解释能帮你彻底分清这三者!如果你对某个解决方案的具体实现细节感兴趣,我们可以继续深入探讨。
❤️❤️❤️本人水平有限,如有纰漏,欢迎各位大佬评论批评指正!😄😄😄
💘💘💘如果觉得这篇文对你有帮助的话,也请给个点赞、收藏下吧,非常感谢!👍 👍 👍
🔥🔥🔥Stay Hungry Stay Foolish 道阻且长,行则将至,让我们一起加油吧!🌙🌙🌙
缓存穿透、击穿、雪崩解析

1633

被折叠的 条评论
为什么被折叠?



