Redis 的穿透、雪崩、击穿
1、缓存穿透
-
定义
- 缓存穿透是指查询一个不存在的数据,由于缓存中没有该数据,每次请求都会直接访问数据库,导致数据库压力过大
-
产生原因
- 恶意攻击:攻击者故意请求大量不存在的key,导致请求直接穿透到数据库中
- 业务逻辑问题:用户查询的数据在数据库中也不存在(如查询不存在的商品ID)
- 缓存未命中:缓存中存储相关数据,且数据库也没有,导致请求直接到达数据库
-
解决方法
1、布隆过滤器
- 在缓存层前使用布隆过滤器,判断请求的key是否可能存在。如果布隆过滤器判断不存在,直接返回,减少对数据库的访问
- 注意:布隆过滤器可能有误判(假阳性),但可以有效过滤大量无效请求
2、缓存空值
- 对于查询不存在的数据,将空值(如null)缓存到Redis中,并设置较短的过期时间(如30秒),避免重复穿透数据库
3、参数校验
- 在接口层对请求参数进行校验,过滤掉明显无效的请求(如负数ID、非法的查询参数)
4、异步回填
- 如果数据可能动态生成,可以异步触发数据生成逻辑,并缓存结果,防止频繁穿透
2、缓存雪崩
- 定义
- 缓存雪崩是指在某一个时刻,大量缓存key同时失效,或者Redis服务宕机,导致大量请求直接打到数据库,数据库无法承受高并发而崩溃
- 产生原因
- 缓存key集中失效:大量key设置了相同的过期时间,导致在同一时间点全部失效
- Redis服务宕机:Redis集群不可用,所有请求直接访问数据库
- 高并发场景:在缓存失效或不可用时,系统面临高并发请求,数据库不堪重负
- 解决方法
- 随机化过期时间
- 在设置缓存过期时间时,添加随机偏移量(如在基础时间上加减几秒),避免大量key同时失效
- 热点缓存时间延长
- 对于热点数据,延长缓存时间,或设置为永不过期,定期异步更新
- 高可用架构
- 部署Redis集群(如主从复制、哨兵模式、Cluster模式),确保Redis服务高可用,防止单点故障
- 降级与限流
- 在数据库层实现限流机制(如通过Nginx或网关限制请求频率)
- 提供降级方案,如返回默认值或提示用户稍后重试,减少数据库压力
- 分布式锁
- 在缓存失效时,使用分布式锁(如Redis锁或Zookeeper锁)限制同时访问数据库的线程数,防止数据库被压垮
- 随机化过期时间
3、缓存击穿
-
定义
- 缓存击穿是指某个热点key在失效的瞬间,大量并发请求同时访问该key,导致这些请求直接打到数据库上,造成数据库压力激增
-
产生原因
- 热点key失效:某个高频访问的key(如热门商品信息)在缓存中失效,且此时有大量并发请求
- 高并发访问:热点数据失效后,大量线程同时查询数据库,导致数据库瞬间负载过高
-
解决方法
1、热点key永不过期
- 对于热点数据,设置缓存永不过期,或通过异步任务定期刷新缓存内容
2、分布式锁
- 在缓存失效时,使用分布式锁(如redis的SEINX或Redisson)限制只有一个线程去查询数据库,其余线程等待缓存更新
- 示例流程
- 1、线程A发现缓存失效,尝试获取锁
- 2、获取锁成功后,查询数据库并更新缓存
- 3、其他线程等待锁释放后直接读取缓存
3、异步加载
- 在热点key接近失效时,提前异步触发缓存刷新,减少失效瞬间的请求压力
4、热点隔离
- 将热点数据单位存储到专用的Redis实例或本地缓存(如Caffeine、Guava Cache),降低对主数据库的冲击
总结对比
问题 | 定义 | 产生原因 | 解决方法 |
---|---|---|---|
缓存穿透 | 查询不存在的数据,穿透到数据库 | 恶意请求、数据不存在、缓存未命中 | 布隆过滤器、缓存空值、参数校验 |
缓存雪崩 | 大量 key 同时失效或服务宕机 | 集中失效、Redis 宕机、高并发 | 随机过期时间、高可用、限流降级 |
缓存击穿 | 热点 key 失效,大量请求打到数据库 | 热点 key 失效、高并发 | 分布式锁、永不过期、异步刷新、热点隔离 |