Redis 缓存三大故障 - 缓存穿透
导言
在分布式系统中,Redis 作为高性能分布式缓存,可有效减轻数据库压力、提升接口响应速度,但高并发场景下,缓存雪崩、缓存击穿、缓存穿透三类异常易引发系统稳定性问题。
一、缓存穿透 ——“不存在数据” 的持续穿透
1. 核心定义
缓存穿透是指查询的数据在缓存和数据库中均不存在(如查询不存在的 ID、非法参数),导致每次请求都穿透缓存直接查询数据库,且由于缓存无法存储 “不存在的数据”,后续相同请求会持续穿透,造成数据库无效查询压力激增的现象。
核心特征:区别于前两类异常,其关键在于 “查询无结果数据”,缓存无法拦截,请求持续打向 DB。
2. 触发条件
缓存穿透的发生源于两类场景:
非法请求攻击:恶意用户构造非法参数(如负数 ID、超长字符串)发起大量查询,这类数据在缓存和 DB 中均不存在;
业务空数据查询:正常业务场景中,部分查询天然无结果(如查询已删除的用户、未创建的订单),且未做缓存处理。
3. 解决方案对比
解决方案 | 实现逻辑 | 优点 | 缺点 | 适用场景 |
---|---|---|---|---|
空值缓存 | 查询 DB 无结果时,将 “空值”(如空字符串、默认对象)存入 Redis,并设置较短过期时间(如 5-10 分钟),拦截后续相同请求 | 实现简单,无额外组件依赖;可快速拦截重复请求 | 占用 Redis 内存(存储大量空值);短期存在数据不一致(如 DB 新增数据前,缓存仍返回空值) | 非法请求较少、空数据查询量可控的场景 |
布隆过滤器 | 提前将 DB 中所有有效数据的 “标识”(如 ID)存入布隆过滤器;查询前先通过过滤器校验,若标识不存在则直接返回,不查询缓存和 DB | 内存占用极低(比空值缓存节省 90% 以上);拦截效率高 | 存在误判率(无法 100% 精准拦截);需维护过滤器与 DB 数据一致性(如数据新增 / 删除时同步更新过滤器) | 非法请求量大、空数据查询频繁的场景(如用户 ID 查询、商品 ID 查询) |
请求参数校验 | 在业务层或网关层添加参数校验(如 ID 范围校验、格式校验),直接拦截非法参数请求(如负数 ID、非数字 ID) | 从源头拦截无效请求,无缓存 / DB 压力;实现简单 | 仅能拦截 “格式非法” 的请求,无法拦截 “格式合法但 DB 无结果” 的请求(如合法 ID 但已删除) | 可作为基础防护,需与其他方案配合使用 |
4. 代码示例(空值缓存・Java)
1 | public Object getDataById(Long id) { |
5. 关键监控指标
无结果查询量:Redis 无结果查询量 + DB 无结果查询量≥总请求量的 10%,需警惕穿透风险;
DB 无结果查询占比:DB 查询中无结果的比例≥20%,可能存在穿透;
非法参数请求量:网关层拦截的非法参数请求≥500 次 / 秒,需加强参数校验;
布隆过滤器误判率:若使用布隆过滤器,误判率应控制在 1% 以下,超过需调整过滤器参数(如哈希函数数量、bit 数组大小)。
二、三类缓存异常核心差异总结
异常类型 | 核心诱因 | 影响范围 | 关键防护思路 |
---|---|---|---|
缓存雪崩 | 大量缓存集中过期 / 服务不可用 | 全局 | 打散过期时间、多级缓存、保障服务可用性 |
缓存击穿 | 单个热点数据过期 | 局部(热点) | 互斥锁、逻辑过期、热点数据永不过期 |
缓存穿透 | 查询不存在的数据 | 全局(DB) | 空值缓存、布隆过滤器、参数校验 |
All articles on this blog are licensed under CC BY-NC-SA 4.0 unless otherwise stated.