什么是布隆过滤器
布隆过滤器是由很长的二进制向量和多个随机映射函数组成的,用于判断集合中是否存在某元素。
优点
- 是可以快速的查找和插入
- 占用空间少
空间存储和查找/插入复杂度都是常数
缺点
不可以删除并且有一定的误差(误差率可由二进制向量的长度和随机映射函数控制,且随着插入元素的增多误差率会扩大)
原因:是因为删除首先要保证元素一定要在这个集合中,但是由于布隆过滤器的误差性,导致无法做到删除元素。
布隆过滤器的实现原理
布隆过滤器是通过hash函数将元素映射到bitArray上的一个点,这样就可以通过判断是否该位置上的数是否为1来判断集合中是否有该元素。而对于多个hash函数来讲,就是将元素通过多个hash函数映射到bitArray上,然后判断这些位是否为1,进行元素的查找。
为什么使用多个hash函数
因为使用hash函数就存在hash冲突的问题,如果是hash函数过少的话,那么发生hash冲突的可能性就越大,那么误差率也会越大。所以要根据预期误差率选择合适的hash函数个数。
比如若我们的hash函数足够优秀(能够随机分配到每一个点),那么在一个hash函数的情况下,某一点为1的概率为1/m,如果有k个函数,那么k个位置都为1的概率为
(
1
/
m
)
k
(1/m)^k
(1/m)k以次来降低冲突的概率,并且更好的利用空间。当然,hash函数的个数也不能过高,因为这样会导致位的长度不够,误差率增大。
所以要根据位长和误差率决定k的个数。
这个要根据具体的情况,样本集的大小,以及允许的误差率来确定
数学推导
- 误差率
设有n个key,位长为m,hash函数的个数是k个,失误率为p
假设hash函数足够优秀(落在每个点的概率相同),n和k已知,对于一个hash函数,某一位被置为的概率为1/m,不被置于1的概率为 1 − 1 m 1-{1 \over m} 1−m1,而对于k个hash函数,某一位不被置于1的概率为 ( 1 − 1 m ) k (1-{1 \over m})^k (1−m1)k插入n个key,某一位不被置为1的概率为 ( 1 − 1 m ) k n (1-{1\over m})^{kn} (1−m1)kn则被置为1的概率为 1 − ( 1 − 1 m ) k n 1-(1-{1 \over m})^{kn} 1−(1−m1)kn那么查找一个key,出现误差的概率为 ( 1 − ( 1 − 1 m ) k n ) k (1-(1-{1 \over m})^{kn})^k (1−(1−m1)kn)k - 计算最小误差率
因为 lim x → 0 ( 1 + x ) 1 / x = e \lim_{x \to 0}(1+x)^{1/x}=e x→0lim(1+x)1/x=e
所以 ( 1 − ( 1 − 1 m ) k n ) k = ( 1 − ( 1 − 1 m ) − m − k n m ) k (1-(1-{1 \over m})^{kn})^k = (1-(1-{1 \over m})^{-m{-kn\over m}})^k (1−(1−m1)kn)k=(1−(1−m1)−mm−kn)k
当m较大时, 1 m {1} \over {m} m1趋于0,所以上式可推为 ( 1 − e − k n m ) k (1-e^{{-kn\over m}})^k (1−em−kn)k
令a = e − n m e^{- n \over m} em−n,则上式变为 f ( k ) = ( 1 − a k ) k f(k) = (1-a^{k})^k f(k)=(1−ak)k即为误差的概率
下面求 f ( k ) f(k) f(k)的最小值。
所以可知 k = l n 2 ∗ m n k = ln2*{m \over n} k=ln2∗nm p = 2 − l n 2 m n = 2 − k p=2^{-ln2{m \over n}}=2^{-k} p=2−ln2nm=2−k
由第二个可以推出 m = − l n p ∗ n l n 2 2 m = -{{lnp*n}\over ln^22} m=−ln22lnp∗n
使用
当给出允许的误差率p,和key的个数n后,通过公式推导出m的大小,然后根据内存限制,对m向上取整,然后根据m,和n求的k的个数,以及真正的误差率。
空间占用情况
例如:有10亿数据,p=0.001,可计算m约为1797198446个bit位,约为1.8G,很少了。
如何选择较好的Hash函数
尽量选择一些优秀的hash函数(即尽量均匀分布),每个key等概率的分布各个槽点。
MurmurHash,Fnv等
无法删除的问题
https://cloud.tencent.com/developer/article/1136056
插入问题
应用场景
- 网页爬虫对URL的去重,避免爬去相同的URL地址
- 垃圾邮件过滤,从数十亿个垃圾邮件列表中判断某邮箱是否是垃圾邮箱
- 解决数据库缓存击穿,黑客攻击服务器时,会构建大量不存在于缓存中的key向服务器发起请求,在数据量足够大的时候,频繁的数据库查询会导致挂机。
白名单
黑名单的对立面,黑名单是指在黑名单的不能访问,不在黑名单的可以访问,白名单是指在白名单的可以访问,不再白名单的不可以访问。
可用来减少黑名单误差,将可能的误差数据放入白名单,这样若判断数据在黑名单里,那么在判断是否在白名单了,如果在,则应该访问。