1、布隆过滤器使用场景
比如有如下几个需求:
①原本有10亿个号码,现在又来了10万个号码,要快速准确判断这10万个号码是否在10亿个号码库中?
- 解决办法一:将10亿个号码存入数据库中,进行数据库查询,准确性有了,但是速度会比较慢。
- 解决办法二:将10亿号码放入内存中,比如Redis缓存中,这里我们算一下占用内存大小:10亿*8字节=8GB,通过内存查询,准确性和速度都有了,但是大约8gb的内存空间,挺浪费内存空间的。
②接触过爬虫的,应该有这么一个需求,需要爬虫的网站千千万万,对于一个新的网站url,我们如何判断这个url我们是否已经爬过了?
- 解决办法还是上面的两种,很显然,都不太好。
③一个邮件系统,有上亿的邮件数量,我们要检测某一个邮箱是否正确发送了邮件信息?
④提到Redis做缓存查询,我们需要考虑几个问题,缓存穿透、缓存击穿和缓存雪崩。我们该如何解决缓存?
那么对于类似这种,大数据量集合,如何准确快速的判断某个数据是否在大数据量集合中,并且不占用内存,布隆过滤器应运而生了。
2、布隆过滤器
布隆过滤器其实就是一种数据结构,是由一串很长的二进制向量组成,可以将其看成一个二进制的数组。既然是二进制,那么里面存放非不是0,就是1,但是初始默认值都是0。
大致的数据结构如下图:
0 | 1 | 0 | 0 | 1 | 1 | 1 | 0 | 0 | 0 | 1 | 1 |
(1)添加数据
向布隆过滤器中添加key时,会使用多个hash函数对key进行hash计算得到一个整数索引值,然后对位数组长度进行取模运算得到一个位置,再把位数组的这几个位置都置为1就完成了add操作。
比如,下图hash1(key)=1,那么在第3个格子将0变为1(数组是从0开始计数的),hash2(key)=5,那么将第7个格子置位1,依次类推,
(2)判断数据是否存在?
知道了如何向布隆过滤器中添加一个数据,那么新来一个数据,我们如何判断其是否存在于这个布隆过滤器中呢?
很简单,我们只需要将这个新的数据通过上面自定义的几个哈希函数,分别算出各个值,然后看其对应的地方是否都是1,如果存在一个不是1的情况,那么我们可以说,该新数据一定不存在于这个布隆过滤器中。
反过来说,如果通过哈希函数算出来的值,对应的地方都是1,那么我们能够肯定的得出:这个数据一定存在于这个布隆过滤器中吗?
答案是否定的,因为多个不同的数据通过hash函数算出来的结果是会有重复的,所以会存在某个位置是别的数据通过hash函数置为的1。
我们可以得到一个结论:布隆过滤器可以判断某个数据一定不存在,但是无法判断一定存在。
布隆过滤器优缺点
优点:优点很明显,二进制组成的数组,占用内存极少,并且插入和查询速度都足够快。
缺点:随着数据的增加,误判率会增加;还有无法判断数据一定存在;另外还有一个重要缺点,无法删除数据