初级5 题目三 认识布隆过滤器

1. 布隆过滤器的使用需求是:查询一个东西是否在一个集合中。例如现在有 100 亿个url被列为黑名单,每次用户访问到该 url 时,返回 false。如果单纯地使用 HashSet,至少 6400 亿字节内存的损耗。而布隆过滤器可以极大程度降低这种内存需求,实现该功能。但布隆过滤器是存在短板的,即失误率。但这种失误率不是被列为黑名单的 url 被判断不在黑名单中, 而是不在黑名单的 url 被判断在了黑名单中。简单来说,就是宁可错杀三千,不放过一个

2. 在面试官问这个问题时,首先讲一下经典解法。然后问面试官,该系统允许较低的失误率吗?如果允许,再说布隆过滤器

3. 首先,介绍一个 bit 数组,如果一个 int[] a = new int [1000],那么这个数组有 32000 个字节数,也就是 1000 大小的 int 数组可以看做是 32000 个大小的 bit 类型数组。如果此时需要将 30000 这个位置 bit 赋值为 1,如何操作?首先用 30000/32,看 30000 这个位置的 bit 在 int 类型数组的哪个位置,之后 30000%32,看 30000 这个 bit 在 int 类型位置的第几个 bit。通过除和模的运算,可以将 30000 这个位置的 bit 赋值为1。注意,1<<16,意思是左移16位,也就是只有第 16 个位置赋值为 1 了,其他还是 0

int[] arr = new int[1000];

int index = 30000;

int intIndex = index / 32;

int bitIndex = index % 32;

arr[intIndex] = (arr[intIndex] | (1 << bitIndex));

 初级5 题目三 认识布隆过滤器_第1张图片

4. 布隆过滤器实际操作便是借助 bit 数组实现的。每个 url 通过 k 个哈希函数计算出 k 个哈希值,然后 k 个哈希值都 % m(m为bit数组的大小),然后将模出来的结果对应的 bit 位置设为1。当所有 url 都这样操作后,这个 bit 数组就是黑名单。如果新来的 url 经过 k 个哈希函数运算后,k 个 bit 位置均为 1,那么这个 url 就是在黑名单之中。由此也可以看出,会存在误伤的现象。如果 m 较小,黑名单的 url 将所有的 bit 位置都置为了1,那么每个新来的 url 都会被当做黑名单。直观上,空间 m 越大,失误率就会越低。

5. 在深入分析 m 和 k 之前,需要注意一点,空间 m 的大小与单个 url 的长度无关,只与 url 的总数量有关。无论单个 url 是 64 字节还是 128 字节,经过哈希运算,结果只有 0 和 1。空间 m 的大小实际上是由url 总数量和预期失误率决定的,m=-\frac{n*lnp}{(ln2)^{2}},其中 n 就是 url 总数量,p 是预期失误率。如果 url 数量 100 亿,p 为 0.0001 时,m 为 131,571,428,572 bit 大小,转为字节约为 16G 大小。和先前的 6400 G相比,所需空间缩小非常多。哈希函数个数 k 的公式为  k=ln2*\frac{m}{n}=0.7*\frac{m}{n},根据所需空间大小和 url 总数量确定,结果向上取整,此处约为 13 个。正因为这样 m 和 k 存在向上取整的情况,所以在选定好 m 和 k 后,实际失误率和预期失误率是有所不同的,此时需要计算实际失误率,公式为 p = (1-e^{-\frac{n*k}{m}})^{k} , 此题为十万分之六,和先前万分之一比,降低了一点。三个公式,决定了布隆过滤器的空间大小,哈希函数个数,实际失误率。

 

 

你可能感兴趣的:(算法,算法)