Redis用布隆过滤器防缓存穿透的核心是提前拦截不存在key的请求,因其“不存在”判断100%准确,可避免无效查询打到数据库;需通过RedisBloom模块实现,注意误判率、不可删除、空值缓存等关键限制。

Redis 用布隆过滤器解决缓存穿透,核心是“提前拦截非法或不存在的请求”,不让它们打到数据库。它不保证100%存在,但能100%确认不存在——这个确定性,就是防御穿透的关键。
为什么布隆过滤器适合防穿透
缓存穿透的本质是:大量请求查一个根本不存在的 key(比如恶意构造的 user_id=-1、商品 id=999999999),缓存没命中,DB 也没数据,每次都要走完整链路。布隆过滤器在这类场景中发挥不可替代的作用:
- 它只存哈希位,不存原始数据,内存开销极小(例如 1 亿数据仅需 ~12MB)
- 查询是 O(k) 时间复杂度(k 通常为 3~8),比查 Redis 字符串还快
- 返回“不存在”时,结果绝对准确——这类请求直接拒绝,不再碰缓存和 DB
实际部署步骤
推荐使用官方模块 RedisBloom(已支持 Redis 6.0+,生产环境稳定):
-
安装模块:启动 Redis 时加载
redisbloom.so,或通过MODULE LOAD redisbloom.so -
初始化过滤器:根据预估总量和可接受误判率创建,例如:
BF.RESERVE user_filter 0.01 1000000(误判率 1%,容量 100 万) -
预热数据:系统上线前,把所有合法 user_id、商品 id 等批量写入:
BF.ADD user_filter "uid:1001" "uid:1002" ... -
请求拦截逻辑:在业务代码中,先查布隆过滤器:
若BF.EXISTS user_filter "uid:999999"返回 0 → 直接返回 404 或空响应;
若返回 1 → 再查 Redis 缓存 → 缓存无则查 DB → DB 无则按需缓存空值(可选)
关键注意事项
布隆过滤器不是万能钥匙,用错反而引入新问题:
- 误判率要合理设置:0.1% 误判率对应约 10 位/元素;追求更低误判率需更大位数组,权衡内存与精度
- 无法删除元素:一旦加入,就不能删。若业务有频繁注销/下架场景,需配合分片过滤器或定时重建
- 不代替缓存空值:布隆过滤器只拦“绝对不存在”的请求;对“曾经存在但已删除”的数据,仍建议缓存短时效空对象,避免反复穿透
- 动态扩容慎用:BF.RESERVE 创建后容量固定;如需扩量,必须新建过滤器并迁移,线上应预留 20%~30% 容量余量
替代方案对比(无 RedisBloom 时)
如果不能加载模块,可用 Lua 脚本 + Redis Bitmap 模拟简易布隆过滤器:
- 用
SETBIT手动维护一个大 bitmap(如 1000 万位) - 在 Lua 中实现多个哈希函数(如 MurmurHash3 变种),将 key 映射到位偏移
- 插入时设多位为 1;查询时检查所有位是否全为 1
- 缺点:脚本逻辑复杂、哈希分布难调优、无自动扩容,仅适用于低并发或临时验证


















