什么是缓存穿透,缓存击穿,缓存雪崩?他们有什么区别?怎么解决? 深入浅出Redis 缓存穿透、击穿、雪崩全解析 —— 从原理到防护加了缓存系统确实变快了但缓存也带来了三个经典问题穿透、击穿、雪崩。搞不清这三个孪生兄弟高并发下数据库分分钟被打垮。一文讲透 给足解决方案。目录一、为什么要用缓存二、缓存穿透三、缓存击穿四、缓存雪崩五、三大问题对比六、防御体系与最佳实践七、总结一、为什么要用缓存1.1 缓存的存在意义在高并发场景下数据库扛不住每秒上万次的访问于是引入Redis 缓存挡在前面客户端 → Redis 缓存读快扛高并发 → 数据库兜底扛持久化 │ │ └── 命中直接返回 ────────────────────┘存储速度容量职责Redis微秒级有限内存挡流量快速返回数据库毫秒级大磁盘持久化兜底1.2 缓存的三种典型路径路径场景风险读缓存命中数据在缓存中无读未命中数据不在缓存中查库回填缓存穿透缓存集中失效大量 key 同时过期缓存雪崩核心观点缓存是挡箭牌但挡箭牌本身也会破 —— 穿透、击穿、雪崩就是它的三个破绽。二、缓存穿透2.1 什么是缓存穿透缓存穿透指查询缓存和数据库都不存在的数据。因为查不到缓存永远不会被写入每次请求都直接打到数据库。恶意请求: 查 id-1 / id不存在的商品 ├─▶ Redis: 没有永不被写入 ├─▶ DB: 也没有 → 直接压垮数据库场景说明恶意攻击用不存在的 id 批量刷接口业务 bug前端传了非法参数2.2 解决方案方案原理适用缓存空值查不到也缓存设短 TTL如 60s通用兜底布隆过滤器不存在直接拦截不再查库大量非法 key参数校验非法 id负数、超长直接拒绝前置拦截// 方案一缓存空值通用兜底Objectvredis.get(key);if(vnull){Objectdbdb.query(key);if(dbnull){redis.set(key,EMPTY,60);// 空值也缓存 60 秒}else{redis.set(key,db,3600);}}一句话穿透打的是缓存里永远没有的 key解决办法就是让它有空值或别让它进来布隆/校验。三、缓存击穿3.1 什么是缓存击穿缓存击穿指某个热点 key在过期瞬间大量请求同时涌入缓存失效、全部穿透到数据库。热点 key 秒杀商品 过期的那 1 秒 ├─▶ 1000 个请求同时发现缓存没了 ├─▶ 1000 个请求同时打数据库 └─▶ 数据库瞬间崩掉⚠️ 区别穿透是根本没有击穿是恰好过期对象是热点 key。3.2 解决方案方案原理特点互斥锁只让一个请求去查库其余等待简单有效有阻塞逻辑过期值里带过期时间异步刷新无阻塞实现略复杂永不失效 后台更新热数据不设 TTL定时刷新最稳需管理刷新任务// 方案互斥锁只放一个线程去查库Stringvredis.get(key);if(vnull){Stringlockredis.setnx(lockKey,1,3);// 抢锁if(lock){try{vdb.query(key);redis.set(key,v,3600);}finally{redis.del(lockKey);}}else{Thread.sleep(50);vredis.get(key);// 等拿到锁的线程写回}}一句话击穿打的是单个热点 key 过期核心思路是只让一个请求重建缓存。四、缓存雪崩4.1 什么是缓存雪崩缓存雪崩指大量 key 同时失效或 Redis 宕机所有请求一起打到数据库数据库被压垮甚至引发连锁故障。大量 key 同一秒过期 / Redis 挂了 ├─▶ 海量请求同时穿透到数据库 ├─▶ 数据库超负荷 - 宕机 └─▶ 连锁反应 - 系统雪崩触发原因说明TTL 相同同一批 key 设了相同过期时间Redis 宕机缓存整体不可用缓存重启重启后缓存为空被瞬间打爆4.2 解决方案方案原理TTL 加随机值TTL random(0~300s)打散过期时间多级缓存本地缓存Caffeine Redis层层兜底Redis 集群 持久化高可用宕机自动切换服务降级 限流数据库撑不住时降级返回默认值// 方案一TTL 打散核心intttl3600random.nextInt(300);// 3600~3900 随机redis.set(key,value,ttl);一句话雪崩打的是一批 key 同时过期或缓存整体不可用核心思路是打散过期时间 高可用 降级兜底。五、三大问题对比维度缓存穿透缓存击穿缓存雪崩对象不存在的 key单个热点 key大量 key / 整个缓存本质缓存里永远没有缓存恰好过期缓存批量失效触发恶意/非法请求热点 key 过期的瞬间TTL 相同 / Redis 宕机危害打数据库打数据库打挂数据库缓解空值缓存 / 布隆过滤器互斥锁 / 逻辑过期随机 TTL / 集群 / 降级记忆口诀穿透 不存在击穿 单点过期雪崩 批量失效。六、防御体系与最佳实践6.1 四层防御第1层 前置拦截: 参数校验 布隆过滤器 第2层 缓存策略: 空值缓存 随机 TTL 互斥锁 第3层 高可用: Redis 集群 持久化 多级缓存 第4层 兜底降级: 限流 返回默认值 熔断层级手段防的是① 前置拦截参数校验、布隆过滤器穿透② 缓存策略空值缓存、随机 TTL、互斥锁穿透/击穿/雪崩③ 高可用集群、持久化、多级缓存雪崩④ 兜底降级限流、降级、熔断全部兜底6.2 实战清单场景组合方案商品查询空值缓存 随机 TTL 互斥锁秒杀热点逻辑过期 永不失效 后台刷新活动列表TTL 打散 本地二级缓存全局兜底布隆过滤器 限流降级⚠️ 常见误区只加 Redis 不做集群、空值缓存 TTL 太长、热点 key 忘了互斥锁 —— 都是高并发事故的温床。七、总结7.1 核心要点穿透查不存在的 key缓存永远为空 → 空值缓存 布隆过滤器击穿热点 key 恰好过期并发打库 → 互斥锁 逻辑过期雪崩大量 key 同时失效 / Redis 宕机 → 随机 TTL 集群 降级记忆口诀穿透不存在、击穿单点过期、雪崩批量失效四层防御前置拦截 → 缓存策略 → 高可用 → 兜底降级7.2 最后的话核心观点三大问题的本质都是缓存挡不住请求解法殊途同归 —— 要么让缓存总有值要么让数据库少受击。提前布防才能让缓存真正成为系统的盾牌。记住面试必问三者的区别与解决方案必须脱口而出开发必做所有读接口都要考虑穿透与击穿进阶方向Redisson 分布式锁、本地缓存 Caffeine、缓存一致性双写/延迟删除参考资料Redis 官方文档 —— Keyspace Notifications 与缓存策略《Redis 设计与实现》黄健宏《深入理解高并发编程》JD 技术内幕阿里云 Redis 最佳实践文档标签Redis, 缓存穿透, 缓存击穿, 缓存雪崩, 高并发, 面试题