d-Left Counting Bloom Filter (3)

  
通过以上的介绍,d-left counting bloom filter的主要思路已经呈现出来了,那就是利用d-left hashing的方法存储fingerprint。下面我们就总结一下d-left counting bloom filter的构造过程。
 
首先我们使用一个d-left哈希表,表中每个bucket可以容纳若干个(固定数量的)cell,每个cell的位数固定,包括一个fingerprint和一个counter。包含一个fingerprint或许你可以理解,可以为什么还要包含一个counter呢?很简单,就是为了处理碰撞(collision)。在d-left哈希表的d个子表中,每个子表都要处理碰撞的情况。在某一个子表出现碰撞时,会发现已经有同样的fingerprint被存储到同一位置,因此,有了counter只需把counter的值加1即可。
 
在没有应用d-left hashing的情况下,我们使用一个哈希函数,把它的hash value分成两段,高位作存储地址,低位作fingerprint。现在要应用d-left hashing,有d个存储地址需要生成,我们仍然用一个哈希函数,但把它的hash value分成d+1段:高位的d段分别用作d个存储地址,每个子表对应一个,剩下的低位部分作为fingerprint。
 
在添加一个key时,先对它作一次hash,得到d个存储位置和一个fingerprint,然后判断d个位置中的负载情况,并在负载最轻的几个位置中选择最左边的插入。如果选择的位置已经存储了相同的fingerprint,就把那个cell的counter加1。在删除一个key时,同样地作一次hash,然后在d个存储位置查找相应的fingerprint,如果找到就将这个cell置空或者将相应的counter减1。
 
一切看上去都很完美,d-left counting bloom filter的构造似乎也已经完成。但实际上,上面的构造过程中有一个缺陷,这个缺陷会在从集合中删除元素时出现。下面举一个例子演示这个缺陷如何出现。
 
假设有一个元素x要插入表中,它的d个存储位置对应每个子表的第一个bucket,它的fingerprint是a。再假设根据负载情况,x的fingerprint被存储到了最后一个子表的第一个bucket中。现在又有一个元素y要插入到表中,它的d个存储位置对应第i个子表的第i个bucket,它的fingerprint也是a。注意,由于x被存储在最后一个子表的第一个而非第d个bucket(对应y的位置选择),在插入y时,y根本感觉不到x的存在。假设根据负载情况,y的fingerprint被存储在第一个子表的第一个bucket中,现在我们来看看在删除x时会出现什么情况。很明显,删除x时我们会发现两个完全相同的fingerprint:一个在第一个子表中,另一个在最后一个子表中。我们该删除哪个?
 
简单概括上面的例子,x和y本不相同,但hash后的fingerprint相同。它们的d个位置选择中有一个重合,x不选择重合的位置,y选择重合的位置。这样就造成了我们在删除x时无法判断到底该删除哪个fingerprint。这个缺陷对上面的构造过程提出了挑战,但是别担心,扑救的办法还是有的。

你可能感兴趣的:(filter,存储)