作用
用于判断某个元素是否存在于指定集合中。在确保高性能的同时,布隆过滤器能够将存储空间降低 90% 以上,不过和 HyperLogLog 一样的问题是,它也存在一定误差,不过对于海量数据而言,这个误差是可以接收的(
它判断不存在的元素,一定不存在,但是它判断存在的元素,有可能不存在。
)
常用命令
bf.add
添加元素到集合bf.exists
检查元素是否存在- bf.madd 批量添加元素到集合
- bf.mexists 检查多个元素是否存在
代码实践
127.0.0.1:6379> bf.madd index.uv.20210401 user_1 user_2 user_3
(integer) 1
127.0.0.1:6379> bf.exists index.uv.20210401 user_1
(integer) 1
127.0.0.1:6379> bf.exists index.uv.20210401 user_7
(integer) 0
底层原理
每个布隆过滤器对应到 Redis 底层的数据结构就是一个大型的位数组和一系列的无偏哈希函数(所谓无偏就是能够把元素的哈希值算得比较均匀)
向布隆过滤器中添加键值对时,会使用这一系列哈希函数分别对键名进行哈希运算,然后将得到的整数索引值与位数组长度进行取模运算得到最终索引位置,再把位数组的这几个索引位都置为 1,这就完成了 bf.add
操作。
向布隆过滤器查询指定键名是否存在时,和 bf.add
一样,也会把哈希后的索引位置都算出来,看看位数组中这几个索引位的值是否都为 1,只要有一个位为 0,则说明布隆过滤器中这个键名不存在。如果都为 1,也并不能说明这个键名就一定存在,只是很有可能存在,因为这些位被置为 1 可能是其它键名哈希运算时出现哈希冲突所致(概率很低,但是存在)。
如果这个位数组比较稀疏,判断正确的概率就会很大,如果这个位数组比较稠密,判断正确的概率就会降低,因为出现哈希冲突的概率会提高,但是相对整体而言依然是很小的比例
使用场景
除了爬虫链接去重之外,布隆过滤器还可以广泛应用于推荐系统去重
(比如电商推荐系统排除已购买过的商品)、敏感词过滤系统
(敏感词库是否已包含这个敏感词)、垃圾邮件/短信过滤(判断某个邮箱是否是垃圾邮箱)、避免缓存穿透
(将缓存键放到布隆过滤器,避免恶意读取不存在的缓存键对 DB 造成巨大压力`)等业务场景