见龙在田,利见大人。 —— 《易经》之乾卦的第二爻(九二爻) 译为一个胸怀大志的人,已经崭露头角。今指一个人仕途顺利,初露锋芒,得到领导的赏识,前途光明。
一、基础
- 概念
布隆过滤器(Bloom Filter)是1970年由布隆提出的,是一个很长的二进制向量和一系列随机映射函数。实质上,它是一种概率型数据结构(probabilistic data structure),其特点是高效地插入和查询,可以用来快速判断某个元素存在或不存在,空间效率和查询时间都远远超过一般的算法,缺点是有一定的误识别率和删除困难。
✅ 特点:插入、查询速度极高,空间效率远超普通集合
❌ 局限:存在假阳性误判(判断存在不一定真存在),普通布隆不支持删除元素
核心特性总结
- 无假阴性:如果元素真实存在,查询一定返回“可能存在”;
- 有假阳性:元素不存在,也有可能巧合判定为“可能存在”。
适用场景:网页黑名单、垃圾邮件过滤、爬虫URL判重、Redis缓存穿透防护、账号/商品ID预校验去重。
- 原理
- 布隆过滤器是一个bit向量或者说bit数组,所有bit初始值为0。

布隆过滤器离不开哈希函数,它有如下特点
- 输入值域无限;输出值域固定;
- 相同输入,哈希结果一定相同;
- 不同输入,哈希结果可能相同(哈希冲突);
- 哈希结果尽量均匀分布,减少聚集。
如果我们要映射一个值到布隆过滤器中,需要使用多个不同的哈希函数生成多个哈希值,并对每个生成的哈希值指向的bit位设为1,例如针对值“baidu”和三个不同的哈希函数分别生成了哈希值1、4、7,则上图转变为:

- 再存一个值“tencent”,假设三个不同的哈希函数得到的哈希值分别为3、4、8,图继续变为:

- 如图,4这个bit位由于两个值的哈希函数都返回了这个bit位,因此它被覆盖了。
- 当需要查询“dianping”这个值是否存在,假设三个哈希函数分别得到哈希值1、5、8。结果发现5这个bit位上的值为0,说明没有任何一个值映射到这个bit位上,因此可以很确定地说“dianping”这个值不存在。
- 当需要查询“baidu”这个值是否存在,那么三个哈希函数肯定会拿到1、4、7三个值。然后发现这三个bit位上的值均为1,那么可以说“baidu”这个值可能存在,即哈希冲突的问题。
适用场景
- 爬虫URL去重:避免重复抓取相同链接;
- 缓存穿透防护(Redis最常用场景):拦截不存在的key,防止大量空请求穿透到数据库;
- 黑名单校验、手机号/优惠券ID去重;
❗不适合场景
需要精准判断元素是否存在(不能容忍误判);
需要频繁删除元素(普通布隆无法删除);
元素数量无法预估,持续无限增长(bit数组会被填满)。
二、使用
注意:原生Redis内核没有内置布隆过滤器,两种实现方案:
- 方案1:Redis原生Bitmap手动实现布隆过滤器
利用SETBIT / GETBIT命令,自己在业务代码编写多个哈希函数,计算bit位置,操作bitmap。
优点:不需要安装Redis模块,任意版本Redis都能用;
缺点:
- 需要自己实现哈希算法、计算bit长度,维护成本高
- 没有内置误判率计算,需要自行估算
- 不支持批量操作,容易写bug
一般生产很少手写,优先RedisBloom模块。
- 方案2:RedisBloom模块(推荐)
Redis 4.0+支持加载模块,RedisBloom提供完整布隆过滤器命令,云厂商托管Redis(阿里云/腾讯云)大多已经预装RedisBloom。
三、全置为1的问题
随着不断插入元素,bit 数组中 0 的 bit 位会越来越少:
- 在还没有全部变成 1 之前,误判率就会持续上升,业务上已经不可用,不是等到全部置 1 才失效;
- 一旦 bit 数组全部置为 1:任何元素查询,所有哈希对应的 bit 都是 1,布隆过滤器100% 返回 “可能存在”,过滤器完全失效;
- 后果:缓存穿透防护失效,无效请求全部打到数据库。
解决办法
- 创建时预留容量余量:BF.RESERVE 设置预估数量,实际插入量不要超过预设值;
- 分片布隆(可扩展布隆):代码维护多个独立布隆分片,新增数据写入新分片;查询时遍历所有分片;旧分片可以直接删除,解决容量上限问题
- RedisBloom 本身不自带分片,需要业务层实现;
- 定时重建布隆过滤器:定时从DB全量同步合法ID,生成新布隆,切换引用,销毁旧过滤器;
- 适合数据相对稳定场景;
- 监控:监控布隆插入数量,接近预设阈值告警。
四、常见误区
- ❌ 布隆过滤器可以判断元素一定存在
✅ 只能判断元素一定不存在;返回存在只是大概率。 - ❌ Redis 原生自带布隆过滤器
✅ 原生 Redis 没有,需要 RedisBloom 模块;Bitmap 只是底层 bit 结构,可以手动实现布隆。 - ❌ 布隆可以删除元素
✅ 普通布隆不能删除;删除会影响其他元素。 - ❌ 元素数量超出预设值只是一点点,没关系
✅ 超出预设容量后,误判率会快速恶化。