HoRain云--缓存穿透、击穿、雪崩:核心区别与秒懂解决方案

缓存穿透、击穿、雪崩解析

  

🎬 HoRain云小助手个人主页

 🔥 个人专栏: 《Linux 系列教程》《c语言教程

⛺️生活的理想,就是为了理想的生活!


⛳️ 推荐

前些天发现了一个超棒的服务器购买网站,性价比超高,大内存超划算!忍不住分享一下给大家。点击跳转到网站。

专栏介绍

专栏名称

专栏介绍

《C语言》

本专栏主要撰写C干货内容和编程技巧,让大家从底层了解C,把更多的知识由抽象到简单通俗易懂。

《网络协议》

本专栏主要是注重从底层来给大家一步步剖析网络协议的奥秘,一起解密网络协议在运行中协议的基本运行机制!

《docker容器精解篇》

全面深入解析 docker 容器,从基础到进阶,涵盖原理、操作、实践案例,助您精通 docker。

《linux系列》

本专栏主要撰写Linux干货内容,从基础到进阶,知识由抽象到简单通俗易懂,帮你从新手小白到扫地僧。

《python 系列》

本专栏着重撰写Python相关的干货内容与编程技巧,助力大家从底层去认识Python,将更多复杂的知识由抽象转化为简单易懂的内容。

《试题库》

本专栏主要是发布一些考试和练习题库(涵盖软考、HCIE、HRCE、CCNA等)

目录

⛳️ 推荐

专栏介绍

🔍 深入理解每种情况

🕳️ 缓存穿透

💥 缓存击穿

❄️ 缓存雪崩

💎 总结与实践建议


img

缓存穿透、缓存击穿和缓存雪崩是缓存系统设计中三个关键又容易混淆的概念。它们都描述了缓存失效导致数据库压力激增的场景,但根源和应对策略各有侧重。为了让你快速抓住核心区别,下表提供了一个清晰的对比。

维度

缓存穿透

缓存击穿

缓存雪崩

问题本质

查询数据库中根本不存在的数据

某个热点数据在缓存中过期失效

大量缓存数据同一时间点大面积失效或缓存服务宕机

触发条件

查询不存在的数据(如非法ID、恶意攻击)

高并发访问的热点Key突然过期

1. 缓存设置了相同的过期时间
2. Redis缓存服务崩溃

缓存状态

缓存和数据库均此数据

缓存中数据过期,但数据库中存在

大量缓存数据集体过期或缓存服务不可用

对数据库影响

持续对数据库进行无效查询,可能耗尽连接资源

数据库瞬间承受针对单条数据的高并发查询

数据库瞬间承受针对大量不同数据的海量查询,极易被压垮

类比形象

试图寻找一个不存在的地址,每次都要查遍全网

一家极度火爆的店铺开门瞬间,人群蜂拥而入

城市中心大片区域同时停电,导致所有人群涌向少数几个发电站

核心解决方案

1. 布隆过滤器
2. 缓存空对象
3. 请求参数校验

1. 互斥锁
2. 逻辑过期
3. 热点数据永不过期

1. 设置随机过期时间
2. 构建高可用缓存集群
3. 数据预热
4. 服务降级与限流


🔍 深入理解每种情况

🕳️ 缓存穿透

这指的是查询一个根本不存在于数据库中的数据。由于缓存中自然也没有该数据,每次请求都会穿透缓存,直接落到数据库上。如果短时间内有大量此类恶意或无效的请求,数据库就会不堪重负 。

解决方案的核心思路是“拦截”和“标记”

  • 布隆过滤器:这是一种非常高效的数据结构,用于判断 “某样东西一定不存在”​ 。将所有可能存在的键预先存入布隆过滤器。在查询缓存前,先由此过滤器把关。如果过滤器说键不存在,那就直接返回,有效阻挡大部分非法请求 。需要注意的是,它可能会产生微小的误判(即判断某个存在的键为不存在,但概率极低),且通常不支持删除操作。

  • 缓存空对象:即使数据库查询结果为空,也将这个空结果(例如 null)进行缓存,并设置一个较短的过期时间。这样,后续相同的请求在缓存层就能拿到结果(哪怕是空结果),从而保护数据库。缺点是会占用少量缓存空间,并可能存在短时间的数据不一致(如果这个空值后来在数据库中有对应数据了)。

  • 严格的参数校验:在API入口处对请求参数进行合法性验证,例如检查ID是否为正整数、字段长度是否合规等,从源头拦截明显异常的请求 。

💥 缓存击穿

这种情况通常发生在某个访问极其频繁的热点数据上(比如明星八卦、爆款商品)。当这个热点Key在缓存中过期的瞬间,海量的并发请求会像洪水一样找不到缓存数据,于是全部涌向数据库,导致数据库瞬间压力巨大 。

解决方案的核心思路是“防止并发”和“避免失效”

  • 互斥锁:当缓存失效时,不是所有线程都去查询数据库。而是让只有一个线程(如通过Redis的 SETNX命令获取锁)有权去数据库加载数据并回填缓存。其他线程则等待锁释放后,直接读取缓存中的新数据。这能确保数据库面前只有一个查询请求 。

  • 逻辑过期:不依赖Redis的物理过期时间,而是在写入缓存时,在Value中封装一个逻辑过期时间。业务线程从缓存中拿到数据后,会检查是否逻辑过期。如果已过期,业务线程会尝试获取锁并异步更新缓存,同时先返回旧的、略微过期的数据。这种方式用户体验更好,但实现稍复杂,且存在短暂的数据不一致 。

  • 热点数据永不过期:对于极热点且不常变动的数据,可以直接设置为永不过期。然后通过后台任务或消息队列在数据变更时主动更新缓存。这种做法简单有效,但需要关注内存管理和数据更新的及时性 。

❄️ 缓存雪崩

这是最严重的一种情况,指的是大量的缓存数据在同一时刻集体失效,或者整个Redis缓存服务突然宕机。这会导致所有请求瞬间全部转向数据库,数据库几乎必定会因为无法处理如此高的并发而崩溃,引发“雪崩”式的连锁反应 。

解决方案的核心思路是“分散”和“冗余”

  • 设置随机过期时间:在为缓存数据设置过期时间时,不要设置相同的值。而是在基础值之上加上一个随机偏差值(例如,基础1小时,随机范围1-10分钟),让缓存键在不同时间点陆续失效,从而分散对数据库的冲击 。

  • 构建高可用缓存集群:通过Redis的哨兵模式或集群模式,避免因单点故障导致整个缓存服务不可用,提升系统的容灾能力 。

  • 数据预热:在系统高峰期来临前(或系统启动时),提前将主要的数据加载到缓存中,并设置好随机的过期时间,避免“冷启动”时的问题 。

  • 服务降级与限流:在雪崩真的发生时,作为最后的保护手段。可以启用熔断机制,直接返回默认值或友好提示,保护数据库不被冲垮。同时,使用限流工具(如令牌桶、漏桶算法)控制到达数据库的请求速率 。

💎 总结与实践建议

简单来说:

  • 缓存穿透是查没有的东西。

  • 缓存击穿是查一个刚丢了的热门东西。

  • 缓存雪崩一大堆东西同时丢了。

在实际项目中,这些策略往往需要根据业务场景组合使用。例如,针对热点数据,可以采用 互斥锁 + 随机过期时间​ 的策略;对于可能不存在的键查询,布隆过滤器​ 是第一道高效防线。理解它们的本质区别,能帮助你在系统设计初期就做出更合理的架构选择,构建出既高效又健壮的应用系统。

希望这个解释能帮你彻底分清这三者!如果你对某个解决方案的具体实现细节感兴趣,我们可以继续深入探讨。

❤️❤️❤️本人水平有限,如有纰漏,欢迎各位大佬评论批评指正!😄😄😄

💘💘💘如果觉得这篇文对你有帮助的话,也请给个点赞、收藏下吧,非常感谢!👍 👍 👍

🔥🔥🔥Stay Hungry Stay Foolish 道阻且长,行则将至,让我们一起加油吧!🌙🌙🌙

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值