布隆过滤器可精准拦截“绝对不存在”的请求,因其位数组中任一哈希位置为0即判定key未注册;实际需启用redisbloom、预热过滤器、入口校验bf.exists;但不支持删除、有误判率、须配合空值缓存防历史删除key穿透。

Redis 缓存穿透通过布隆过滤器拦截解决,核心是把“查不到的数据”在请求最前端就挡掉——只要布隆过滤器说“这个 key 绝对不存在”,就直接返回,不查 Redis,更不碰数据库。
为什么布隆过滤器能精准拦截“不存在”的请求
布隆过滤器底层是一个固定大小的位数组 + 多个独立哈希函数。所有合法 key(比如真实存在的商品 ID、用户 ID)在系统上线前或数据写入时,就被哈希映射到位数组中对应位置并置为 1。
当一个请求到来时,对它的 key 执行同样的哈希计算:只要任意一个哈希位置是 0,就说明这个 key 从未被加入过,一定不存在;只有全部位置都是 1,才认为“可能存在”(这时才有资格继续走缓存 → 数据库链路)。
这个“不存在即确定”的特性,正是防御穿透的关键——恶意构造的 user_id=999999999、order_no=ABC-XXX 这类非法 key,几乎 100% 被当场拦截。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
实际部署必须做的三件事
- 启用 RedisBloom 模块:Redis 默认不支持布隆过滤器,需加载 redisbloom.so(Redis 6.0+ 推荐用 MODULE LOAD 命令动态加载,或启动时通过 --loadmodule 指定)
- 创建并预热过滤器:例如 BF.RESERVE goods_filter 0.01 1000000(误判率 1%,容量 100 万),再用 BF.ADD 批量导入所有已存在的商品 ID
- 在业务入口加一层判断:收到请求后,先执行 BF.EXISTS goods_filter "goods:123456";返回 0 就直接返回 404 或空响应,不再往下执行
不能忽略的几个关键限制
布隆过滤器不是“查表工具”,它有明确边界:
- 不支持删除:用户注销、商品下架后,对应的 key 仍留在过滤器里。若这类场景多,建议按天/按业务域分片建多个过滤器,或定期重建(用新过滤器替换旧的,期间双写过渡)
- 误判率要权衡:设成 0.1% 时,每 1000 个不存在 key 中可能有 1 个被误判为“可能存在”,会漏放一次;但设成 0.001% 就需要更大内存。生产环境通常选 0.1%~1%
- 不能替代空值缓存:布隆过滤器只拦“从没存在过”的 key;而“曾经存在、现已删除”的数据,仍需配合短时效空值缓存(如 set product:999 “null” ex 60),否则会反复穿透
和空值缓存搭配效果更好
单独用布隆过滤器,能挡住 99% 的恶意无效请求;但真实业务中,总有些 key 是“历史存在过、后来删了”。这类请求布隆过滤器无法识别(因为当初加进去了),所以仍会打到缓存和 DB。
推荐组合策略:
→ 请求进来先过布隆过滤器(拦绝对不存在)
→ 若通过,再查 Redis 缓存
→ 若缓存 miss,查数据库
→ 若数据库也无结果,往 Redis 写一个带 1~5 分钟过期的空值(如 "" 或 "NULL")
这样两层防护,既控住恶意流量,又兜住业务变更带来的临时空查。










