- 浏览: 108987 次
- 性别:
- 来自: 昆明
文章分类
- 全部博客 (151)
- 120D02 (5)
- 直升机 (1)
- 我的技术资料收集 (82)
- 的技术资料收集 (4)
- .NET Solution (2)
- ASP.NET (1)
- Linq to sql (1)
- 数据库技术(MS SQL) (2)
- 架构/设计 (1)
- 敏捷/持续集成 (1)
- C#.NET开发 (1)
- Matlab开发 (1)
- WinForm开发 (1)
- 开源技术 (1)
- jQuery (1)
- 我的博文 (4)
- js (2)
- android (2)
- 9. 读书笔记 (1)
- CSS3 (1)
- HTML5 (1)
- JavaScript (5)
- 移动开发 (2)
- 编程心得 (1)
- Linux操作系统 (1)
- (BI)商业智能 (1)
- IOS (1)
- Windows Phone (2)
- C# API (1)
- JQuery系列 (1)
- TFS (1)
- C# (2)
- ExtJs (1)
- .NET (1)
- Nginx (1)
- WCF学习笔记 (1)
- Computer Graphic (1)
- IT产品 (1)
- 工具分享 (1)
- MySelf (1)
- C#专栏 (1)
- 管理 (1)
- 基于Oracle Logminer数据同步 (1)
- 日常 (1)
- 实用工具 (1)
- 网页设计 (1)
- avalon (1)
- flash (1)
- DDD (1)
- 01 技术Android (1)
- WCF (1)
- selenium (1)
最新评论
-
464410531:
三国杀。。。。。。。。。。。。。。。。。。。。。。。。。。。。 ...
实用的职场宝典:不提拔你,就因为你只想把工作做好
标题用了了海量数据(Massive datasets)而不用大数据(Big data)。感觉大数据还是略微有点虚,来点实际的。
一、需求
现在我们需要设计一个在线过滤垃圾邮件地址的方案,我们的数据库里面已经有10亿个合法的邮件地址(称为合法地址集S),当有新的邮件发过来时,要检查这个邮件地址是不是在我们的数据库里面,如果在,我们接收邮件,如果不在,我们就把它当做垃圾邮件过滤掉。
二、直觉想到的方法
一拿到这个问题,我就想到了用log(n)的折半查找,先将10亿个邮件地址排序,当收到一个邮件地址时,我利用折半查找,看邮件地址是否在S中,log(1,000,000,000) = 29.89约等于30,对每一个邮件地址我最多也只需要查找30次,感觉也挺快的,应该能满足要求。仔细想一下,折半查找必须放入内存,10个邮件地址还差不多,10亿个邮件地址我们来算一算有多大,邮件地址平均长度按20个字符计算,一个字符占用2Byte,一个email就占了40B,1,000,000,000X40B = 40GB,内存顶得住么,当然可以分多段进行折半,当分段需要多次I/O操作,需要的时间已经不是在线过滤所能承受的了。
三、利用hash处理问题
当数据量很大时,我们一些快速的方法已经不是多给点时间就能解决的,是压根解决不了,折半查找的方法在可接受的范围内是不可行的。我们来介绍一种神奇的方法,利用hash和位图实现常量时间确定邮件地址是否在S中。
1、过滤器初步设计
我们申请一个1GB的内存(虽然大了点,但现在的PC都顶得住了),1B共8位,1GB共有80亿位(实际应该为8X2^30=8,589,934,592位,但为了方便叙述,我们这里用80亿位)这个位图用B表示,B[i]表示位图的第i位;设计一个hash函数,将邮件地址映射到1-80亿的整数空间上。先将80亿位全部置为0,然后对S中的每一个邮件地址进行hash,hash得到一个整数k,就将第k位 置为1,即B[k]=1,如果hash函数设计得好,hash完S后,80亿的位图应该有10亿个(实际值比10亿小,后面会详细分析)位的值为1,当收到邮件时,对邮件地址进行hash,记hash得到的结果为p,如果B[p]=0,则邮件地址一定不再S中,即当作垃圾邮件过滤;如果B[p]=1,则邮件通过过滤,接收邮件。可以结合下图理解:
注意当B[p]=1时,我们并不是说新邮件地址一定在S中,而是说很可能在S中。B[p]=1只能说明S中一定有一个邮件地址URL,使得hash(URL)=p,而这不能保证其他垃圾邮件地址的hash值不等于p。B[p]=0说明S中不存在邮件地址URL,使得hash(URL)=p,从而新邮件地址一定不在S中。因此,被当作垃圾邮件过滤的邮件一定不包含合法的地址,而通过过滤的地址仍然有可能是垃圾邮件地址,大约有1/8(1/8=10亿/80亿,不过实际值比1/8小,后面会详细分析)的垃圾邮件通过过滤,1/8也称为伪阳率。
这样的方案直接上线还是有问题的,因为伪阳率比较高,我们来计算一下照这种方案我们接收的邮件中垃圾邮件的比率是多少。根据新闻报道全球80%的邮件是垃圾邮件,于是P(接收到的垃圾邮件/接收的邮件)=(1/8*80%)/(20%+1/8*80%)=1/3(33.33%),也就是说平均收三封邮件就有一封是垃圾邮件,这对用户来说是不能忍受的,方案必须优化,不过我们应该看到,我们在不漏掉任何一个合法邮件的前提下过滤了7/8的垃圾邮件,已经初显hash利器之锋芒了。
2、伪阳率分析
前面我们提到过伪阳率并不是1/8,它比1/8略小,现在我们从概率的角度来计算一下伪阳率的真实值。
先来看另外一个简单的例子,假设我们有m个飞镖、n个靶,一个射击高手(所谓高手就是无论怎么射击都不会脱靶的神人)把这m个飞镖一个接一个的射向这n个靶,假设一个飞镖击中每个耙的概率相等,问高手射击完之后,某一个靶上面一个飞镖也没有的概率是多少?这个计算并不难,对于任意的一个耙W,被某一个飞镖击中的概率P(耙W被某飞镖击中)=1/n,那么不被某一飞镖击中的概率P(耙W不被某飞镖击中)=1-1/n,射击m个飞镖可以看做是m次独立重复事件,于是P(耙W不被任何一个飞镖击中) = (1-1/n)^m,这也就是某一个耙上面一个飞镖也没有的概率。现在我们再问,某一个飞镖至少有一个飞镖的概率?有了上一步的分析,可以知道p(耙W上至少有一个飞镖)=1-P(耙W不被任何一个飞镖击中)=1- (1-1/n)^m。
现在回到我们之前的问题,我们的80亿个位相当于上例中的n个耙,10亿个合法邮件地址相当于m个飞镖,hash函数相当于射击高手,集合S经过hash后,某一位值为1(即至少被击中一次)的概率P=1-((1-1/8,000,000,000)^1,000,000,000),直接用计算器计算这个值是不现实的,因为1除以80亿已经下溢出为0,再进行10亿次累乘已经没有意义。这个值的计算需要用到极限的知识,伟大的数学家已经帮我们算好了,我们只需要套一下公式,还记得下面这个公式吗:
可以看到0.1175与我们初步估计的1/8=0.125相差并不大,所以我们之前用1/8分析是合理的。
p(某一位值为1)也就是伪阳率,即垃圾邮件被接收的概率,这里再解释一下为什么p(某一位值为1)就是垃圾邮件被接收的概率:我们收到一个新邮件,将地址hash为p,B[p]为1的概率即为我们接受邮件的概率,显然P(B[p]=1)=p(某一位值为1)。
3、优化过滤器,降低伪阳率
前面我们计算过了,按上面的方案,用户平均每接受3封邮件就有1封是垃圾邮件。我们对过滤器进行改进,设置k个hash函数h1,h2,...,hk,每一个hash函数的映射空间都是1-80亿的整数集。对S中的每一个邮件地址都在k个hash函数进行计算,记hash的结果为p1,p2,...,pk,则将对于位 置1,即B[pi]=1(i=1,2,..,k), 当新邮件发来时,我们对新邮件地址也在k个hash函数上计算,同样记hash的结果为p1,p2,...,pk,如果hash结果的所有位都为1,则接受邮件,否则新地址一定不再S中,当作垃圾邮件过滤。当k=2时的示意图如下:
跟1个hash函数一样,设置k个hash函数也不会漏掉任何一个合法邮件,而接受的邮件里仍然还是会有垃圾邮件,现在我们来计算此时的伪阳率,根据前面的分析,对单个hash函数的情况下,一个位为1的概率为P=1-e^(-m/n)。
现在有k个hash函数,相当于我们现在有k*m个飞镖,于是此时某一位为1的概率为P=1-e^(-k*m/n),但此时伪阳率不再等于p(某一位值为1),只有在k个hash结果所在位都为1的情况下我们才接收邮件,而P(k个hash结果所在位都为1)=(1-e^(-k*m/n))^k,因此伪阳率为(1-e^(-k*m/n))^k,当k=2时,伪阳率P=(1-e^(-1/4))^2=0.048929094,这个值比一个hash函数下的0.1175小了很多,那是不是伪阳率也越低呢,我们来看一下曲线图:
发现伪阳率随着k的增大先减小后增大,最后趋于1,最优的k值在5,6之间,但k取整数,因此k=6时伪阳率最小,即设置6个hash函数,可以得到最小的伪阳率,此时伪阳率的值为0.0216。一般情况下,最优值k=ln(2)*n/m,记住这个答案就可以了,如果感兴趣,可以参看下面的计算过程:
现在我们再来计算一下最优情况下k=6时,接收到的垃圾邮件在接收的邮件中的比例 P(接收到的垃圾邮件/接收的邮件)=80%*0.0216/(20%+80%*0.0216)=0.077490775=1/13,即平均每接收13封邮件有一封是垃圾邮件,我感觉这跟我的邮箱情况差不多,达到了用户可以承受的范围。
如果我们申请2G的内存,那么我们有160亿位,k=ln(2)*n/m=ln(2)*16=11.09,即k=10,此时伪阳率p=0.0004587, P(接收到的垃圾邮件/接收的邮件)=80%*0.0004587/(20%+80%*0.0004587)=0.00183144=1/546,也就是说平均接收546封邮件才收到一封垃圾邮件,这已经完全符合业务要求了,要知道这个方案处理速度很快,只需要计算几个hash函数,然后查位图,可在线计算(当然必须提前hash映射S)。
这个多个hash函数的顾虑器称为布隆过滤器(Bloom Filter)。
当有新的合法邮件添加时,将新合法邮件地址添加到S中,并进行k次hash,并将对应位置为1,这样新的合法邮件就不会被过滤,当新合法邮件添加到一定数量时,需要重新计算k,重新hash一遍S。
事实上,更多的垃圾邮件过滤是基于邮件内容的,可以在我们的过滤器过滤之后,进行自然语言处理内容分析过滤,我们的过滤器以及过滤了绝大部分垃圾邮件了。
我们见证了hash了处理海量数据的威力,这只是一个例子,相信大家可以在其他地方也能用的。
最后,我想说,终于发现以前的数学分析、高等代数、概率论有用了,不是吗?
参考资料:
[1].Anand Rajaraman, Jeffrey davaid UIIman. Mining of Massive Datasets. Cambridge University Presss 2012.
[2].维基百科.e (数学常数).https://zh.wikipedia.org/wiki/E_(%E6%95%B0%E5%AD%A6%E5%B8%B8%E6%95%B0). 2013.5.27
[3].Jure Leskovec.Stanford CS246 Mining Massive Data Sets.http://www.stanford.edu/class/cs246/.2013(很好的一门课,推荐)
[4].维基百科.Email spam.https://en.wikipedia.org/wiki/Email_spam.2013.6.21
ps:画图工具:word2010
数据处理:excel2010
感谢条子同学提供的数学证明指导!
感谢关注,欢迎评论。
本文链接:http://www.cnblogs.com/fengfenggirl/p/bloom_filter.html,转载请注明。
发表评论
-
Javascript:猜猜弹出的是啥?为啥? - 幸福框架
2013-06-28 13:33 430原帖地址:http://www.cnblogs.com/hap ... -
C#中WindowsForm常见控件的运用 -- - 李晓峰
2013-06-28 13:27 1747原帖地址:http://www.cnblogs.com/liy ... -
ASP.NET MVC 4 for Visual Studio 2010 下载地址 - 张鸿伟
2013-06-27 11:48 754原帖地址:http://www.cnblogs.com/wei ... -
【ASP.NET Web API教程】6.2 ASP.NET Web API中的JSON和XML序列化 - r01cn
2013-06-26 11:00 919原帖地址:http://www.cnblogs.com/r01 ... -
[珠玑之椟]估算的应用与Little定律 - 五岳
2013-06-26 10:54 639原帖地址:http://www.cnblogs.com/wuy ... -
30行,金额转人民币大写的代码 - 史蒂芬.王
2013-06-26 10:42 1028原帖地址:http://www.cnblogs.com/ste ... -
从银行的钱荒看一个公司的团队建设 产品线过多最终导致最赚钱的项目面临破产 - James Li
2013-06-26 10:36 632原帖地址:http://www.cnblogs.com/Jam ... -
Windows 8 动手实验系列教程 实验6:设置和首选项 - zigzagPath
2013-06-25 13:39 535原帖地址:http://www.cnblogs.com/zig ... -
闲聊可穿戴设备 - shawn.xie
2013-06-25 13:33 615原帖地址:http://www.cnblo ... -
如何使用开源库,吐在VS2013发布之前,顺便介绍下VS2013的新特性"Bootstrap" - 量子计算机
2013-06-25 13:27 869原帖地址:http://www.cnblogs.com/DSh ... -
一步一步将自己的代码转换为观察者模式 - 文酱
2013-06-23 11:36 608原帖地址:http://www.cnblo ... -
iOS内存错误EXC_BAD_ACCESS的解决方法(message sent to deallocated instance) - VicStudio
2013-06-23 11:30 543原帖地址:http://www.cnblogs.com/vic ... -
记录asp.net在IE10下事件丢失排错经过 - Adming
2013-06-23 11:24 710原帖地址:http://www.cnblogs.com/wea ... -
记 FineUI 官方论坛所遭受的一次真实网络攻击!做一个像 ice 有道德的黑客! - 三生石上
2013-06-23 11:18 793原帖地址:http://www.cnblogs.com/san ... -
3、使用Oracle Logminer同步Demo
2013-06-19 10:33 571原帖地址:http://www.cnblogs.com/shi ... -
算法实践——数独的基本解法
2013-06-19 10:27 1450原帖地址:http://www.cnblogs.com/gre ... -
简单实现TCP下的大文件高效传输
2013-06-19 10:21 691原帖地址:http://www.cnblogs.com/sma ... -
avalon - 初步接触
2013-06-18 10:06 783原帖地址:http://www.cnblogs.com/aar ... -
Nginx学习笔记(一) Nginx架构
2013-06-18 09:59 527原帖地址:http://www.cnblogs.com/cod ... -
证书打印《二》
2013-06-17 10:47 532原帖地址:http://www.cnblogs.com/bin ...
相关推荐
海量数据处理是指基于海量数据上的存储、处理、操作,解决方案包括巧妙的算法搭配适合的数据结构,如 Bloom filter/Hash/bit-map/堆/数据库或倒排索引/trie 树,以及大而化小、分而治之的策略。根据数据处理的场景,...
接着,文章介绍了海量数据处理策略,包括基于散列(Hash)的分布存储方式和迁移方式扩容两种方法。基于散列的分布存储方式是通过对Key进行散列算法,将不同的用户数据分散在不同的数据库节点上,以实现高效的数据...
标题中的“python_geohash-0.8.5-cp310-cp310-win_amd64.whl.zip”是一个Python软件包的压缩文件,它包含了Python的Geohash库的一个特定版本(0.8.5)。这个库主要用于处理地理坐标,并将它们转换成可存储和比较的...
标题中的"python_geohash-0.8.5-cp39-cp39-win_amd64.whl.zip"表明这是一个与Python相关的压缩包,其中包含了一个名为"python_geohash-0.8.5-cp39-cp39-win_amd64.whl"的文件,这个文件是Python的轮子(wheel)格式...
标题中的"python_geohash-0.8.5-cp37-cp37m-win_amd64.whl.zip"表明这是一个与Python相关的压缩包,特别提到了`geohash`,它是一个用于处理地理位置数据的库。版本号是0.8.5,`cp37`和`cp37m`指的是它适用于Python ...
Python Geohash是一个用于处理地理坐标数据的Python库,它实现了地理位置编码和解码功能,主要基于Geohash算法。这个特定的版本是`0.8.5`,专为Python 3.12编译,并且适用于Windows操作系统,64位架构(amd64)。`...
python_geohash-0.8.5-cp39-cp39-win_amd64
python_geohash-0.8.5-cp37-cp37m-win_amd64
Python Geohash库是用于处理地理空间数据的工具,它基于一种叫做Geohash的编码技术。Geohash是一种将经纬度坐标转化为可比较的字符串的方法,这种编码方式能够高效地进行地理位置的索引和查询。`python_geohash-...
python_geohash-0.8.5-cp35-cp35m-win_amd64
hashcat + john-1.9.0-jumbo-1-win64, 哈希运算,破解工具
标题中的"python_geohash-0.8.5-cp36-cp36m-win_amd64.whl.zip"表明这是一个与Python相关的库,名为`geohash`,版本为0.8.5。它是一个适用于Python 3.6(cp36代表Python 3.6)且构建于Windows AMD64架构(win_amd64...
python_geohash-0.8.5-cp38-cp38-win_amd64
标题中的"python_geohash-0.8.5-cp311-cp311-win_amd64.whl.zip"是一个Python软件包的压缩文件,它包含了Python的GeoHash库的一个特定版本。GeoHash是一种地理位置编码技术,用于将经纬度坐标转换成可存储和查询的...
对于极大规模的数据集,单机处理能力可能完全无法满足需求,这时可以将数据分布到多台机器上,采用类似于MapReduce的分布式计算框架来并行处理数据,再将结果合并。这种方式不仅能够充分利用计算资源,还能大幅缩短...
- 利用多台计算机并行处理数据。 - MapReduce是一种常用的分布式处理框架。 通过以上解析可以看出,面对海量数据处理的问题,合理利用各种数据结构和算法是非常重要的。不同的应用场景需要选择合适的技术手段来...
### 海量数据处理关键技术解析 #### 一、海量数据处理概述 在当前的大数据时代,数据量的急剧增长使得传统的数据处理技术面临着前所未有的挑战。海量数据处理是指在合理的时间内,对大规模数据集进行高效存储、...
标题中的“使用Hash散列从海量IP地址中查找IP地址”是一个关于数据结构与算法的实践应用,主要涉及如何高效地在大量IP地址中进行查找操作。在这个问题中,使用了哈希(Hash)技术,它是一种将任意大小的数据映射到...