目录
一、什么是布隆过滤器
布隆过滤器可以用于查询一个元素是否存在于一个集合当中,查询结果为以下二者之一:
- 这个元素可能存在于这个集合当中。
- 这个元素一定不存在于这个集合当中。
布隆过滤器(Bloom Filter)是1970年由布隆提出的。它用一个二进制向量和一些哈希计算函数来实现的。布隆过滤器可以用于检索一个元素是否在一个集合中。
布隆过滤器的原理是,当一个元素被加入集合时,通过K个散列函数将这个元素映射成一个位数组中的K个点,把它们置为1。检索时,我们只要看看这些点是不是都是1就(大约)知道集合中有没有它了:如果这些点有任何一个0,则被检元素一定不在;如果都是1,则被检元素很可能在。这就是布隆过滤器的基本思想。 –引自《维基百科,自由的百科全书》
二、布隆过滤器数据结构
布隆过滤器是一个由固定大小的二进制向量或者位图和一系列映射函数所组成的。
在初始状态下,对于一个长度为m的位数组,所有位置0,如下:
当有变量被加入集合时,通过K个映射函数将这个变量映射成位图中的K个点,把它们置为1【举例中以3个映射函数为例】:
查询某个变量的时候,只要这些对应的点是否是都是1:
- 如果这些点有一个0,则被查询的变量一定不存在
- 如果都是1,则被查询的变量可能存在
为什么说可能存在,而不是一定存在呢?
那是因为映射函数本身就是散列函数,散列函数就是会有碰撞哒~
三、支持删除吗?
布隆过滤器不能直接支持删除操作,因为在删除一个元素时,可能会影响其他元素
四、布隆过滤器应用
在实际工作中,布隆过滤器常见的应用场景如下:
- 网页爬虫对 URL 去重,避免爬取相同的 URL 地址;
- 秒杀系统,查看用户是否重复购买;
- 反垃圾邮件,从数十亿个垃圾邮件列表中判断某邮箱是否垃圾邮箱;
- Google Chrome 使用布隆过滤器识别恶意 URL;
- Medium 使用布隆过滤器避免推荐给用户已经读过的文章;
- Google BigTable,Apache HBbase 和 Apache Cassandra 使用布隆过滤器减少对不存在的行和列的查找;
- 业务场景中判断用户是否阅读过某视频或文章,比如抖音或头条,当然会导致一定的误判,但不会让用户看到重复的内容;
- Venti 文档存储系统也采用布隆过滤器来检测先前存储的数据;
- SPIN 模型检测器也使用布隆过滤器在大规模验证问题时跟踪可达状态空间;
- 缓存宕机、缓存击穿场景,一般判断用户是否在缓存中,如果在则直接返回结果,不在则查询db,如果来一波冷数据,会导致缓存大量击穿,造成雪崩效应,这时候可以用布隆过滤器当缓存的索引,只有在布隆过滤器中,才去查询缓存,如果没查询到,则穿透到db。如果不在布隆器中,则直接返回;
- WEB拦截器,如果相同请求则拦截,防止重复被攻击。用户第一次请求,将请求参数放入布隆过滤器中,当第二次请求时,先判断请求参数是否被布隆过滤器命中。可以提高缓存命中率。Squid 网页代理缓存服务器在 cache digests 中就使用了布隆过滤器。Google Chrome浏览器使用了布隆过滤器加速安全浏览服务;
五、布隆过滤器的优缺点
优点
- k和m相同,使用同一组散列函数的两个布隆过滤器的交并运算可以使用位操作进行;
- 增加和查询元素的时间复杂度为O(k)【k为哈希函数的个数】,与数据量大小无关;
- 哈希函数相互之间没有关系,方便硬件并行运算;
- 布隆过滤器不需要存储元素本身,在某些对保密要求比较严格的场合有较大优势;
- 在能够承受一定误判时,布隆过滤器比其他数据结构有很大的空间优势;
- 数据量很大时,布隆过滤器可以表示全集,其他数据结构不能;
- 使用同一组散列函数的布隆过滤器可以进行交、并、差运算;
缺点
- 但是布隆过滤器的缺点和优点一样明显。误算率是其中之一。随着存入的元素数量增加,误算率随之增加。但是如果元素数量太少,则使用散列表足矣。
- 另外,一般情况下不能从布隆过滤器中删除元素。我们很容易想到把位数组变成整数数组,每插入一个元素相应的计数器加1, 这样删除元素时将计数器减掉就可以了。然而要保证安全地删除元素并非如此简单。首先我们必须保证删除的元素的确在布隆过滤器里面。这一点单凭这个过滤器是无法保证的。另外计数器回绕也会造成问题。
在降低误算率方面,有不少工作,使得出现了很多布隆过滤器的变种。
- 有误判率,即存在假阳性,即不能准确判断元素是否在集合中【补救:再建立一个白名单,存储可能会误判的数据】
- 不能获取元素本身
- 一般情况,不能从布隆过滤器中删除元素