大家好,我是小米,今年 31 岁,一个写代码写到凌晨、也被线上事故教育过无数次的普通 Java 程序员。
今天想跟你聊一个特别爱在 Java 社招面试里出现,而且特别容易在真实线上把你按在地上摩擦的问题:
Redis 缓存击穿,到底是什么?怎么解决?
为了让你真正记住这个东西,我不打算一上来就丢概念、丢术语。我想先讲一个故事。
故事开始:凌晨三点,数据库被“围殴”了
想象这样一个画面。你开了一家24 小时营业的网红奶茶店。生意最好的是一款「爆款招牌奶茶」,每天能卖上万杯。
为了不让后厨太累,你提前准备好了很多奶茶,放在前台的保温柜里。客人一来,直接从保温柜拿,快、稳、省事。
这个保温柜,就是 Redis 缓存。后厨,就是 数据库。
1、平时的日子,一切都很美好
- 客人点奶茶
- 前台一看:保温柜里有
- 直接交付
- 后厨继续悠闲地切珍珠、煮椰果
这,就是缓存命中的美好世界。
2、问题出在一个细节:这杯奶茶“过期了”
有一天凌晨三点,这杯爆款奶茶,在保温柜里放太久了,被系统自动清空了。偏偏就在这时:
- 外卖平台搞活动
- 推送了这杯奶茶
- 瞬间来了 几千个订单
前台一看:咦?保温柜里没有!于是发生了可怕的一幕:
- 几千个前台员工
- 同时冲进后厨
- 同时找厨师现做这同一杯奶茶
后厨当场崩溃。这,就是缓存击穿。
什么是缓存击穿?一句话讲清楚
在面试中,如果你只能说一句话,请记住这一句:
缓存击穿:缓存中没有,但数据库中有的数据,在高并发下被大量同时访问,导致所有请求直接打到数据库。
它有几个非常关键的特征:
- 数据 在数据库中是存在的
- 缓存中 刚好没有(通常是过期)
- 大量并发请求
- 查的是同一条数据
- 数据库压力瞬间暴增
缓存击穿 vs 缓存雪崩,别再说混了
很多同学在面试里,一说缓存击穿,面试官马上追一句:那缓存雪崩呢?
如果你这时开始支支吾吾,基本就要扣分了。我们用一个直观对比表,一眼就懂。
缓存击穿 vs 缓存雪崩对比表
一句话记忆法:
- 击穿:一个明星被围殴
- 雪崩:一整个城市停电
为什么缓存击穿这么危险?
很多人会问一句:不就是查一次数据库吗?有这么夸张?
问题就出在 “并发” 两个字上。
1、单线程思维 vs 并发现实
在你本地测试时:
- 缓存没了
- 查一次数据库
- 写回缓存
- 一切正常
但线上是:
- 1000 个线程
- 同一毫秒发现缓存为空
- 同时查数据库
- 同时回写缓存
数据库的 QPS 不是被“使用”,而是被围殴。
2、热点数据是“固定被打的点”
缓存击穿往往发生在:
- 商品详情
- 首页配置
- 活动规则
- 系统参数
这些数据的特点是:
- 访问量极高
- 数据变化不频繁
- 一旦失效,后果极大
解决方案一:热点数据,永远不过期
这是最简单、也是最常见的一种方案。
1、思路很直接
既然问题出在:热点数据过期, 那我就让它:永远不过期
2、具体怎么做?
Redis 中设置永不过期
不设置过期时间,数据就会一直存在。
3、那数据怎么更新?
很多人一听“永不过期”,马上慌了:那数据变了怎么办?
答案是:主动更新,而不是被动失效。
常见方式有:
- 后台管理系统更新商品时
- 直接更新数据库
- 同时更新 Redis 缓存
4、优点与缺点
解决方案二:互斥锁,挡住后面的洪水
如果你只说“永不过期”,在社招面试里是不够的。面试官更想听的是这个方案:互斥锁(Mutex Lock)
1、互斥锁的核心思想
一句话:同一时间,只允许一个线程去查数据库。
其他线程:
- 要么等待
- 要么直接返回旧值
- 要么稍后重试
2、用生活类比一下
还是奶茶店。发现保温柜空了之后:
- 店长立刻拉上一个 “正在补货,请稍等” 的牌子
- 只允许 一个员工 进后厨现做
- 其他人站在门口等
这,就是互斥。
基于 Redis 的互斥锁实现思路
实现互斥锁,核心就三步:
- 先查缓存
- 缓存没命中,尝试加锁
- 拿到锁的人查数据库、回写缓存、释放锁
1、伪代码流程
2、Java 示例代码(核心逻辑)
为什么要“双重检查”?
这是一个高频面试加分点。原因很简单:
- A 线程拿到锁,查数据库,写缓存
- B 线程在等锁
- A 释放锁
- B 拿到锁
- 如果不重新查缓存,就会重复查数据库
所以必须:查缓存 → 加锁 → 再查缓存
互斥锁方案的优缺点
我们用一张表总结一下。
面试中怎么回答,才像“干过活”的人?
如果你在面试中这样说:缓存击穿就是缓存没了打数据库,用互斥锁解决。
那基本只能算 “背过八股” 。更好的回答结构是:
- 先定义缓存击穿
- 区分缓存击穿和缓存雪崩
- 强调“热点数据 + 高并发”
- 讲两种解决方案
- 重点展开互斥锁 + 双重检查
- 提一句实际项目中的取舍
实战经验总结
最后,说点我自己踩过坑之后的结论。
- 不要迷信一种方案
- 热点数据少:直接永不过期
- 热点数据多:互斥锁
- 核心原则只有一个:宁可慢一点,也别把数据库打死
END
缓存击穿,本质上不是 Redis 的问题,而是:我们低估了并发的破坏力。
如果你能把这个故事、这个逻辑、这个代码,在面试里讲清楚,Java 社招里关于 Redis 的问题,你至少能赢 80%。
我是小米,一个喜欢分享技术的31岁程序员。如果你喜欢我的文章,欢迎关注我的微信公众号“软件求生”,获取更多技术干货!
好朋友们,我们下篇见。