【C++】 ——亿级数据过滤之布隆过滤器

大数据处理之布隆过滤器

  • 一、布隆过滤器
  • 二、布隆过滤器的原理
  • 三、布隆过滤器不支持删除
  • 四、布隆过滤器的使用场景

一、布隆过滤器

秉承着学习的态度,博主对布隆过滤器产生了很大的兴趣,它适用于大数据处理,比如垃圾邮件过滤,电话黑名单,URL去重,网页黑名单等都

“宁可错杀一千,也不放过一个”,这是布隆过滤器的特点,也就是说我们利用布隆过滤器判断这一邮件是垃圾邮件一定就是准确的,也有可能将有效邮件判断称垃圾邮件,布隆过滤器存在误判的可能。接下来,我们就来看看布隆过滤器的原理。

二、布隆过滤器的原理

在这之前,我们考虑一个问题,通常我们判断一个数据是否在一个大的数据集合中通常采用的是什么办法?应该蛮多人回答HashMap,确实可以将值映射到HashMap的key中,时间复杂度是O(1),效率也挺高。我们面对下现实,当我们的数据集是40亿的时候,它原本存储在远程服务器上,本地服务器接收输入,我们不可能一次性将数据读进内存构建HashTable.

我觉得布隆过滤器就是利用位图这一原理来提高空间利用率,1个整型=4个字节=32个比特位,原来存储一个整形数字的空间,现在使用位图,可以存储32个数字的标志位,需要注意的是,位图里面存放的并不是key值,而是标志位,如果key值是垃圾邮件,就将标志位设为1(二进制的0和1)。先开始的一种方法是我们利用一个哈希函数,让所有的垃圾邮件都通过这一个函数映射出位置,如图所示:
【C++】 ——亿级数据过滤之布隆过滤器_第1张图片
这会产生一个问题,那就是如果垃圾邮件abcd已经将该位置为1,另一个垃圾邮件bcda来了以为自己被标记过了,就会被误认为是有效邮件。这是不合理的。所以我们这里采用多个不同的哈希函数生成多个哈希值,并对每个生成的哈希值指向的bit位置为1.如图所示:
【C++】 ——亿级数据过滤之布隆过滤器_第2张图片
abcd和三个不同的哈希函数分别生成了哈希值1,4,7,我们就将1,4,7位置置为1,如果接下来的垃圾邮件是bcda,如图所示:
【C++】 ——亿级数据过滤之布隆过滤器_第3张图片
他映射的位置是2,4,8,我们看到4这个位置由于两个值的哈希函数都映射到了,因此它被覆盖了。那如果我们现在想查询邮件www.cabd.com是不是垃圾邮件,哈希函数分别返回1,5,8三个值,结果我们发现5这个比特位是0,说明他是有效邮件。当我们查询www.dbca.com是不是垃圾邮件的时候,发现他经过哈希函数映射的是2,4,7这个位置,那我们是不是就能说这个邮件就是垃圾邮件了呢?不可以的,我们只能说他可能是垃圾邮件。

原因为何?很简单,当随着增加的值越来越多,被置为1的bit位也会越来越多,这样某个值虽然没有被存储过,但是哈希函数返回的值已经被其他的值覆盖成了1,程序还是会判断www.dbca.com是垃圾邮件。这也就是说如果一个邮件是垃圾邮件,布隆过滤器一定能判断出来,但是会存在误判的原因。

三、布隆过滤器不支持删除

根据以上我们知道,布隆过滤器是支持add的,但是这里需要说明的是它不支持删除,比如上图中的垃圾邮件abcd和dcba映射了同一个位置4,如果abcd删除了,将4置为0,那下一次判断dcba是否湿垃圾邮件的时候会直接返回false,实际上你并没有删除它。

如何解决这个问题?答案是计数删除。但是计数删除需要存储一个数值,而不是原来的bit位,会增大占用内存的大小,这样的话,增加一个值就是将对应索引槽上存储的值加1,删除则是减1,判断是否存在则是看值是否大于0.

四、布隆过滤器的使用场景

场景一:使用布隆过滤器标记垃圾邮箱

理想状态如果我们布隆过滤器已经帮我们标记了所有垃圾邮箱,那么我们收件箱中的邮件一定是非垃圾的,但是由于会出现误判,所以我们垃圾箱中却可能出现非垃圾邮件
场景二:使用布隆过滤器帮助我们标记垃圾网站

理想状态如果我们布隆过滤器已经帮我们标记了所有垃圾网站,那么我们访问的网站未弹出威胁信息,那么这个网站一定是安全的,如果弹出威胁信息,因为存在误判,所以这个网站可能是安全的
场景三:使用布隆过滤器标记空查询

理想状态如果我们布隆过滤器已经帮我们标记了所有查询,那么如果我们进行查询时如果这条数据不在数据库中就直接返回,如果误判为在的话,我们再进行数据库中的查找,若不在则返回。

(博主看了其他优秀文章后觉得收获很多,布隆过滤器还挺有意思的,有问题的希望小伙伴们提出来,博主一定虚心改正)

你可能感兴趣的:(C++,过滤器)