缓存三兄弟穿透、击穿、雪崩:我们线上数据库被打挂的那晚,3 个方案只救活了 1 个
上个月大促前做一次压测我把商品详情服务的 Redis 缓存整个清空想验证无缓存冷启动的数据库承压。结果脚本跑起来第 8 分钟DB 连接池告警、慢查询堆积MySQL 的 CPU 直接打到 100%。那一刻我才意识到缓存三兄弟——穿透、击穿、雪崩——不是三个名词是三种能把数据库直接送走的真实路径。这篇用我们那次的翻车现场把三种问题和对应的解法讲透并附上能直接抄的 Java 代码。先分清三兄弟到底差在哪很多人把缓存失效笼统叫缓存击穿其实三者触发条件完全不同穿透查一个数据库里根本不存在的 key比如 id-1 或已被删除的订单。请求每次都绕过缓存直接打到 DB缓存形同虚设。击穿某个热点 key 在过期瞬间恰好被高并发集中访问。大量请求同时发现缓存没了一起涌向 DB 重建缓存。雪崩大量 key 在同一时间段集中过期或 Redis 实例挂掉导致请求像雪崩一样全部砸向 DB。三者共同点只有一条请求最终落到了数据库。区别在为什么会落——穿透是 key 本就不该查 DB击穿是单点过期并发雪崩是多点同时失效。解法和代价也完全不同下面分开讲。缓存穿透空值和布隆过滤器两道闸穿透的本质是查不存在的数据。最简单的错误写法是直接查缓存、没有就查库// 错误示范穿透的源头 public Product getProduct(long id) { String cache redis.get(product: id); // 1. 缓存里没有 if (cache ! null) return parse(cache); Product p productMapper.selectById(id); // 2. 直接查库——id-1 也查 if (p ! null) redis.set(product: id, toJson(p), 300); // 3. 查到才回写 return p; // 4. 查不到就返回 null缓存依旧空 }逐行第 1 行查缓存不存在返回 null第 2 行不管 id 存不存在都查库攻击者用 id-1 或随机大 id 狂打DB 被无意义的查询淹没第 3 行只有查到才回写所以查不到的 key 永远不会进缓存下一次同样的非法请求还是打到 DB。这就是穿透——缓存对非法 key 没有防御能力。解法一缓存空值。查到 null 也写一份短过期比如 60 秒的空标记让后续请求在缓存层被挡住。// 解法一空值缓存 public Product getProductSafe(long id) { String cache redis.get(product: id); if (cache ! null) { return NULL.equals(cache) ? null : parse(cache); // 1. 空标记直接返回 null } Product p productMapper.selectById(id); if (p ! null) { redis.set(product: id, toJson(p), 300); // 2. 真值回写 } else { redis.set(product: id, NULL, 60); // 3. 空标记短过期防误删后长期穿透 } return p; }逐行第 1 行如果缓存是 NULL 标记直接返回不再查库第 3 行把查不到的结果也写入缓存60 秒过期是为了避免数据其实刚插入、却被空标记挡住的一致性问题。空值缓存成本极低但有个隐患如果攻击者用海量不同的非法 id缓存里会堆满无用的空标记浪费内存。解法二布隆过滤器拦在缓存之前。我们最终用的是 Redisson 的RBloomFilter在写入真实数据时同步加进过滤器查询前先问过滤器这个 id 可能存在吗。// 解法二布隆过滤器前置拦截 RBloomFilterLong bf redisson.getBloomFilter(product:ids); bf.tryInit(1000000L, 0.01); // 1. 预计 100 万元素误判率 1% public Product getProductWithBf(long id) { if (!bf.contains(id)) return null; // 2. 一定不存在直接挡住 // 3. 可能存在有误判可能走空值缓存 查库流程 return getProductSafe(id); }逐行第 1 行tryInit设定容量和误判率布隆过滤器用位数组多个哈希函数判断一定不存在/可能存在第 2 行返回 false 表示一定不存在这一步能挡掉绝大多数非法请求缓存层几乎碰不到穿透流量。注意布隆过滤器有误判可能说存在但其实没有所以第 3 行还要接空值缓存兜底。我们组合布隆过滤器 空值缓存后那次压测里 DB 的无效查询从每秒 4 万降到个位数。缓存击穿单点热 key 过期的并发重建击穿发生在热点 key 过期那一瞬。比如首页爆款商品缓存 300 秒过期瞬间几百个并发请求同时发现缓存没了一起查库重建——DB 被一拥而上的查询打穿。解法一互斥锁。只有一个线程能去查库重建其余线程等待或返回旧值。// 解法一分布式互斥锁重建击穿 private static final String LOCK_PREFIX lock:product:; public Product getWithLock(long id) { String cache redis.get(product: id); if (cache ! null) return parse(cache); // 1. 缓存还在直接返回 String lockKey LOCK_PREFIX id; String uuid UUID.randomUUID().toString(); try { boolean locked redis.setnx(lockKey, uuid, 30); // 2. 抢锁30 秒自动过期防死锁 if (locked) { Product p productMapper.selectById(id); // 3. 只有抢到锁的线程查库 redis.set(product: id, toJson(p), 300); // 4. 重建缓存 return p; } else { Thread.sleep(50); // 5. 没抢到短暂等待后重试 return getWithLock(id); } } finally { if (uuid.equals(redis.get(lockKey))) redis.del(lockKey); // 6. 只删自己的锁 } }逐行第 2 行setnx抢锁用唯一 uuid 防止误删别人的锁第 3 行只有持锁线程查库把几百个并发查库压成1 个查库第 5 行没抢到的线程睡 50 毫秒重试拿到刚建好的缓存第 6 行finally里校验 uuid 才删锁避免把别人刚抢到的锁删了。这是我们线上主用方案简单可靠。解法二逻辑过期不设物理 TTL值里带过期时间。适合数据可以短暂不一致、但不能阻塞的场景比如排行榜。它的好处是不用抢锁坏处是重建期间可能返回旧数据。// 解法二逻辑过期不阻塞返回旧值 class LogicalValue { Object data; long expireAt; } public Product getLogical(long id) { LogicalValue v parse(redis.get(product: id)); if (v null) return getWithLock(id); // 1. 真没有才走锁重建 if (v.expireAt System.currentTimeMillis()) return (Product) v.data; // 2. 没过期返回 // 3. 逻辑过期开新线程重建当前请求返回旧值 executor.submit(() - { if (redis.setnx(rebuild: id, 1, 20)) redis.set(product: id, wrap(productMapper.selectById(id))); }); return (Product) v.data; }逐行第 2 行没过期直接返回第 3 行过期了不阻塞用户而是异步提交重建任务、当前请求仍然返回旧数据。代价是重建完成前用户看到的是旧值——对价格、库存这类强一致字段我们不这么做只用在对一致性要求低的展示数据上。缓存雪崩别让 key 一起死雪崩是大量 key 同时失效。最常见诱因是统一设了相同 TTL比如全部 300 秒到点一起过期。解法核心是打散过期时间 兜底。// 解法TTL 加随机抖动避免集中过期 int base 300; // 1. 基础 300 秒 int jitter new Random().nextInt(120); // 2. 0~120 秒随机抖动 redis.set(product: id, value, base jitter); // 3. 实际过期 300~420 秒错峰逐行第 2 行生成 0 到 120 秒的随机值第 3 行每个 key 的过期时间在基础值上浮动把同一时刻集体过期拆成几分钟内陆续过期DB 不会瞬间承压。除此之外雪崩还有两个工程手段其一是多级缓存本地 Caffeine RedisRedis 挂了本地还能扛一部分其二是熔断降级DB 压力过大时直接返回默认页或走限流别让请求无脑打到库里。我们那晚翻车的复盘回到开头的压测事故。根因是脚本清缓存后几千并发同时查不存在的商品 id穿透 部分热点 key 过期击穿三兄弟在同一时间窗口叠满DB 连接池被占满。我们当晚的修复顺序先上一道布隆过滤器把非法 id 在网关层挡掉 90% 的穿透流量热点 key 加互斥锁重建击穿的并发查库压成单查TTL 全部加随机抖动并给核心接口加 Sentinel 熔断DB 压力大时直接降级。救活的是第 1 步——布隆过滤器一上DB QPS 从 4 万掉到 3000 以内雪崩和击穿的压力随之瓦解。空值缓存和逻辑过期我们在非核心接口上才用核心交易链路只用锁重建 多级缓存因为那里不能接受返回旧值。我的取舍别把三个问题用一套方案糊弄我的观点很明确穿透用布隆过滤器 空值缓存组合击穿用互斥锁优先于逻辑过期雪崩用TTL 抖动 熔断。不建议为了省事只上一道空值缓存应对所有场景——空值缓存挡不住雪崩key 是真存在的只是同时过期也挡不住高误判场景下的内存浪费。我更不建议在交易链路上用逻辑过期旧值返回引发的差错比缓存击穿本身更难查。方案选型就一句话先看请求为什么落到 DB再对症下药的分别处理而不是找一个万能缓存框架指望它全包。思考题假设你的热点 key 缓存时间设 300 秒但数据每 10 秒就会变一次比如实时库存。互斥锁重建和逻辑过期两种方案哪种更不合适为什么如果要兼顾不击穿和数据不太旧你会怎么组合写在最后缓存三兄弟不是考试题是三种能把数据库打挂的真实路径。穿透是查不存在的数据、击穿是单点过期并发、雪崩是多点同时失效。我们那晚的教训是别等压测才想起它们上线前就该按请求为什么落 DB把三道防线布好。布隆过滤器挡穿透、互斥锁挡击穿、TTL 抖动加熔断挡雪崩三道闸各管一摊DB 才稳得住。

相关新闻

物联网安全:SE050与PIC18F47K40硬件级防护方案

物联网安全:SE050与PIC18F47K40硬件级防护方案

1. 物联网安全现状与SE050的定位 在当今物联网设备爆炸式增长的环境下,安全问题已成为制约行业发展的关键瓶颈。根据行业统计,超过70%的物联网设备存在不同程度的安全隐患,从简单的数据泄露到关键基础设施被控,安全事件频发暴露出…

2026/7/29 15:39:12阅读更多 →
独立开发者如何用 AI 做用户研究:从「问卷」到「行为理解」

独立开发者如何用 AI 做用户研究:从「问卷」到「行为理解」

独立开发者如何用 AI 做用户研究:从「问卷」到「行为理解」 一、独立开发者的用户研究困境 独立开发者在做用户研究时,面临一个和结构化的产品团队完全不同的困境:没有专门的研究资源,但需要做研究;没有大量的用户访谈…

2026/7/29 15:39:12阅读更多 →
基于mPython与百度语音API的嵌入式语音交互项目实战

基于mPython与百度语音API的嵌入式语音交互项目实战

1. 从“Hello World”到“开口说话”:为什么选择mPython与百度语音 如果你玩过Micro:bit、掌控板这类开源硬件,或者接触过图形化编程,那你对mPython这个国产的图形化编程软件应该不陌生。它让编程变得像搭积木一样简单,尤其适合教…

2026/7/29 15:39:12阅读更多 →
小白程序员转型AI Agent后端工程师的进阶学习路线图(含面试核心考点)

小白程序员转型AI Agent后端工程师的进阶学习路线图(含面试核心考点)

本文以北京1-3年薪资20-40K的AI Agent后端开发工程师JD为例,拆解企业对AI后端的核心要求,指出面试重点在于工程化能力与落地能力而非纯算法。文章详细阐述了四大核心能力模块:企业级Agent架构研发、RAGAgent工程化落地、复杂系统架构及后端性…

2026/7/29 17:09:35阅读更多 →
程序员小白必看:6大核心支柱彻底搞懂 Agent 内部运作原理

程序员小白必看:6大核心支柱彻底搞懂 Agent 内部运作原理

本文深入解析了 Agent 的六大核心支柱:Agent Loop、记忆系统、工具系统、Context Engine、推理引擎和上下文压缩。通过底层原理讲解,帮助读者理解 Agent 是如何运作的,以及为什么这样设计。文中穿插了 Hermes、OpenClaw 等具体 Agent 的实现案…

2026/7/29 17:09:35阅读更多 →
MCP 到底是什么?

MCP 到底是什么?

大模型会回答问题,但想让 AI 真正读取数据、调用工具、连接业务系统,就需要一套统一的连接方式。 MCP,全称 Model Context Protocol,可以理解为 AI 连接外部世界的通用接口。 它不是大模型,也不是 Agent 框架&#xff…

2026/7/29 17:09:35阅读更多 →
基于ESP32-S3的MicroByte复古掌机:从硬件设计到模拟器集成的全流程实战

基于ESP32-S3的MicroByte复古掌机:从硬件设计到模拟器集成的全流程实战

1. 项目缘起:为什么是 ESP32 和 MicroByte? 几年前,我在整理旧物时翻出了一台老旧的 Game Boy,开机后那熟悉的像素画面和略显生涩的按键声,瞬间把我拉回了童年。但兴奋之余,一个问题冒了出来:这…

2026/7/29 17:09:35阅读更多 →
多源异构通信数据统一识别:运营商分类分级平台关键技术与落地成

多源异构通信数据统一识别:运营商分类分级平台关键技术与落地成

云网融合、物联网、政企数字化业务持续扩张,运营商内部形成海量、多形态、跨域分散的异构通信数据,涵盖结构化业务库、半结构化信令日志、非结构化客服录音、基站测绘文件、离线工单文档等多类资产。传统分类分级工具仅适配单一数据库,无法统…

2026/7/29 17:09:35阅读更多 →
如何轻松在iOS设备上安装TrollStore:TrollInstallerX完整指南

如何轻松在iOS设备上安装TrollStore:TrollInstallerX完整指南

如何轻松在iOS设备上安装TrollStore:TrollInstallerX完整指南 【免费下载链接】TrollInstallerX A TrollStore installer for iOS 14.0 - 16.6.1 项目地址: https://gitcode.com/gh_mirrors/tr/TrollInstallerX 你是否厌倦了iOS系统的应用安装限制&#xff1…

2026/7/29 17:07:35阅读更多 →
覆盖国产 + 海外 + 开源模型,OpenClaw 2.7.9 Windows/Mac 双端部署详解

覆盖国产 + 海外 + 开源模型,OpenClaw 2.7.9 Windows/Mac 双端部署详解

🔹 工具基础介绍 OpenClaw 是开源生态中一款实用性较强的本地智能工具,凭借本地离线运行、可视化图形操作和任务自动化三大核心特性,赢得了众多用户的青睐。与普通在线对话AI工具不同,它属于能够直接操控本机软硬件的智能数字员工…

2026/7/29 9:47:45阅读更多 →
伺服阀焊完微漏毁整机?精密激光焊接三关锁住高压

伺服阀焊完微漏毁整机?精密激光焊接三关锁住高压

所谓液压伺服阀体的精密激光焊接,是用激光束对阀座壳体(通常为不锈钢或铝合金)进行密封焊接,使阀体在21-35MPa的高压液压油或压缩气体中长期运行而不发生介质泄漏。液压伺服阀是高端液压系统的"大脑"。从航空航天飞行控…

2026/7/29 7:00:19阅读更多 →
D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南

D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南

D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南 【免费下载链接】d2dx D2DX is a complete solution to make Diablo II run well on modern PCs, with high fps and better resolutions. 项目地址: https://gitcode.com/gh_mirrors/d2/d2dx 你是否还在…

2026/7/29 7:58:51阅读更多 →
28. Agent 执行到一半想暂停?用 interrupt 给它设个“关卡“!

28. Agent 执行到一半想暂停?用 interrupt 给它设个“关卡“!

28. Agent 执行到一半想暂停?用 interrupt 给它设个“关卡“! 在构建复杂的 Agent 系统时,我们经常会遇到这样的场景:Agent 正在执行一个多步骤的任务,比如“下单购买商品”,但执行到一半时,我们…

2026/7/29 0:01:46阅读更多 →
自律同行,突破无界!NANK南卡正式官宣曾舜晞成为品牌代言人

自律同行,突破无界!NANK南卡正式官宣曾舜晞成为品牌代言人

近日,国际专注开放式技术研发的声学品牌Nank南卡,正式官宣实力艺人曾舜晞担任品牌代言人。消息一经发出便轰动全网。为什么耳机品牌不选择流量明星、老牌歌手?而且是选择曾舜晞?让我们一起来探索一下!比起短期的流量&a…

2026/7/29 0:01:46阅读更多 →
【RT-DETR多模态创新改进】CVPR 2025 | 独家特征融合创新改进篇 | 引入RLAB残差线性注意力模块,有效融合并强调多尺度特征,多种改进点,适合红外与可见光融合目标检测任务,有效涨点

【RT-DETR多模态创新改进】CVPR 2025 | 独家特征融合创新改进篇 | 引入RLAB残差线性注意力模块,有效融合并强调多尺度特征,多种改进点,适合红外与可见光融合目标检测任务,有效涨点

一、本文介绍 🔥本文在RT-DETR多模态融合目标检测中引入RLAB残差线性注意力模块,可在不同模态特征交互阶段进行多次残差细化,使可见光、红外等特征在尺度、语义和空间位置上更好对齐;随后将细化特征与解码器输出拼接并生成Q、K、V,通过线性注意力自适应强化关键通道、目…

2026/7/29 0:01:46阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/28 20:22:24阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/29 4:31:51阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/29 14:26:42阅读更多 →