缓存穿透
现象(秒杀场景)
大量请求查询数据库不存在的数据,Redis 找不到对应 key,缓存无法命中,请求全部穿透到 MySQL,数据库压力持续上涨,严重造成数据库 CPU 打满。
典型场景:恶意传入负数商品 ID、不存在编号、乱参数攻击接口。
产生原因
- 请求访问数据库不存在的数据,缓存没有记录;
- 缺少参数合法性校验;
- 没有布隆过滤器拦截无效 key;
- 未缓存空值。
临时应急方案(线上故障紧急止血)
- 接口层参数校验,拦截负数、空、非法参数,直接返回;
- 查询数据库无数据时,缓存空值,设置较短过期时间(3~5 分钟);
- 网关封禁高频异常 IP,临时限流。
长期工业级优化方案
布隆过滤器(主流方案):预加载所有合法商品 id,请求先经过过滤器,不存在直接拦截,避免访问 Redis、DB;
缺点:存在误判、不支持删除元素
规范空值缓存,短时效,防止大量无效 key 占用内存;
网关 + 业务双层参数校验;
搭建恶意请求黑名单。
重点坑点
布隆过滤器无法删除元素、存在误判;空值缓存过期时间不能设置过长,避免 Redis 内存膨胀。
缓存击穿
现象(秒杀场景)
秒杀爆款属于热点 Key,缓存 key 到期一瞬间,大量并发请求缓存未命中,全部涌向 MySQL,瞬间压垮数据库,接口大量超时阻塞。
核心特征 :单个热点 Key 失效,瞬时大量并发请求击穿到数据库
产生原因
热点 key 统一过期,缺少并发控制
- 热点商品缓存设置固定过期时间,同一时间失效;
- 没有并发控制,大量线程同时执行查库、更新缓存逻辑。
临时应急方案(线上紧急止血)
手动延长 key 过期时间、本地临时锁、扩容数据库连接池。
- 手动延长热点商品 Redis 过期时间,推迟失效;
- 增加单机本地锁,短时间限制并发查询数据库;
- 临时调大数据库连接池,缓解瞬时压力。
长期工业级优化方案
- 过期时间增加随机值打散(基础时间 + 0~5 分钟随机偏移);
- 分布式锁方案(Redisson):只放行一个线程更新缓存,其余线程等待;
- 热点 key 永不过期方案:不设置 expire,后台定时任务异步刷新缓存(秒杀爆款推荐);
- 多级缓存:Caffeine 本地缓存 + Redis 二级缓存。
缓存雪崩
现象(秒杀场景)
场景 1:系统内大量商品缓存设置统一过期时间,某个时间点大批量 key 同时失效;
场景 2:Redis 单点故障、集群宕机,缓存整体无法访问。
两种情况都会导致几乎所有请求绕过缓存,直接访问 MySQL,数据库连接被打满,服务大面积不可用,秒杀活动瘫痪
两种情况:①大量 key 集中过期;②Redis 整体宕机不可用。大规模流量同时冲击数据库。
产生原因
- 批量 key 过期时间集中;
- Redis 架构无高可用,单点故障没有自动转移;
- 缺少熔断、降级兜底策略;
- 未开启持久化,宕机后数据全部丢失。
缓存过期时间集中、Redis 无高可用架构、缺少熔断降级、未开启持久化。
临时应急方案(线上故障急救)
- 快速恢复 Redis 节点,依靠 RDB/AOF 持久化恢复缓存数据;
- 网关启动全局限流,削减打到数据库的流量;
- 启用本地 Caffeine 缓存临时兜底;
- 数据库层面临时限制最大查询并发。
恢复 Redis 实例、网关限流、本地缓存兜底、限制数据库并发
长期工业级优化方案
- 过期时间增加随机偏移,打散 key 失效时间;
- Redis 搭建高可用架构:主从 + 哨兵 / Redis Cluster 集群;
- 开启 RDB+AOF 混合持久化,故障快速恢复;
- 接入 Sentinel 实现熔断降级,缓存故障时直接返回兜底数据,拒绝访问数据库;
- 构建多级缓存:本地缓存 + Redis 分布式缓存;
- 网关、业务层多级限流,削峰填谷。
- 事前预防:过期时间随机打散、Redis 集群 / 哨兵高可用、开启混合持久化;
- 事中防护:多级缓存(Caffeine+Redis)、多层限流;
- 事后兜底:Sentinel 熔断降级。
综合知识点总复盘(三大缓存问题对比)
| 问题 | 核心特征 | 典型场景 |
|---|---|---|
| 缓存穿透 | 查询不存在的数据,缓存一直 miss | 黑客传入非法商品 ID |
| 缓存击穿 | 单个热点 key过期,瞬时并发打库 | 秒杀爆款缓存到期 |
| 缓存雪崩 | 大批量 key 失效 / Redis 宕机,整体流量冲击数据库 | 批量缓存统一过期、Redis 故障 |