缓存穿透及解决方案
# 什么是缓存穿透
缓存穿透是 “查询一个不存在的 Key(如用户查询 ID=-1 的用户),由于缓存中没有该 Key,所有请求都穿透到数据库,导致数据库处理大量无效请求,压力增大” 的问题。与击穿(Key 存在但过期)、雪崩(批量 Key 失效)不同,穿透的 Key 是 “不存在的”,缓存无法命中。
# 解决方案
- 1. 缓存空值:
- 当数据库查询结果为空时(Key 不存在),仍将空值存入 Redis(如
set(key, null, 60)),并设置较短的过期时间(如 60 秒); - 后续请求查询该 Key 时,直接从缓存获取空值,无需查数据库。
- 优点:实现简单;缺点:若大量不存在的 Key 被缓存,会占用 Redis 内存(需设置较短过期时间,减少内存占用)。
- 当数据库查询结果为空时(Key 不存在),仍将空值存入 Redis(如
- 2. 布隆过滤器(Bloom Filter):
- 原理:布隆过滤器是一种概率型数据结构,通过多个哈希函数将 “存在的 Key” 映射到位数组中,标记为 1;查询时,先通过布隆过滤器判断 Key 是否存在:
- 若布隆过滤器判断 Key 不存在,直接返回空值,无需查缓存和数据库;
- 若布隆过滤器判断 Key 存在,再查缓存和数据库(存在极低误判率,需容忍)。
- 实现:
- 系统启动时,将数据库中所有存在的 Key(如用户 ID、商品 ID)导入布隆过滤器;
- 新增 Key 时,同步更新布隆过滤器;
- 查询时,先通过布隆过滤器过滤不存在的 Key。
- 优点:空间效率极高(位数组存储),查询速度快;缺点:存在误判率(可通过调整哈希函数数量和位数组大小降低),无法删除 Key(只能新增)。
- 原理:布隆过滤器是一种概率型数据结构,通过多个哈希函数将 “存在的 Key” 映射到位数组中,标记为 1;查询时,先通过布隆过滤器判断 Key 是否存在:
- 3. 接口参数校验:
- 在接口层(如 Controller)对请求参数进行合法性校验,过滤无效参数(如用户 ID=-1、商品 ID=0),直接返回错误,无需进入缓存和数据库查询;
- 例如:用户 ID 必须为正整数,否则返回 “参数错误”。
- 优点:从源头拦截无效请求,成本低;缺点:无法过滤所有无效参数(如合法格式但不存在的 ID)。
- 4. 限流与黑名单:
- 对高频查询不存在 Key 的 IP 或用户设置黑名单,限制其请求频率(如 1 分钟内最多 10 次请求);
- 通过网关或 Redis 记录请求次数,超过阈值的 IP 直接拒绝。
- 优点:防止恶意攻击(如黑客批量查询不存在的 Key);缺点:可能误判正常用户。
上次更新: 12/30/2025