Bloom Filter简述

1.适用场景

在极大的数据集合中快速查找某个元素是否存在,但是不要求100%正确.这个是文绉绉的说法,说人话: 一个很理想的场景:分布式缓存

缓存的数据可能很大,QPS也相当的高,比如千万级,那么一般这个缓存集群就会达到近百台机器的规模.能不能少点机器呢? 毕竟找老板要这么多机器,不容易啊,动不动就是KPI导向!

这个时候Bloom Filter就可以上场了

2.横向对比

为了查找某元素是否出现,一般有哪些方法呢?

  • 将所有的数据存起来(比如存数据库),然后直接查询呗: 第一是存不下,第二是找不快
  • 使用Hash结构存储:更加存不下,一般hash空间利用率<=50%, 数据量大了,Hash碰撞也不容小觑
  • 将原始数据md5或者SHA-1,再存hash:MD5结果128Bit, SHA-1结果160Bit,确实比上面的靠谱多了
  • 位向量(将数据哈希值对应的bit位置1):可查证数据显示,要降低冲突发生的概率到1%,就要将BitSet的长度设置为数据总数量的100倍

以上方法都是能百分百准确找到或者找不到元素,空间上多少不尽如人意,但是能百分百准确!可是作为一个缓存服务器,百分百的准确性,有必要么? 为了百分百的准确,多花了多少存储啊!缓存命不中,又不怀孕,是吧? 如果降低5%的准确率,能省20%甚至40%的机器呢?是不是更划算!

3.Bloom Filter原理

布隆过滤器首先是基于上面的方法4,位向量,判断数据的哈希值对应的bit是否为1

改进点在于,使用多个哈希函数,而不是一个

比如数据aaa
index1=func_hash_1(aaa)

index2=func_hash_2(aaa)
那么同时判断bitset[index1]bitset[index2]是否同时为1,就能大致知道aaa是否存在.

判断规则:

  • 只要bitset[index1]活着bitset[index2]任意一个为0,表示数据aaa不存在
  • bitset[index1],bitset[index2]全部同时为1,数据aaa可能存在
    为什么所有的都是1了,只是可能存在呢?仔细想想,每个数据都会被映射到2个标志位,可能刚好index1标志位与bbb的其中一个碰撞(重叠),刚好index2标志位与ccc的其中一个标志位碰撞(重叠).
    再直白一点 A=func1(aaa),  B=func2(aaa),  C=func1(bbb),  D=func2(bbb),AB是数据aaa产生的两个标志位,CD是数据bbb产生的两个标志位.然而很可能aaabbb原始数据都不存在,而是A=func2(ccc),  B=func1(ddd),  C=func2(eee),  D=func1(fff),意思是ccc,ddd,eee,fff分别有一个标志位与aaa,bbb碰撞(重叠),其实aaa,bbb压根不存在

4.Counting Bloom Filter

上面已经举例分析,布隆过滤器存在不准确性,可能误报.误报率是多少,有兴趣额的可以查查,公式就不贴了.

此处另外一个问题,数据一旦写入集合,就不能删除,原因同上面:
ccc,eee,fff,ddd能碰撞虚构出aaa,bbb存在的假象; 那么你删除ccc,ddd,eee,fff时将ABCD标志位置0,也就能虚构aaa,bbb不存在的假象,而此时aaa,bbb可能恰好又倒霉催的真实存在

Counting bloomfilter(CBF),这是一种基本Bloom Filter的变体,CBF将基本Bloom Filter每一个Bit改为一个计数器,出现一个加1,删除一个减1,此时就支持删除数据了

5.数学细节

关于错误率估算,最优的哈希函数个数,位数组的大小,这几个值如何计算调优?鄙人数学不精,不推理公式了,有兴趣的搜索一把,应有尽有

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章