前言
前段时间惊喜的获得了腾讯的面试机会,面试过程中面试官提到了布隆过滤器 ,当时一点都没有听说过,遂决定抽时间整理一下。没想到的是后面几天接二连三的面试没有来得及整理,在和百世集团的面试官闲聊期间,竟然又提到了布隆过滤器。可能这就是一段特别的缘分吧。下边就是我的总结和整理。
背景
大数据时代到来之后,信息爆炸式的增长,编程中需要处理的数据规模也变得越来越大。在开发过程中,经常需要判断元素是不是已经在集合中存在,这时我们第一反应想到的是使用哈希表(hash table, 也成为散列表)或者与其相似的结构进行查重,但是数据量一旦增大,事情就没有我们想象的这么简单了。
举例来说:我们使用哈希表来判断一条url,是否在一亿个url中重复。首先我们需要用哈希表来存储一亿个url,假设每个url的平均大小为16个字节,一亿条的数据将占用1.6GB的内存(16byte × 1 0 8 10^{8} 108),此时别忘了,哈希表是有存储效率的,Java中的使用链式冲突解决法的HashMap的扩容因子默认为0.75,如果使用其他的方法解决冲突,存储效率可能会更低。
对于一亿的数据量所需要的内存就十分大,那么对于更高的十亿、一百亿的数据就可能超出一般计算机的处理能力。而使用布隆过滤器就可以以较低的代价来解决同样的问题。
简介
布隆过滤器(Bloom Filter)是由伯顿·布隆(Burton Bloom)于1970年提出的。它实际上是一个很长的二进制向量和一系列随机映射函数。布隆过滤器可以用于检测一个元素是否在一个集合中。
原理
我们接着使用“背景”中提到的场景阐述布隆过滤器的原理。
- “背景”中我们需要存储一个亿的url,先建立一个16亿bit的向量(至于为什么是16亿bit,我们在下边接着解释),也就是2亿字节的向量,并将向量中的所有位清零。
- 对于一个url,我们使用8个不同的随机数产生器( f 1 f_{1} f1, f 2 f_{2} f2, … , f 8 f_{8} f8)生成八个对应的信息指纹。
- 再使用一个随机数产生器G把8个信息指纹映射到1-16亿中的8个整数上,并把对应的位置为1。
- 对一亿个url重复执行上述操作。
具体结构如下图所示:
经过这样处理之后,一个针对一亿个url的布隆过滤器就完成了。若需要判断一个url是否在这一亿个url中存在