缓存穿透、击穿、雪崩本质均为缓存失效致请求直冲数据库,需分别通过“守门”(空值缓存/布隆过滤器/参数校验)、“串行”(互斥锁/逻辑过期)和“错峰+冗余”(随机过期/多级缓存/集群预热)应对。

缓存穿透、雪崩、击穿是 Redis 实际使用中最常见的三类高危问题,本质都是缓存失效或缺失导致请求直冲数据库,引发性能抖动甚至服务崩溃。解决思路不靠堆资源,而在于“提前拦截”“错峰控制”和“并发保护”。
缓存穿透:查一个根本不存在的 key
典型表现是大量请求查询数据库里压根没有的 ID(比如恶意刷无效订单号、爬虫遍历用户 ID),缓存没命中,数据库也没数据,每次都要走全链路,白白消耗连接和 CPU。
- 空值缓存:查数据库返回 null 时,往 Redis 存一个特殊标记(如 red">"" 或 "NULL"),并设较短过期时间(比如 2–5 分钟)。后续同 key 请求直接命中缓存,不碰 DB。
- 布隆过滤器预检:系统启动时把所有合法 key 加载进布隆过滤器(Bloom Filter)。请求来时先过滤器判断“可能有”,再查缓存;若过滤器说“肯定无”,直接拒绝。注意它有极小误判率(可调),但不漏判,适合防攻击场景。
- 参数校验兜底:在接入层(如网关、Controller)对 key 做格式/范围校验(比如 ID 必须是正整数、手机号需符合规则),非法请求直接拦截,不进缓存和 DB。
缓存击穿:单个热 key 过期瞬间被并发打穿
比如某爆款商品详情页的缓存刚好到期,上百人同时刷新,全部涌向数据库查同一行记录。
- 互斥锁(分布式锁):缓存未命中时,用 Redis 的 SETNX 或 Redisson 加锁。只有一个线程能查 DB 并写回缓存,其余线程等待后直接读新缓存。适合 QPS 高但 key 数量有限的热点。
- 逻辑过期 + 异步重建:缓存 value 封装为含 expireTime 字段的对象,物理不过期。过期时只允许一个线程异步更新,其他请求仍返回旧数据(容忍短暂不一致),避免雪崩式等待。
- 永不过期 + 定时刷新:对极关键且更新不频繁的热数据(如首页 Banner 配置),缓存不设 TTL,改由后台定时任务(如每 10 分钟)主动查库更新,保证数据新鲜又不触发击穿。
缓存雪崩:大批 key 集中失效或 Redis 整体宕机
最危险——不是个别请求出问题,而是整个服务链路承压。例如凌晨批量设置 2 小时 TTL,结果整点集体过期;或主节点宕机未及时切从。
- 过期时间随机化:基础 TTL(如 30 分钟)基础上,叠加 0–10 分钟随机偏移量,让 key 失效时间分散开,避免扎堆。
- 多级缓存 + 降级策略:本地 Caffeine 缓存 + Redis 作为二级。Redis 不可用时,自动降级读本地缓存(哪怕旧一点),或返回兜底静态页,保障基本可用。
- 集群高可用 + 预热机制:用 Redis Cluster 或哨兵模式;大促前跑预热脚本,把核心 key 提前加载进缓存,避开冷启动高峰。
基本上就这些。三者虽常并列讲,但成因和解法逻辑不同:穿透重在“守门”,击穿重在“串行”,雪崩重在“错峰+冗余”。实际项目中往往组合使用,比如空值缓存 + 布隆过滤器防穿透,逻辑过期 + 分布式锁防击穿,随机 TTL + 集群容灾防雪崩。










