缓存穿透解决:程序员必会的三大实战策略

2025年Java面试宝典抢先领:
👉 点击下载
提取码:9b3g (建议保存到个人网盘)
什么是缓存穿透?
缓存穿透简单说就是大量恶意请求直接绕过缓存,疯狂捶打数据库。比如用不存在的ID(负数、超大数值)频繁查询,导致缓存形同虚设,数据库压力暴增甚至宕机。这在技术面试中绝对是高频考点!
解决缓存穿透的三大核心方案
✅ 方案一:缓存空对象(Cache Null)
当数据库查不到数据时,在缓存里存个空值(如null)并设置短过期时间。后续相同请求直接返回空值,避免重复穿透。
请求流程:
1. 查缓存 → 无数据
2. 查数据库 → 无数据
3. 缓存中存入 Key: null (TTL=5分钟)
4. 后续相同请求直接返回缓存中的null
关键点:
- 空值过期时间建议 2-5分钟,防止垃圾数据堆积
- 需配合布隆过滤器防随机Key攻击(下文细说)
✅ 方案二:布隆过滤器(Bloom Filter)
在缓存前加一层内存级过滤器,用极小的空间快速判断Key是否存在。原理如下:

工作流程:
1. 请求先过布隆过滤器
2. 若过滤器说"不存在" → 直接拦截
3. 若说"可能存在" → 继续查缓存/DB
为什么能防穿透?
攻击者生成的随机Key在过滤器中必然返回"不存在",直接挡在缓存层之外!
注意事项:
- 有误判率(可通过增加哈希函数降低)
- 需预热:系统启动时加载所有有效Key
- 推荐Guava或Redis4.0+模块实现
✅ 方案三:互斥锁(Mutex Lock)
当多个并发请求查询同个空Key时,用分布式锁保证只有一个请求访问数据库,其它请求等待后直接读缓存。
典型流程:
1. 线程A查缓存 → 未命中
2. 获取分布式锁(如Redis SETNX)
3. 查数据库 → 为空 → 缓存空值
4. 释放锁
5. 线程B等待锁释放后直接读缓存空值
适用场景:
- 热点Key突发穿透
- 对数据一致性要求高的业务
如何选择解决方案?
| 方案 | 适用场景 | 注意事项 | |--------------------|---------------------------------|-------------------------| | 缓存空对象 | 数据变化不频繁的业务 | 需定期清理无效Key | | 布隆过滤器 | 海量数据+防随机攻击(强推!) | 需预热,存在误判率 | | 互斥锁 | 热点Key突发请求 | 增加系统复杂度 |
面试实战技巧
当面试官问:"如何解决缓存穿透?" 建议按这个逻辑回答:
-
先明确定义
"缓存穿透是指查询不存在的数据,绕过缓存直击数据库,可能引发雪崩" -
分层递进解决方案
"常用三种方式:- 基础方案:缓存空值并设短过期时间
- 加强方案:布隆过滤器预筛非法Key
- 补充方案:互斥锁避免重复查库"
-
强调工程细节
"生产环境推荐组合使用,比如:布隆过滤器+缓存空对象。同时要对空值缓存设置最大数量限制,防止内存溢出"
🔥 程序员福利时间
如果你正在准备Java面试,面试鸭返利网 可享 25元返利开通会员!涵盖所有大厂真题+技术架构解析,点击注册立省↓
常见面试陷阱
-
缓存穿透 vs 缓存雪崩 vs 缓存击穿
- 穿透:查不存在的数据
- 雪崩:大量缓存同时失效
- 击穿:某个热点Key失效后并发请求压垮DB
-
布隆过滤器能否删除数据?
→ 不能!删除元素会导致其它Key判断失效。解决方案:- 用Counting Bloom Filter(计数过滤器)
- 重建新过滤器后切换
-
空值缓存导致数据不一致怎么办?
→ 在数据库写入时主动更新缓存(删除空值标记)
最后的小提醒
遇到要求"设计高并发系统"的面试题,一定要主动抛出缓存穿透解决方案!这能直接体现你的实战经验深度。建议把本文策略整理到你的知识库,随时调取~
(完)



