跳转至

布隆过滤器

原理

当一个元素被加入集合时,通过 K个 Hash 函数将这个元素映射成一个位阵列(Bit array)中的 K 个点,把它们置为 1。检索时,我们只要看看这些点是不是都是 1 就(大约)知道集合中有没有它了:

  • 如果这些点有任何一个 0,则被检索元素一定不在;
  • 如果都是 1,则被检索元素很可能在。

误算率

假设Bit Array位数为m, 插入元素个数为n,Hash函数个数为k

说明 计算公式
n次插入,某个位置被置成1的概率 \(P=1-(1-\frac{1}{m})^{kn}=1-(1-\frac{1}{m})^{m(\frac{kn}{m})} \approx 1-e^\frac{-kn}{m}\)
误判的概率 \(p^k=(1-e^\frac{-kn}{m})^k\),当 \(k = m /n * ln 2 = 0.7m/n\) 时,概率最小(取对数,求导=0)
误判率 < 1 / 2,则 \(ln 2 * \frac{m}{n} > 1\)

注: \(lim (1+\frac{1}{x})^x = e\)

缺点:

  • 随着存入的元素数量增加,误算率随之增加;(建立白名单)

  • 一般情况下不能从布隆过滤器中删除元素;

误算率表

m/n k k=1 k=2 k=3 k=4 k=5 k=6 k=7 k=8
2 1.39 0.393 0.400
3 2.08 0.283 0.237 0.253
4 2.77 0.221 0.155 0.147 0.160
5 3.46 0.181 0.109 0.092 0.092 0.101
6 4.16 0.154 0.0804 0.0609 0.0561 0.0578 0.0638
7 4.85 0.133 0.0618 0.0423 0.0359 0.0347 0.0364
8 5.55 0.118 0.0489 0.0306 0.024 0.0217 0.0216 0.0229
9 6.24 0.105 0.0397 0.0228 0.0166 0.0141 0.0133 0.0135 0.0145
10 6.93 0.0952 0.0329 0.0174 0.0118 0.00943 0.00844 0.00819 0.00846
11 7.62 0.0869 0.0276 0.0136 0.00864 0.0065 0.00552 0.00513 0.00509
12 8.32 0.08 0.0236 0.0108 0.00646 0.00459 0.00371 0.00329 0.00314
13 9.01 0.074 0.0203 0.00875 0.00492 0.00332 0.00255 0.00217 0.00199
14 9.7 0.0689 0.0177 0.00718 0.00381 0.00244 0.00179 0.00146 0.00129
15 10.4 0.0645 0.0156 0.00596 0.003 0.00183 0.00128 0.001 0.000852
16 11.1 0.0606 0.0138 0.005 0.00239 0.00139 0.000935 0.000702 0.000574
17 11.8 0.0571 0.0123 0.00423 0.00193 0.00107 0.000692 0.000499 0.000394
18 12.5 0.054 0.0111 0.00362 0.00158 0.000839 0.000519 0.00036 0.000275
19 13.2 0.0513 0.00998 0.00312 0.0013 0.000663 0.000394 0.000264 0.000194
20 13.9 0.0488 0.00906 0.0027 0.00108 0.00053 0.000303 0.000196 0.00014
21 14.6 0.0465 0.00825 0.00236 0.000905 0.000427 0.000236 0.000147 0.000101
22 15.2 0.0444 0.00755 0.00207 0.000764 0.000347 0.000185 0.000112 7.46e-05
23 15.9 0.0425 0.00694 0.00183 0.000649 0.000285 0.000147 8.56e-05 5.55e-05
24 16.6 0.0408 0.00639 0.00162 0.000555 0.000235 0.000117 6.63e-05 4.17e-05
25 17.3 0.0392 0.00591 0.00145 0.000478 0.000196 9.44e-05 5.18e-05 3.16e-05
26 18 0.0377 0.00548 0.00129 0.000413 0.000164 7.66e-05 4.08e-05 2.42e-05
27 18.7 0.0364 0.0051 0.00116 0.000359 0.000138 6.26e-05 3.24e-05 1.87e-05
28 19.4 0.0351 0.00475 0.00105 0.000314 0.000117 5.15e-05 2.59e-05 1.46e-05
29 20.1 0.0339 0.00444 0.000949 0.000276 9.96e-05 4.26e-05 2.09e-05 1.14e-05
30 20.8 0.0328 0.00416 0.000862 0.000243 8.53e-05 3.55e-05 1.69e-05 9.01e-06

k个Hash函数的选择

《Less Hashing, Same Performance: Building a Better Bloom Filter》提出的一个技巧,可以用2个哈希函数来模拟k个哈希函数,即gi(x) = h1(x) + i * h2(x),其中0<=i<=k-1,可以参考Google Guava中的Bloom Filter的实现。

​ 假如,你有一个哈希函数f,它的输出域是\(2^{64}\),也就是16字节的字符串,每个位置上是16进制的数字0-9,a-f。

我们将这16字节的输出域分为两半,高八位和低八位是相互独立的(这16位都相互独立)。这样,我们将高八位作为新的哈希函数f1的输出域,低八位作为新的哈希函数f2的输出域,得到两个新的哈希函数,它们之间相互独立。

​ 故此可以通过以下算式得到1000个哈希函数:

f1+1*f2=f3
f1+2*f2=f4
f1+3*f2=f5