浅谈布隆过滤器 (Bloom Filter)

121 阅读3分钟

我正在参加「掘金·启航计划」


一、介绍

布隆过滤器(Bloom Filter)是 1970 年由布隆提出的,主要用于判断一个元素是否在一个集合中。它实际上是一个很长的二进制向量和一系列随机映射函数,因此空间效率和查询时间都非常高,缺点是有一定的误判率和删除困难。适用于一些需要快速判断某个元素是否属于集合,但是并不严格要求100%正确的场合。

二、原理

Bloom Filter 是由一个固定大小的二进制向量或者位图(bitmap)和一系列映射函数组成的。

在初始状态时,对于长度为 m 的位数组,它的所有位都被置为0,如下图所示:
image.png

当有变量被加入集合时,通过 K 个映射函数将这个变量映射成位图中的 K 个点,把它们置为 1(假定有两个变量都通过 3 个映射函数)。

查询某个变量的时候我们只要看看这些点是不是都是 1 就可以大概率知道集合中有没有它了

  • 如果这些点有任何一个 0,则被查询变量一定不在;
  • 如果都是 1,则被查询变量很可能存在

为什么是可能存在,而不是一定存在呢?这是由于散列函数会发出碰撞。如下图所示,即使集合中仅包含元素e1、e3、e4,Bloom Filter 同样会认为 e2 存在于集合中。因此可以发现,Bloom Filter 存在假正例(FP),不存在假负例(FN)
image.png

三、处理步骤

1. 添加元素

  • 用 k 个哈希函数处理元素
  • 得到元素在位数组上的 k 个位置
  • 将这 k 个位置置为 1

2. 查找元素

  • 用 k 个哈希函数处理要查找的元素
  • 得到元素在位数组上的 k 个位置
  • 如果 k 个位置有一个为 0,则肯定不在集合中
  • 如果 k 个位置全部为 1,则可能在集合中

四、优缺点

由 Bloom Filter 的原理以及操作步骤可以得知,Bloom Filter 的优点和缺点都非常明显

优点

  1. 相比于其它的数据结构,布隆过滤器在空间和时间方面都有巨大的优势。布隆过滤器存储空间和插入/查询时间复杂度为 O(k);
  2. 哈希函数之间相互没有关系,便于并行操作;
  3. 布隆过滤器不需要存储元素本身。

缺点

  1. 存在误判,且随着存入的元素数量增加,误算率随之增加;
  2. 一般情况下不能进行删除元素的操作,使用计数布隆过滤器(Counting Bloom Filter)可以一定程度上解决这个问题;

五、使用场景

布隆过滤器可用于网页 URL 去重、垃圾邮件识别、大集合中重复元素的判断和缓存穿透等问题。
其典型应用有:

  • 业务场景中判断用户是否阅读过某视频或文章,比如抖音或头条,当然会导致一定的误判,但不会让用户看到重复的内容。
  • 缓存宕机、缓存击穿场景,一般判断用户是否在缓存中,如果在则直接返回结果,不在则查询db,如果来一波冷数据,会导致缓存大量击穿,造成雪崩效应,这时候可以用布隆过滤器当缓存的索引,只有在布隆过滤器中,才去查询缓存,如果没查询到,则穿透到db。如果不在布隆器中,则直接返回。

六、最后

对于 Bloom Filter 的详细介绍以及误判率等的证明方法可见 en.wikipedia.org/wiki/Bloom_…