其他分享
首页 > 其他分享> > 布隆过滤器?好像有点局限啊,瞅一瞅布谷鸟过滤器

布隆过滤器?好像有点局限啊,瞅一瞅布谷鸟过滤器

作者:互联网

糗事!本来打算7点左右起床,看书充电的。然,并卵,床铺拖住了我的步伐,结果还是晚了半个小时。8点洗漱,仅仅半个小时的时间,可以说,收获寥寥。这么短的时间,很难深入都某个方面去学习,思考,只是草草过了一些知识点,模模糊糊看了一些东西。

结果,通勤路上,也在纠结者自己的计划与执行力,有句名言怎么说来着?“凡事预则立,不预则废”!这句话的意思是:任何事情,事前有准备就可以成功,没有准备就会失败。说话先有准备,就不会词穷理屈站不住脚;行事前计划先有定夺,就不会发生错误或后悔的事,哲学上反映的是原因和结果的关系。有时候某段时间,常常制定计划,结果一次次在执行前放弃,这个时候,其实已经不仅仅是放弃一次次机会了,似乎也在一点点消磨自己的心气,可能过一段时间之后,“计划”这个词,对我来说,只是一个遥远的记忆吧。

干碗鸡汤吧!给麻木的自己一点点激励。

别让“懈怠”打败你,也别让“拖沓”拖垮你,更不要让“下次”消磨你!

有志者立长志,无志者常立志。

come on ! cheers !

希望这碗鸡汤能引起你的一点共鸣。

好了,来看下今天的主题:布谷鸟过滤器。

之前我们已经看过了布隆过滤器,它通过hash和散列,对已有数据进行标记,通过对比请求数据,最终实现对请求数据过滤的功能。对于网站攻击拦截,数据去重,都有不错的效果。

当然,布隆过滤器也有着自己的局限性,首先就是数据流通性问题,我们知道,目前互联网中,数据时刻都是在流动的,布隆过滤器必须事先将已有的数据提前放入过滤器,之后才能进行过滤,而且,这个过程中,并不能进行删除和修改操作,这样对变化很快的数据来说,是很不友好的。

于是,就有人开始致力于修复这个局限,让布隆过滤器可以进行删除,从而出现了一种布隆过滤器的升级版,count bloom filter!什么意思呢?之前的布隆过滤器不是只占有一个bit位么,现在我把这bit位进行扩展,比如,扩展到4bit位,也就是新的布隆过滤器就是原来的4倍大小。4个bit位,对应的是同一个hash,可以存储的数据大小是0-15(2^4-1),当对数据进行hash,落到这个位置的时候,这个位置的数据就加1,删除的时候就减一,这样就实现了对数据的删除。如下图:

count-bloom-filter示意图

如图,data1的hash命中了第一个位置,于是第一个位置记为1,data1、data2、data3都命中了第三个位置,于是第三个位置记为3(二进制11), data2、data3都命中了第六个位置,于是第六个位置记为2 。

删除的时候,同理,如果删除了某个数据,就在对应的hash位置上的数据减一。比如,上图中,删除了data1,那么,位置一减1,位置三减1,位置五也减1,其他数据并没有影响,不进行操作,这样,便完美的删除了data1。这便是对布隆过滤器的删除功能的实现。

但是,我们发现,这种操作有个很明显的问题,那就是算术溢出。如果操作几十万条数据,刚好hash碰撞频率很高,那么同一个位置,一直加一,最终肯定会有溢出的,比如就以上图为主,一个位置占据4个bit的空间,一旦超过15,再进行累加,数据直接就混乱了。当然,也可以增加存储的bit的空间,但是许多没有命中的明显会有很严重的空间浪费。还有就是bloom filter 不能进行伸缩,也就是不能扩展,所以需要保证最大的元素个数需要提前知道,否则一旦插入的元素超过了容量,误判率将急剧增加。

这个时候,有个牛皮哄哄的卡内基梅隆大学的大神发表了一篇论文:Cuckoo Filter: Practically Better Than Bloom ,用我勉强认识英文单词的水平翻译下就是---布谷鸟过滤器:用起来比布隆过滤器强多了!

前人栽树,后人砍树。人家论文都写好了,咱们就过来瞅瞅呗。至于翻译就算了,我也是从“中间商”那里看到的解释,直接分析这种论文对我来说,呵呵呵!

布谷鸟,布谷鸟大家知道不?好吧,来个更熟悉一点的,“鸠占鹊巢”这个成语大家总知道吧?这个“鸠”说的就是布谷鸟!让我来给大家展示一段详细的解释。

“鸠占鹊巢”成语里的两种鸟,鹊和鸠,其中争议比较小的是鸠,这里的鸠不是指鸠鸽类的斑鸠。而是指俗称布谷鸟的一种杜鹃,古称鸤鸠。吴代陆玑撰毛诗陆疏广要说:“鸠,鸤鸠也。今谓布谷。”诗经曹风里也有用鸤鸠四处下蛋,来比喻儿子不在身边的篇章:“鸤鸠在桑,其子在梅…鸤鸠在桑,其子在棘…鸤鸠在桑,其子在榛。”

意思是鸤鸠 [1]  不会做巢,常强占喜鹊的窠。本指女子出嫁,定居于夫家。后比喻强占别人的住处。出自《诗经·召南·鹊巢》。

先说下布谷鸟过滤器的主要思想,上面我们已经说了count bloom filter,主要缺点是容易溢出,不好扩展,而且可能会有严重的空间浪费。而布谷鸟过滤器呢?让我们来看下论文原作者对布谷鸟过滤器优点的阐述:

  1. 它支持动态添加和删除项;

  2. 它提供了比传统的布隆过滤器更高的查找性能,即使当其接近满载(例如,95%的空间已被使用); 

  3. 它比诸如商过滤器等替代品更容易实现;

  4. 在许多实际应用中,如果目标假阳性率ε小于3%,则它使用的空间小于布隆过滤器。

我们来主要看下,首先是可以动态删除和添加,这个不必多说,其次就是空间利用率。我们知道,布隆过滤器可能会放过不存在的数据,而且布隆过滤器提前把数据放的越满,误判率(假阳性)就越高,如果你把布隆过滤器塞满了,那不用说,这个过滤器卵用都没了。一般来说,布隆过滤器是不能存满超过一半的空间的,也就是说,50%的空间都是浪费掉的。

下面我们来看下布谷鸟过滤器的设计,了解下简单的结构。

布谷鸟过滤器也是根据数据二进制这个特性设计的,不过比布隆过滤器更加精巧一些。它不仅会记录数据的位置信息,还会记录数据的指纹信息。

1

如上图,一个基本的布谷鸟哈希表由一个桶数组组成,每个插入项都有由散列函数h1(x)和h2(x)确定的两个候选桶。 查找过程会检查两个桶是否任意一个桶包含此项。 图1(a)显示将新项 x 插入到8个桶的哈希表中的示例,其中 x 可以放置在桶2或6中。 如果x的两个桶中的任何一个是空的,则算法将x插入到该空桶中,插入完成。如果两个桶都没有空间,如例所示,项选择一个候选桶 (例如桶 6), 踢出去现有的项 (在本例中为“a”) 并将此被踢出项重新插入到它的备用位置。 在我们的例子中,重新放置“a”触发了另一个重置,将现有的项“c”从桶4踢到桶1。这个过程可能会重复,直到找到一个空桶,如图1(b)所示或直到达到最大位移次数(例如在我们的实现中为500次)。如果没有找到空桶则认为此哈希表太满,无法插入。 虽然布谷鸟散列可能执行一系列重置,但其均摊插入时间为O(1)。

     布谷鸟散列确保了高空间占用率,因为它改进了在插入新项时对先前项放置决策。 布谷鸟散列的大多数实际实现是通过使用包含多个项的桶(一般来说是两个桶)来扩展上面的基本描述。在假设所有散列函数都是完全随机的情况下,使用k个哈希函数和大小为b的桶时的最大可能负载已经被分析过了。通过配置适当的布谷鸟哈希表参数,其95%的表空间可以被填充。

简单来说,布谷鸟过滤器是有两个has算法,其中一个是用来计算数据存储的位置,可能也有位运算(类似求余),另一个就是计算数据的指纹信息。比如上图中的a,计算出了对应的hash位置,同时会将指纹信息的一部分,也就是指纹hash计算的值的后几位bit,放入预先准备的空间中。

hash冲突肯定会存在的,但是作者巧妙的设计了计算指纹信息的hash和计算位置的hash,这样最终对比的结果几乎不会一样。而且,两个hash位置h1和h2可以通过一种计算相互转换。

fp = fingerprint(x)
h1 = hash(x)
h2 = h1 ^ hash(fp)  // 异或

h1 = h2 ^ hash(fp)

fp是x的指纹信息,h1是hash 桶数组一的位置(一般会有两个桶,冲突会降低,空间利用率也会提高很多),h2是hash 桶数组二的位置。

指纹计算是求hash,最后根据数组长度进行部分截取,获取其中的一部分二进制数据,存入数组。位置计算的话,也是进行的位运算(这也是布谷鸟过滤器要求长度必须是2的倍数的原因之一),使用的是异或运算。 二进制运算 ,计算机原理里面的东东,什么原码、反码、补码、与、或、非、同或、异或等等,大家应该都明白,之前的聊一聊java线程池ThreadPoolExecutor(二)——线程池状态 里面就有涉及二进制计算,不太明白的可以结合看下,或者去学习下二进制计算。

从上面的公式中可以看到,针对一个数据,有hash,有指纹,若是要发生误判,首先要有hash碰撞,其次,指纹信息也要相同。布谷鸟过滤器作者通过巧妙的设计hash函数,尽可能的规避了这种误判的存在,当然指纹信息越多,存储的信息越精确,越不容易出现假阳性(误判),也就是牺牲空间,提高精确度。空间与精确度之间应该是有一个权衡,以做到最合适的空间大小来完成对数据的过滤。

由于过滤器中存有数据的指纹信息,于是,对数据的增删来说,都是可以的,大大增加了布谷鸟过滤器的灵活性。

查了一圈,似乎没找到java版本的布谷鸟过滤器比较成熟的实现方式jar包【苦笑】,所以使用上,暂时还是建议大家使用布隆过滤器,有一个实现布谷鸟的java实现:https://github.com/MGunlogson/CuckooFilter4J   大家有兴趣的话可以看下。

 

No sacrifice,no victory~

标签:hash,布谷鸟,位置,布隆,过滤器,数据
来源: https://blog.csdn.net/zsah2011/article/details/115376172