关闭

使用BloomFilter布隆过滤器解决缓存击穿、垃圾邮件识别、集合判重

标签: 布隆过滤器BloomFilter javajava 大数据查重
1781人阅读 评论(1) 收藏 举报
分类:

Bloom Filter是一个占用空间很小、效率很高的随机数据结构,它由一个bit数组和一组Hash算法构成。可用于判断一个元素是否在一个集合中,查询效率很高(1-N,最优能逼近于1)。

在很多场景下,我们都需要一个能迅速判断一个元素是否在一个集合中。譬如:

网页爬虫对URL的去重,避免爬取相同的URL地址;

反垃圾邮件,从数十亿个垃圾邮件列表中判断某邮箱是否垃圾邮箱(同理,垃圾短信);

缓存击穿,将已存在的缓存放到布隆中,当黑客访问不存在的缓存时迅速返回避免缓存及DB挂掉。

可能有人会问,我们直接把这些数据都放到数据库或者redis之类的缓存中不就行了,查询时直接匹配不就OK了?

是的,当这个集合量比较小,你内存又够大时,是可以这样做,你可以直接弄个HashSet、HashMap就OK了。但是当这个量以数十亿计,内存装不下,数据库检索极慢时该怎么办。

以垃圾邮箱为例

方案比较

1.将所有垃圾邮箱地址存到数据库,匹配时遍历
2.用HashSet存储所有地址,匹配时接近O(1)的效率查出来
3.将地址用MD5算法或其他单向映射算法计算后存入HashSet,无论地址多大,保存的只有MD5后的固定位数
4.布隆过滤器,将所有地址经过多个Hash算法,映射到一个bit数组

优缺点

方案1和2都是保存完整的地址,占用空间大。一个地址16字节,10亿即可达到上百G的内存。HashSet效率逼近O(1),数据库就不谈效率了,不在一个数量级。
方案3保存部分信息,占用空间小于存储完整信息,存在冲突的可能(非垃圾邮箱可能MD5后和某垃圾邮箱一样,概率低)
方案4将所有地址经过Hash后映射到同一个bit数组,看清了,只有一个超大的bit数组,保存所有的映射,占用空间极小,冲突概率高。

大家知道,java中的HashMap有个扩容参数默认是0.75,也就是你想存75个数,至少需要一个100的数组,而且还会有不少的冲突。实际上,Hash的存储效率是0.5左右,存5个数需要10个的空间。算起来占用空间还是挺大的。
而布隆过滤器就不用为每个数都分配空间了,而是直接把所有的数通过算法映射到同一个数组,带来的问题就是冲突上升,只要概率在可以接受的范围,用时间换空间,在很多时候是好方案。布隆过滤器需要的空间仅为HashMap的1/8-1/4之间,而且它不会漏掉任何一个在黑名单的可疑对象,问题只是会误伤一些非黑名单对象。

原理

初始化状态是一个全为0的bit数组

为了表达存储N个元素的集合,使用K个独立的函数来进行哈希运算。x1,x2……xk为k个哈希算法。
如果集合元素有N1,N2……NN,N1经过x1运算后得到的结果映射的位置标1,经过x2运算后结果映射也标1,已经为1的报错1不变。经过k次散列后,对N1的散列完成。
依次对N2,NN等所有数据进行散列,最终得到一个部分为1,部分位为0的字节数组。当然了,这个字节数组会比较长,不然散列效果不好。
那么怎么判断一个外来的元素是否已经在集合里呢,譬如已经散列了10亿个垃圾邮箱,现在来了一个邮箱,怎么判断它是否在这10亿里面呢?
很简单,就拿这个新来的也依次经历x1,x2……xk个哈希算法即可。
在任何一个哈希算法譬如到x2时,得到的映射值有0,那就说明这个邮箱肯定不在这10亿内。
如果是一个黑名单对象,那么可以肯定的是所有映射都为1,肯定跑不了它。也就是说是坏人,一定会被抓。
那么误伤是为什么呢,就是指一些非黑名单对象的值经过k次哈希后,也全部为1,但它确实不是黑名单里的值,这种概率是存在的,但是是可控的。





上面的几个图看起来很高深,但那不是我们关心的问题,归根到底意思其实就是你想让错误率降低,就得增大数组的长度,就是这样。
我们使用BloomFilter的目的就是想省空间,所以我们需要做的就是在错误率上做个权衡就OK。
很多时候这个错误率我们是能接受的,譬如垃圾邮箱问题,是坏人一定会被抓,这个能保证。无非是一些好人也被抓,这个可以通过给这些可伶的被误伤的设置个白名单就OK。至于爬虫Url重复这个就更没问题了,会缺掉一些网页而已。
至于在缓存穿透上的应用,是为了避免恶意用户频繁请求缓存中不存在DB也不存在的值,会导致缓存失效、DB负载过大,可以使用BloomFilter把所有数据放到bit数组中,当用户请求时存在的值肯定能放行,部分不存在的值也会被放行,绝大部分会被拦截,这些少量漏网之鱼对于DB的影响就会比大量穿透好的多了。

讲了这么多,可以看到,原理很简单,但要实际做一个BloomFilter可就麻烦了,已经属于科学家的范畴了,好在早早有人已经搞定了java版的实现,用法很简单,下一篇看看。



1
0
查看评论

缓存击穿之布隆过滤器bloom Filter实现方式

一、什么是缓存击穿 查询一个在缓存内必然不存在的数据,导致每次请求都要去存储层去查询,这样缓存就失去了意义。如果在大流量下数据库可能挂掉。缓存击穿是黑客攻击系统的常用手段。 二、怎么解决缓存击穿问题? 采用布隆过滤器来实现。 什么是布隆过滤器? 它是一种空间效率极高的概率型算法和数据结构,...
  • ocean_fan
  • ocean_fan
  • 2017-10-26 10:28
  • 281

如何使用bloomfilter构建大型Java缓存系统

背景 在如今的软件当中,缓存是解决很多问题的一个关键概念。你的应用可能会进行CPU密集型运算。你当然不想让这些运算一边又一边的重复执行,相反,你可以只执行一次, 把这个结果放在内存中作为缓存。有时系统的瓶颈在I/O操作上,比如你不想重复的查询数据库,你想把结果缓存起来,只在数据发生变化时才去数...
  • hit_hlj_sgy
  • hit_hlj_sgy
  • 2014-09-16 12:17
  • 835

缓存穿透和缓存失效的预防和解决

一.缓存穿透: 缓存穿透是指查询一个一定不存在的数据,由于缓存是不命中时需要从数据库查询,查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到数据库去查询,造成缓存穿透。 解决办法: 1.布隆过滤 对所有可能查询的参数以hash形式存储,在控制层先进行校验,不符合则丢弃。还有最常见的则是采...
  • qq_16681169
  • qq_16681169
  • 2017-07-14 23:43
  • 450

谈谈布隆过滤器(比哈希表省很多内存,简言之更牛逼)

之前就阅读过数学之美,知道有这么个强大的工具,可是因为不常用到也就没当回事,最近重新看到它觉得很高大上,就想来mark下设计初衷: (Bloom Filter)是由布隆(Burton Howard Bloom)在1970年提出的,不知道当时布隆为啥想到设计时究竟是碰到了啥问题,但这确实很有效 来...
  • justdoithai
  • justdoithai
  • 2016-04-24 12:55
  • 5306

基于Redis的布隆过滤器的实现

项目简介包含一个基于Redis的布隆过滤器的实现,以及应用到Scrapy中的Demo。地址:BloomFilterRedis布隆过滤器网上有很多介绍,推荐《数学之美》,介绍的很详尽,此处不再赘述。哈希函数布隆过滤器中需要n个哈希函数,我使用的是Arash Partow提供的常见哈希函数。建立在Red...
  • qq_30242609
  • qq_30242609
  • 2017-04-30 17:57
  • 3371

缓存穿透,缓存击穿,缓存雪崩解决方案分析

前言 设计一个缓存系统,不得不要考虑的问题就是:缓存穿透、缓存击穿与失效时的雪崩效应。 缓存穿透 缓存穿透是指查询一个一定不存在的数据,由于缓存是不命中时被动写的,并且出于容错考虑,如果从存储层查不到数据则不写入缓存,这将导致这个存在的数据每次请求都要到存储层去查询,失去了缓存的意义。在流量大时,...
  • zeb_perfect
  • zeb_perfect
  • 2017-01-06 11:12
  • 13735

缓存雪崩和缓存穿透

缓存雪崩 缓存雪崩可能是因为数据未加载到缓存中,或者缓存同一时间大面积的失效,从而导致所有请求都去查数据库,导致数据库CPU和内存负载过高,甚至宕机。 解决思路: 1,采用加锁计数,或者使用合理的队列数量来避免缓存失效时对数据库造成太大的压力。这种办法虽然能缓解数据库的压力,但...
  • zhang_Red
  • zhang_Red
  • 2016-03-01 18:56
  • 4227

缓存穿透,缓存击穿,缓存雪崩解决方案分析

转载于:http://blog.csdn.net/zeb_perfect/article/details/54135506  仅仅用于个人学习 前言 设计一个缓存系统,不得不要考虑的问题就是:缓存穿透、缓存击穿与失效时的雪崩效应。 缓存穿透 缓存穿透是指...
  • u013970971
  • u013970971
  • 2018-01-16 18:23
  • 35

【布隆过滤器】实现一个简单的布隆过滤器

原理布隆过滤器(Bloom Filter)是1970年由布隆提出的。它实际上是一个很长的二进制向量和一系列随机映射函数。布隆过滤器可以用于检索一个元素是否在一个集合中。它的优点是空间效率和查询时间都远远超过一般的算法,缺点是有一定的误识别率和删除困难。Bloom Filter 是一种空间效率很高的随...
  • wenqiang1208
  • wenqiang1208
  • 2017-08-06 14:27
  • 322

布隆过滤器总结(一)详解

布隆过滤器(Bloom Filter)详解   布隆过滤器[1](Bloom Filter)是由布隆(Burton Howard Bloom)在1970年提出的。它实际上是由一个很长的二进制向量和一系列随机映射函数组成,布隆过滤器可以用于检索一个元素是否在一个集合中...
  • lifuxiangcaohui
  • lifuxiangcaohui
  • 2014-12-19 11:11
  • 3195
    个人资料
    • 访问:348020次
    • 积分:4376
    • 等级:
    • 排名:第8180名
    • 原创:100篇
    • 转载:39篇
    • 译文:0篇
    • 评论:148条
    博客专栏
    友情链接
    最新评论