一句话缓存穿透是“查不存在的数据”缓存击穿是“单个热点 key 过期”缓存雪崩是“大量 key 同时失效或 Redis 整体不可用”。三者都会让请求绕过缓存打到数据库但触发范围和治理手段不同。1. 三者区别问题核心特征典型结果关键词缓存穿透查不存在的数据每次都绕过缓存打 DB不存在的 key缓存击穿单个热点 key 过期大量并发同时查 DB热点 key 过期瞬间缓存雪崩大量 key 同时失效或 Redis 故障大面积请求打 DB大范围失效面试时先讲区别再讲方案不能只背“穿透击穿雪崩都加锁”。2. 缓存穿透正常请求 查缓存 → 没有 → 查 DB → 查到数据 → 写缓存 穿透请求 查缓存 → 没有 → 查 DB → DB 也没有 → 不写缓存 下次同样请求 → 继续查 DB如果有人不断请求不存在的userId-1、orderId999999999这些请求永远命不中缓存会直接压数据库。解决方案① 布隆过滤器 请求先经过 Bloom Filter 如果判断一定不存在 → 直接拦截 如果判断可能存在 → 再查缓存 / DB ② 缓存空值 DB 查不到也写入缓存例如 key - null 设置较短 TTL例如 1-5 分钟布隆过滤器适合数据量大、恶意请求多的场景缓存空值实现简单适合业务规模较小或不存在 key 数量可控的场景。3. 布隆过滤器原理插入 key 经过多个 hash 函数 映射到位数组多个位置 把这些位置置为 1 查询 key 再经过同样的 hash 函数 检查对应位置 只要有一个位置是 0 → 一定不存在 全部都是 1 → 可能存在布隆过滤器的关键特性说“不存在”一定准确 说“存在”可能误判它不会误杀真实存在的数据但可能放过少量不存在的数据继续查 DB。这个误判率可以通过位数组大小和 hash 函数数量控制。4. 缓存击穿热点商品 keyproduct:1001 平时大量请求都命中 Redis 某一刻 key 过期 1000 个请求同时进来 Redis 都没查到 1000 个请求同时查 DB缓存击穿的本质是单个热点 key 在过期瞬间被高并发打穿。解决方案① 互斥锁重建缓存 只允许一个线程查 DB 并回写缓存 其他线程等待、重试、返回旧值或降级 ② 逻辑过期 缓存不设置物理过期时间 value 里存 expireTime 发现逻辑过期后异步刷新旧值继续可读 ③ 热点 key 不过期 适合配置、榜单、考试规则等读多写少数据 通过主动更新或删除保证最终一致互斥锁适合要求数据新鲜度较高的场景逻辑过期适合允许短时间读旧值、但不能让请求打爆 DB 的场景。5. 互斥锁重建缓存流程查缓存 ↓ 缓存未命中 ↓ 尝试加锁 ↓ 加锁成功 double check 缓存 查 DB 写缓存 释放锁 ↓ 加锁失败 短暂等待 重试缓存 / 返回旧值 / 降级为什么要 double check线程 A 拿锁后查 DB 并写回缓存 线程 B 等到锁后如果不再查一次缓存就会重复查 DB 所以拿锁后要再次检查缓存是否已经被别人重建6. 缓存雪崩缓存雪崩有两类① 大量 key 同时过期 比如批量导入缓存时都设置 24 小时 TTL 24 小时后同一时间集中失效 ② Redis 整体不可用 Redis 宕机、网络异常、集群故障 所有请求都绕过缓存打 DB解决方案① TTL 加随机值 expire baseTTL random(0, 300s) 避免大量 key 同时过期 ② Redis 高可用 主从、哨兵、Cluster ③ 本地缓存兜底 Caffeine 缓存热点配置或核心只读数据 ④ 限流 / 降级 / 熔断 保护 DB不让故障继续放大雪崩治理不能只靠应用代码必须把 Redis 高可用、降级策略和数据库保护一起考虑。7. 面试高频追问缓存穿透为什么可以缓存空值因为 DB 查不到的数据如果不缓存下次还会继续查 DB。 缓存 null 后同一个不存在 key 会直接命中 Redis避免反复打 DB。 但空值 TTL 要短避免真实数据后续创建出来后用户长时间读到空结果。逻辑过期和互斥锁怎么选对数据新鲜度要求高优先互斥锁等一个线程重建后再返回。 对可用性要求更高、允许短暂旧值优先逻辑过期先返回旧值再异步刷新。面试回答模板“缓存穿透、击穿、雪崩都表现为请求绕过缓存打到数据库但触发原因不同。 缓存穿透是查不存在的数据缓存和数据库都没有解决方案是布隆过滤器 前置拦截或者缓存空值并设置较短 TTL。 缓存击穿是单个热点 key 过期大量并发请求同时打到数据库。可以用互斥锁 只让一个线程重建缓存也可以用逻辑过期或热点 key 不过期避免过期瞬间 把数据库打穿。 缓存雪崩是大量 key 同时过期或者 Redis 整体不可用导致大面积请求打 DB。 解决方案包括 TTL 加随机值、Redis 主从哨兵或 Cluster、本地缓存兜底 再配合限流、降级、熔断保护数据库。”
缓存穿透、击穿、雪崩
一句话缓存穿透是“查不存在的数据”缓存击穿是“单个热点 key 过期”缓存雪崩是“大量 key 同时失效或 Redis 整体不可用”。三者都会让请求绕过缓存打到数据库但触发范围和治理手段不同。1. 三者区别问题核心特征典型结果关键词缓存穿透查不存在的数据每次都绕过缓存打 DB不存在的 key缓存击穿单个热点 key 过期大量并发同时查 DB热点 key 过期瞬间缓存雪崩大量 key 同时失效或 Redis 故障大面积请求打 DB大范围失效面试时先讲区别再讲方案不能只背“穿透击穿雪崩都加锁”。2. 缓存穿透正常请求 查缓存 → 没有 → 查 DB → 查到数据 → 写缓存 穿透请求 查缓存 → 没有 → 查 DB → DB 也没有 → 不写缓存 下次同样请求 → 继续查 DB如果有人不断请求不存在的userId-1、orderId999999999这些请求永远命不中缓存会直接压数据库。解决方案① 布隆过滤器 请求先经过 Bloom Filter 如果判断一定不存在 → 直接拦截 如果判断可能存在 → 再查缓存 / DB ② 缓存空值 DB 查不到也写入缓存例如 key - null 设置较短 TTL例如 1-5 分钟布隆过滤器适合数据量大、恶意请求多的场景缓存空值实现简单适合业务规模较小或不存在 key 数量可控的场景。3. 布隆过滤器原理插入 key 经过多个 hash 函数 映射到位数组多个位置 把这些位置置为 1 查询 key 再经过同样的 hash 函数 检查对应位置 只要有一个位置是 0 → 一定不存在 全部都是 1 → 可能存在布隆过滤器的关键特性说“不存在”一定准确 说“存在”可能误判它不会误杀真实存在的数据但可能放过少量不存在的数据继续查 DB。这个误判率可以通过位数组大小和 hash 函数数量控制。4. 缓存击穿热点商品 keyproduct:1001 平时大量请求都命中 Redis 某一刻 key 过期 1000 个请求同时进来 Redis 都没查到 1000 个请求同时查 DB缓存击穿的本质是单个热点 key 在过期瞬间被高并发打穿。解决方案① 互斥锁重建缓存 只允许一个线程查 DB 并回写缓存 其他线程等待、重试、返回旧值或降级 ② 逻辑过期 缓存不设置物理过期时间 value 里存 expireTime 发现逻辑过期后异步刷新旧值继续可读 ③ 热点 key 不过期 适合配置、榜单、考试规则等读多写少数据 通过主动更新或删除保证最终一致互斥锁适合要求数据新鲜度较高的场景逻辑过期适合允许短时间读旧值、但不能让请求打爆 DB 的场景。5. 互斥锁重建缓存流程查缓存 ↓ 缓存未命中 ↓ 尝试加锁 ↓ 加锁成功 double check 缓存 查 DB 写缓存 释放锁 ↓ 加锁失败 短暂等待 重试缓存 / 返回旧值 / 降级为什么要 double check线程 A 拿锁后查 DB 并写回缓存 线程 B 等到锁后如果不再查一次缓存就会重复查 DB 所以拿锁后要再次检查缓存是否已经被别人重建6. 缓存雪崩缓存雪崩有两类① 大量 key 同时过期 比如批量导入缓存时都设置 24 小时 TTL 24 小时后同一时间集中失效 ② Redis 整体不可用 Redis 宕机、网络异常、集群故障 所有请求都绕过缓存打 DB解决方案① TTL 加随机值 expire baseTTL random(0, 300s) 避免大量 key 同时过期 ② Redis 高可用 主从、哨兵、Cluster ③ 本地缓存兜底 Caffeine 缓存热点配置或核心只读数据 ④ 限流 / 降级 / 熔断 保护 DB不让故障继续放大雪崩治理不能只靠应用代码必须把 Redis 高可用、降级策略和数据库保护一起考虑。7. 面试高频追问缓存穿透为什么可以缓存空值因为 DB 查不到的数据如果不缓存下次还会继续查 DB。 缓存 null 后同一个不存在 key 会直接命中 Redis避免反复打 DB。 但空值 TTL 要短避免真实数据后续创建出来后用户长时间读到空结果。逻辑过期和互斥锁怎么选对数据新鲜度要求高优先互斥锁等一个线程重建后再返回。 对可用性要求更高、允许短暂旧值优先逻辑过期先返回旧值再异步刷新。面试回答模板“缓存穿透、击穿、雪崩都表现为请求绕过缓存打到数据库但触发原因不同。 缓存穿透是查不存在的数据缓存和数据库都没有解决方案是布隆过滤器 前置拦截或者缓存空值并设置较短 TTL。 缓存击穿是单个热点 key 过期大量并发请求同时打到数据库。可以用互斥锁 只让一个线程重建缓存也可以用逻辑过期或热点 key 不过期避免过期瞬间 把数据库打穿。 缓存雪崩是大量 key 同时过期或者 Redis 整体不可用导致大面积请求打 DB。 解决方案包括 TTL 加随机值、Redis 主从哨兵或 Cluster、本地缓存兜底 再配合限流、降级、熔断保护数据库。”