过滤器系列(一)—— Bloom filter
因为要做过滤器相关内容,最近读了一些过滤器方面的文章,准备从中提取主要思想写几篇博客。
作为这系列的第一篇文章,首先得讲一下过滤器是干什么用的。从历史发展来看,过滤器最早出现是作为散列表的替代品,那么功能就要和散列表差不多,主要是查询当前的元素是否在我已知的集合里。但是随着数据量不断增大,散列表相对来说占用空间过大,而空间占用小的查找树的\(O(logn)\)时间复杂度又太高。于是有人想出来能否用正确率做代价,换取较高的查询速度和较小的存储占用,这就是过滤器。当然,这里所允许的错误仅限假阳性,例如我们做一个关于代理ip地址的过滤器,当有一个不是代理的ip地址发来,我们也许会把它错认成是代理ip,但是我们不会允许一个代理ip被错认成非代理ip,简单的说,就是宁可错杀,不可放过。
作为第一篇,按照历史角度,先说布隆过滤器(bloom filter)。原版的布隆过滤器很朴素,只支持插入和查询两个操作,下面我们看它的原理。
首先,布隆过滤器申请了一片空间,存了一个数组,每个元素都只有1个bit,共有N个元素,初始化每个值都为0。如下图所示。(实际并没有index这一行,仅仅是为了方便观看)

插入操作
下一步就是如何插入数据。布隆过滤器要求你事先定义K个Hash函数,这K个Hash函数都是从定义域映射到上图中的index空间(即N)。通过这K个Hash函数,我们对一条新的数据x,计算出\(h_0(x),h_1(x),....h_{k-1}(x)\),这样就得到了K个地址。我们将这K个地址的比特位置1.这里就有值得注意的地方,因为我们的过滤器的大小远远小于数据集大小,那么常常会有Hash之后映射到同一个位置的数据,不要担心,照常置1。
下面的例子是K=3,\(h_0(x)=2,h_1(x)=5,h_2(x)=7\)。如图所示

查找操作
当插入其他一些数据后,过滤器可能变成下图所示,我们不关心中间经历了什么。

我们现在查找刚才第一次插入的数据是否在过滤器中,那么同样计算\(h_0(x),h_1(x),h_2(x)\),算出3个地址,2,5,7,去表中查找,若3个地址的数据都为1,则判断在过滤器中,否则判断不在过滤器中。
算法和数据结构都很简单,我们下面说的是对布隆过滤器的一些分析和题外话,有兴趣的读者可以继续阅读。
我们在过滤器上很关注三个指标,一个是操作的时间复杂度,一个是平均每条数据占用的比特数,最后是错误率。下面我们分析一下。
时间复杂度
布隆过滤器上的两个操作,插入和查询,都只是计算一下K个Hash函数的值,然后进行K次访存操作。那么时间上很明显是\(O(K)\),其实不算也知道,一个替代Hash表的过滤器,操作代价必须是常数级别。
平均每条数据占用的比特数 and 错误率
直觉上,很容易得出这两个衡量指标其实是矛盾的,当想要较低错误率时就要增大空间;想要减小占用空间时,那么由于Hash碰撞的次数变多,错误率也会提高。我们在这里将错误率作为已知来计算平均每条数据占用的比特数。为什么这么做?因为在实际应用中我们可以对过滤器设定一个错误率作为标准,通常情况下我们对这一点要求更严格。
我们设数组总大小为\(N\),插入n条数据后表中还为0的数据占全部的比例为\(\phi\)。那么
\(\phi = (1-K / N)^n\)-------------------------(1)
读者可以想想为什么不是\(K * n / N\),在这里,我们其实省略了Hash函数默认是随机分布到全空间的。
设错误率为\(P\),
\(P = (1-\phi)^K\) ----------------------------(2)
错误只发生随机分布到K个地址,结果在K个地址都有数据用了,那么不管你是否在过滤器中,布隆过滤器都会判断你在其中,这就是错误来源。
然后我们对(1)式两边取对数
\(log_2^\phi = log_2^{(1-K/N)^n}\)
使用换底公式
\(log_2^\phi = log_2^{(1-K/N)^n} = log_e^{(1-d/N)^n} * log_2^e = -n * K / N *log_2^e\) ---(3)
我们要求的平均每条数据占用的比特数\(N(bit) / n = log_2^{1/P} * log_2^e / (log_2^\phi * log_2^{(1-\phi)})\),通过极值点计算可以得到分母最大时,\(\phi=0.5\),分母为1,则结果为\(N/n = log_2^{1/P} / ln2\)
可以看到,每条数据占用的比特数与错误率的对数成反比。
之后我会先把几个不同思想的过滤器介绍一遍,最后会有关于布隆过滤器的一些变形
过滤器系列(一)—— Bloom filter的更多相关文章
- 浅谈布隆过滤器Bloom Filter
先从一道面试题开始: 给A,B两个文件,各存放50亿条URL,每条URL占用64字节,内存限制是4G,让你找出A,B文件共同的URL. 这个问题的本质在于判断一个元素是否在一个集合中.哈希表以O(1) ...
- Bloom Filter 布隆过滤器
Bloom Filter 是由伯顿.布隆(Burton Bloom)在1970年提出的一种多hash函数映射的快速查找算法.它实际上是一个很长的二进制向量和一些列随机映射函数.应用在数据量很大的情况下 ...
- 【转】Bloom Filter布隆过滤器的概念和原理
转自:http://blog.csdn.net/jiaomeng/article/details/1495500 之前看数学之美丽,里面有提到布隆过滤器的过滤垃圾邮件,感觉到何其的牛,竟然有这么高效的 ...
- 布隆过滤器(Bloom Filter)详解——基于多hash的概率查找思想
转自:http://www.cnblogs.com/haippy/archive/2012/07/13/2590351.html 布隆过滤器[1](Bloom Filter)是由布隆(Burton ...
- 布隆过滤器(Bloom Filter)的原理和实现
什么情况下需要布隆过滤器? 先来看几个比较常见的例子 字处理软件中,需要检查一个英语单词是否拼写正确 在 FBI,一个嫌疑人的名字是否已经在嫌疑名单上 在网络爬虫里,一个网址是否被访问过 yahoo, ...
- 布隆过滤器(Bloom Filter)
一.布隆过滤器介绍 Bloom Filter是一种空间效率很高的随机数据结构,Bloom Filter可以看做是对bit-map的扩展,它的原理如下: 当一个元素被加入集合时,通过K个Hash函数将这 ...
- [转载] 布隆过滤器(Bloom Filter)详解
转载自http://www.cnblogs.com/haippy/archive/2012/07/13/2590351.html 布隆过滤器[1](Bloom Filter)是由布隆(Burton ...
- 布隆过滤器(Bloom Filter)详解
直观的说,bloom算法类似一个hash set,用来判断某个元素(key)是否在某个集合中.和一般的hash set不同的是,这个算法无需存储key的值,对于每个key,只需要k个比特位,每个存储一 ...
- 海量信息库,查找是否存在(bloom filter布隆过滤器)
Bloom Filter(布隆过滤器) 布隆过滤器用于测试某一元素是否存在于给定的集合中,是一种空间利用率很高的随机数据结构(probabilistic data structure),存在一定的误识 ...
随机推荐
- HDU 4745 Two Rabbits(区间DP,最长非连续回文子串)
Two Rabbits Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others) Total ...
- 记一次踩坑:使用ksoap-android时造成的okhttp依赖冲突问题
项目中需要调用webservice接口,android SDK中并没有直接访问webservice接口的方法,于是我引入了ksoap-android的jar包,来实现访问webservice接口.刚开 ...
- Scala使用JUnit4单元测试
在项目开发中在很多地方都要做单元测试,在做Spark项目时使用Scala开发.所以总结一下Scala中的单元测试: 在Maven pom文件中添加依赖: <dependency> < ...
- 高性能Web服务器Nginx
高性能Web服务器Nginx介绍 Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,并在一个BSD-like 协议下发行.其特点是占有内存少,并发能力强 ...
- python2.7多线程的批量操作远程服务器
#!/usr/bin/env python #-*- coding:utf-8 -*- #多线程批量远程执行一条命令 # made in china import threading import s ...
- mongodb安装及副本集搭建
mongodb下载地址:https://www.mongodb.com/dr/fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel62-3.2.7.tg ...
- 系统管理命令之id
当我们想知道某个用户的UID和GID时id命令是非常有用的.一些程序可能需要UID/GID来运行.id使我们更加容易地找出用户的UID以GID而不必在/etc/group文件中搜寻. 1.获取指定用户 ...
- Spring整合Mybatis 之分页插件使用
[分页插件项目中的正式代码一共有个5个Java文件,这5个文件的说明如下] Page<E>[必须]:分页参数类,该类继承ArrayList,虽然分页查询返回的结果实际类型是Page< ...
- 牛客国庆集训派对Day5 Solution
A 璀璨光滑 留坑. B 电音之王 蒙特马利大数乘模运算 #include <bits/stdc++.h> using namespace std; typedef long ...
- ACM ICPC, JUST Collegiate Programming Contest (2018) Solution
A:Zero Array 题意:两种操作, 1 p v 将第p个位置的值改成v 2 查询最少的操作数使得所有数都变为0 操作为可以从原序列中选一个非0的数使得所有非0的数减去它,并且所有数不能 ...