布隆过滤器(Bloom filter)

判断一个元素是否在某个集合中,是现实生活/软件开发中经常遇到的场景。例如,检查一个面部ID是否在逃犯面部信息集中,检查一个网页是否已经被后端缓存等。在计算机领域,通常采用hash表来解决这类问题。hash的优点是查询快速,理论查询操作是O(1),但缺点也很明显——耗费存储空间,数据规模巨大时尤其明显。在《数学之美》中有如下的例子:

一个像 Yahoo,Hotmail 和 Gmai 那样的公众电子邮件(email)提供商,总是需要过滤来自发送垃圾邮件的人(spamer)的垃圾邮件。一个办法就是记录下那些发垃圾邮件的 email 地址。由于那些发送者不停地在注册新的地址,全世界少说也有几十亿个发垃圾邮件的地址,将他们都存起来则需要大量的网络服务器。如果用哈希表,每存储一亿个 email 地址, 就需要 1.6GB 的内存(用哈希表实现的具体办法是将每一个 email 地址对应成一个八字节的信息指纹 googlechinablog.com/2006/08/blog-post.html,然后将这些信息指纹存入哈希表,由于哈希表的存储效率一般只有 50%,因此一个 email 地址需要占用十六个字节。一亿个地址大约要 1.6GB, 即十六亿字节的内存)。因此存贮几十亿个邮件地址可能需要上百 GB 的内存。除非是超级计算机,一般服务器是无法存储的。

布隆过滤器解决了这个烦恼。

A  Bloom filter is a space-efficient probabilistic data structure, conceived by Burton Howard Bloom in 1970, that is used to test whether an element is a member of a set.  ——维基百科

实现原理

布隆过滤器由一个bitArray(长度m)和一个hash函数集(个数k)组成,bitArray初始化为0,m远大于k. 每一个hash函数都将元素映射为0~m-1之间的一个整数。

添加:对于待添加元素x,依次计算k个hash值,并将hash值对应bitArray中的bit置1.

查询:对于待查询元素y,依次计算k个hash值,并查询bitArray中对应的bit是否全为1,只要有任意一个bit为0,则元素y必然不在集合中;如果全为1,则认为y在集合中。

误判:不在集合中的元素可能被误判为在集合中,因为对于一次查询的k个bit,可能由不同的添加操作而置1. 但反过来,在集合中的元素一定不会被误判。

删除:布隆过滤器不支持删除操作,因为某个bit为1可能与多个添加操作有关,一旦复位为0则会影响多个元素的判断。若非要支持删除,思路之一是增加一个布隆过滤器,记录删除的元素。

由以上可知,布隆过滤器的初衷是,保证快速查询的同时极大的节省存储空间,并以很小的误判率作为代价。并且布隆过滤器并不存储元素本身,对于一些保密要求严格的场景尤其友好。

 

一个实例之布隆过滤器在HBASE中的应用 https://www.jianshu.com/p/0858f9d6a6c2

 

posted @ 2019-02-28 15:14  26号  阅读(162)  评论(0)    收藏  举报