海量数据处理利器之布隆过滤器

看见了海量数据去重,找到停留时间最长的IP等问题,有博友提到了Bloom Filter,我就查了查,不过首先想到的是大叔,下面就先看看大叔的风采。

一、布隆过滤器概念引入

(Bloom Filter)是由布隆(Burton Howard Bloom)在1970年提出的。它实际上是由一个很长的二进制向量和一系列随机映射函数组成,布隆过滤器可以用于检索一个元素是否在一个集合中。它的优点是空间效率和查询时间都远远超过一般的算法,缺点是有一定的误识别率(假正例False positives,即Bloom Filter报告某一元素存在于某集合中,但是实际上该元素并不在集合中)和删除困难,但是没有识别错误的情形(即假反例False negatives,如果某个元素确实在该集合中,那么Bloom Filter 是不会报告该元素不存在于集合中的,所以不会漏报)。

下面从简单的排序谈到BitMap算法,再谈到数据去重问题,谈到大数据量处理利器:布隆过滤器。

  • 对无重复的数据进行排序

给定数据(2,4,1,12,9,7,6)如何对它排序?

方法1:基本的排序方法包括冒泡,快排等。

方法2:使用BitMap算法

方法1就不介绍了,方法2中所谓的BitMap是一个位数组,跟平时使用的数组的唯一差别在于操作的是位。首先是开辟2个字节大小的位数组,长度为12(该长度由上述数据中最大的数字12决定的),然后,读取数据,2存放在位数组中下标为1的地方,值从0改为1,4存放在下标为3的地方,值从0改为1....最后,读取该位数组,得到排好序的数据是:(1,2,4,6,7,9,12)。

比较方法1和方法2的差别:方法2中,排序需要的时间复杂度和空间复杂度很依赖与数据中最大的数字比如12,因此空间上讲需要开2个字节大小的内存,时间上需要遍历完整个数组。当数据类似(1,1000,10万)只有3个数据的时候,显然用方法2,时间复杂度和空间复杂度相当大,但是当数据比较密集时该方法就会显示出来优势。

  • 对有重复的数据进行判重

数据(2,4,1,12,2,9,7,6,1,4)如何找出重复出现的数字?

首先是开辟2个字节大小的位数组,长度为12(该长度由上述数据中最大的数字12决定的,当读取完12后,当读取2的时候,发现数组中的值是1,则判断出2是重复出现的。

二、布隆过滤器原理

布隆过滤器需要的是一个位数组(这个和位图有点类似)和k个映射函数(和Hash表类似),在初始状态时,对于长度为m的位数组array,它的所有位都被置为0。对于有n个元素的集合S={s1,s2......sn},通过k个映射函数{f1,f2,......fk},将集合S中的每个元素sj(1<=j<=n)映射为k个值{g1,g2......gk},然后再将位数组array中相对应的array[g1],array[g2]......array[gk]置为1;如果要查找某个元素item是否在S中,则通过映射函数{f1,f2.....fk}得到k个值{g1,g2.....gk},然后再判断array[g1],array[g2]......array[gk]是否都为1,若全为1,则item在S中,否则item不在S中。这个就是布隆过滤器的实现原理。

当然有读者可能会问:即使array[g1],array[g2]......array[gk]都为1,能代表item一定在集合S中吗?不一定,因为有这个可能:就是集合中的若干个元素通过映射之后得到的数值恰巧包括g1,g2,.....gk,那么这种情况下可能会造成误判,但是这个概率很小,一般在万分之一以下。

很显然,布隆过滤器的误判率和这k个映射函数的设计有关,到目前为止,有很多人设计出了很多高效实用的hash函数。尤其要注意的是,布隆过滤器是不允许删除元素的(实际就是因为多个str可能都应设在同一点,而判断str存在的话是所有映射点都存在,所以不能删除),因为若删除一个元素,可能会发生漏判的情况。不过有一种布隆过滤器的变体Counter Bloom Filter,可以支持删除元素,感兴趣的读者可以查阅相关文献资料。

三、布隆过滤器False positives 概率推导

假设 Hash 函数以等概率条件选择并设置 Bit Array 中的某一位,m 是该位数组的大小,k 是 Hash 函数的个数,那么位数组中某一特定的位在进行元素插入时的 Hash 操作中没有被置位为1的概率是:;那么在所有 k 次 Hash 操作后该位都没有被置 "1" 的概率是:;如果我们插入了 n 个元素,那么某一位仍然为 "0" 的概率是:因而该位为 "1"的概率是:;现在检测某一元素是否在该集合中。标明某个元素是否在集合中所需的 k 个位置都按照如上的方法设置为 "1",但是该方法可能会使算法错误的认为某一原本不在集合中的元素却被检测为在该集合中(False Positives),该概率由以下公式确定:

其实上述结果是在假定由每个 Hash 计算出需要设置的位(bit) 的位置是相互独立为前提计算出来的,不难看出,随着 m (位数组大小)的增加,假正例(False Positives)的概率会下降,同时随着插入元素个数 n 的增加,False Positives的概率又会上升,对于给定的m,n,如何选择Hash函数个数 k 由以下公式确定:;此时False Positives的概率为:;而对于给定的False Positives概率 p,如何选择最优的位数组大小 m 呢,;该式表明,位数组的大小最好与插入元素的个数成线性关系,对于给定的 m,n,k,假正例概率最大为:

四、布隆过滤器应用

布隆过滤器在很多场合能发挥很好的效果,比如:网页URL的去重,垃圾邮件的判别,集合重复元素的判别,查询加速(比如基于key-value的存储系统)等,下面举几个例子:

  • 有两个URL集合A,B,每个集合中大约有1亿个URL,每个URL占64字节,有1G的内存,如何找出两个集合中重复的URL。

很显然,直接利用Hash表会超出内存限制的范围。这里给出两种思路:

第一种:如果不允许一定的错误率的话,只有用分治的思想去解决,将A,B两个集合中的URL分别存到若干个文件中{f1,f2...fk}和{g1,g2....gk}中,然后取f1和g1的内容读入内存,将f1的内容存储到hash_map当中,然后再取g1中的url,若有相同的url,则写入到文件中,然后直到g1的内容读取完毕,再取g2...gk。然后再取f2的内容读入内存。。。依次类推,知道找出所有的重复url。

第二种:如果允许一定错误率的话,则可以用布隆过滤器的思想。

  • 在进行网页爬虫时,其中有一个很重要的过程是重复URL的判别,如果将所有的url存入到数据库中,当数据库中URL的数

量很多时,在判重时会造成效率低下,此时常见的一种做法就是利用布隆过滤器,还有一种方法是利用berkeley db来存储url,Berkeley db是一种基于key-value存储的非关系数据库引擎,能够大大提高url判重的效率。

布隆过滤器主要运用在过滤恶意网址用的,将所有的恶意网址建立在一个布隆过滤器上,然后对用户的访问的网址进行检测,如果在恶意网址中那么就通知用户。这样的话,我们还可以对一些常出现判断错误的网址设定一个白名单,然后对出现判断存在的网址再和白名单中的网址进行匹配,如果在白名单中,那么就放行。当然这个白名单不能太大,也不会太大,布隆过滤器错误的概率是很小的。

五、布隆过滤器简单Java实现

package a;

import java.util.BitSet;
/*
 * 存在的问题
 * DEFAULT_LEN长度设置为多少合适呢?
 * 我发现result和DEFAULT_LEN有关,不应该啊,没发现原因
 */
public class BloomFilterTest {
	//30位,表示2^2^30种字符
	static int DEFAULT_LEN = 1<<30;
	//要用质数
	static int[] seeds = {3,5,7,11,17,31};
	static BitSet bitset = new BitSet(DEFAULT_LEN);
	static MyHash[] myselfHash = new MyHash[seeds.length];

	public static void main(String[] args) {
		String str = "[email protected]";

		//生成一次就够了
		for(int i=0; i<seeds.length; i++) {
			myselfHash[i] = new MyHash(DEFAULT_LEN, seeds[i]);
		}
		bitset.clear();
		for(int i=0; i<myselfHash.length; i++) {
			bitset.set(myselfHash[i].myHash(str),true);
		}
		boolean flag = containsStr(str);
		//System.out.println("========================");
		System.out.println(flag);

	}

	private static boolean containsStr(String str) {
		// TODO Auto-generated method stub
		if(null==str)
			return false;
		for(int i=0; i<seeds.length; i++) {
			if(bitset.get(myselfHash[i].myHash(str))==false)
				return false;
		}
		return true;
	}
}
class MyHash {
	int len;
	int seed;

	public MyHash(int len, int seed) {
		super();
		this.len = len;
		this.seed = seed;
	}

	public int myHash(String str) {
		int len = str.length();
		int result = 0;
		//这的len就是str的len,不是成员变量的len
		for(int i=0; i<len; i++) {
			//System.out.println(seed+"oooooooooooo");
			result = result*seed + str.charAt(i);
			//System.out.println(result);
			//长度就是1<<24,如果大于这个数 感觉结果不准确
			//<0就是大于了0x7ffffff
			if(result>(1<<30) || result<0) {
				//System.out.println("-----"+(1<<30));
				System.out.println(result+"myHash数据越界!!!");
				break;
			}
		}
		return (len-1)&result;
	}
}
时间: 2024-10-25 11:58:03

海量数据处理利器之布隆过滤器的相关文章

[算法系列之十]大数据量处理利器:布隆过滤器

[引言] 在日常生活中,包括在设计计算机软件时,我们经常要判断一个元素是否在一个集合中.比如在字处理软件中,需要检查一个英语单词是否拼写正确(也就是要判断 它是否在已知的字典中):在 FBI,一个嫌疑人的名字是否已经在嫌疑名单上:在网络爬虫里,一个网址是否被访问过等等.最直接的方法就是将集合中全部的元素存在计算机中,遇到一个新 元素时,将它和集合中的元素直接比较即可.一般来讲,计算机中的集合是用哈希表(hash table)来存储的.它的好处是快速准确,缺点是费存储空间.当集合比较小时,这个问题

从另一个角度看大数据量处理利器 布隆过滤器

思路:从简单的排序谈到BitMap算法,再谈到数据去重问题,谈到大数据量处理利器:布隆过滤器. 情景1:对无重复的数据进行排序 @给定数据(2,4,1,12,9,7,6)如何对它排序? 方法1:基本的排序方法包括冒泡,快排等. 方法2:使用BitMap算法 方法1就不介绍了,方法2中所谓的BitMap是一个位数组,跟平时使用的数组的唯一差别在于操作的是位. 首先是开辟2个字节大小的位数组,长度为16(该长度由上述数据中最大的数字12决定的)如图         然后,读取数据,2存放在位数组中下

[算法系列之十八]海量数据处理之BitMap

一:简介 所谓的BitMap就是用一个bit位来标记某个元素对应的Value, 而Key即是该元素.由于采用了bit为单位来存储数据,因此在存储空间方面,可以大大节省. 二:基本思想 我们用一个具体的例子来讲解,假设我们要对0-7内的5个元素(4,7,2,5,3)排序(这里假设这些元素没有重复).那么我们就可以采用BitMap的方法来达到排序的目的.要表示8个数,我们就只需要8个bit(1Bytes). (1)首先我们开辟1字节(8bit)的空间,将这些空间的所有bit位都置为0,如下图: (2

海量信息库,查找是否存在(bloom filter布隆过滤器)

Bloom Filter(布隆过滤器) 布隆过滤器用于测试某一元素是否存在于给定的集合中,是一种空间利用率很高的随机数据结构(probabilistic data structure),存在一定的误识别率(false positive),即布隆过滤器报告某一元素存在于某集合中,但是实际上该元素并不在集合中,但是没有错误识别的情形(false negative),即如果某个元素确实没有在该集合中,那么布隆过滤器是不会报告该元素存在于集合中的,没有漏报的情形出现,召回率为百分之百. 算法描述 布隆过

海量数据处理--hash和bit-map

问题实例: 海量日志数据,提取出某日访问百度次数最多的那个IP. 答:对于ip,最多也就2^32个.所以可以很好地通过hash函数映射到内存中,再进行统计. IP最多为2^32个,为4G,一次放入内存中不行,可以采用分而治之的方法,先Hash(IP)/1024,将IP地址分别映射到1024个小文件中,每个文件4M,再将每个小文件中的IP放入内存中,进行hashmap,统计出出现频率最高的那个IP,最后可以得到1024个出现高频的IP,采用冒泡排序,可以迅速找出频率最高的那个IP.1 原理简述:

从hadoop框架与MapReduce模式中谈海量数据处理

前言 几周前,当我最初听到,以致后来初次接触Hadoop与MapReduce这两个东西,我便稍显兴奋,觉得它们很是神秘,而神秘的东西常能勾起我的兴趣,在看过介绍它们的文章或论文之后,觉得Hadoop是一项富有趣味和挑战性的技术,且它还牵扯到了一个我更加感兴趣的话题:海量数据处理. 由此,最近凡是空闲时,便在看“Hadoop”,“MapReduce”“海量数据处理”这方面的论文.但在看论文的过程中,总觉得那些论文都是浅尝辄止,常常看的很不过瘾,总是一个东西刚要讲到紧要处,它便结束了,让我好生“愤懑

从Hadoop框架与MapReduce模式中谈海量数据处理(含淘宝技术架构)

从hadoop框架与MapReduce模式中谈海量数据处理 前言 几周前,当我最初听到,以致后来初次接触Hadoop与MapReduce这两个东西,我便稍显兴奋,认为它们非常是神奇,而神奇的东西常能勾起我的兴趣,在看过介绍它们的文章或论文之后,认为Hadoop是一项富有趣味和挑战性的技术,且它还牵扯到了一个我更加感兴趣的话题:海量数据处理. 由此,近期凡是空暇时,便在看"Hadoop","MapReduce""海量数据处理"这方面的论文.但在看论

从Hadoop骨架MapReduce在海量数据处理模式(包括淘宝技术架构)

从hadoop框架与MapReduce模式中谈海量数据处理 前言 几周前,当我最初听到,以致后来初次接触Hadoop与MapReduce这两个东西,我便稍显兴奋,认为它们非常是神奇.而神奇的东西常能勾起我的兴趣.在看过介绍它们的文章或论文之后,认为Hadoop是一项富有趣味和挑战性的技术,且它还牵扯到了一个我更加感兴趣的话题:海量数据处理. 由此,近期凡是空暇时,便在看"Hadoop"."MapReduce""海量数据处理"这方面的论文.但在看论

海量数据处理之从Hadoop框架与MapReduce模式中谈海量数据处理(淘宝技术架构)

几周前,当我最初听到,以致后来初次接触Hadoop与MapReduce这两个东西,我便稍显兴奋,觉得它们很是神秘,而神秘的东西常能勾起我的兴趣,在看过介绍它们的文章或论文之后,觉得Hadoop是一项富有趣味和挑战性的技术,且它还牵扯到了一个我更加感兴趣的话题:海量数据处理. 由此,最近凡是空闲时,便在看"Hadoop","MapReduce""海量数据处理"这方面的论文.但在看论文的过程中,总觉得那些论文都是浅尝辄止,常常看的很不过瘾,总是一个东