浅谈布隆过滤器

输入框
• 阅读 2042

1. 问题情景

如果面试官问你,一个网站有 100 亿 url 存在一个黑名单中,每条 url 平均 64 字节。问这个黑名单要怎么存?若此时随便输入一个 url,如何判断该 url 是否在这个黑名单中?

对于第一个问题,如果把黑名单看成一个集合,将其存在 hashmap 中,貌似太大了,需要 640G,明显不科学。

那该怎么办?ok,现在该介绍今天的主角了 —— 布隆过滤器就可以解决这样的问题。

首先,布隆过滤器是什么?维基百科是这样解释的:

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

官方说法看下就好,如果不理解没关系,其实不会难,下面我们讲人话慢慢来。

2. 具体介绍

布隆过滤器实际上是一个很长的二进制矢量和一系列随机映射函数。

「很长的二进制矢量」:这是一个长度很长的数组,什么类型的数组呢?bit 类型的数组,也是我们说的「位」,(1Byte = 8bit,1KB = 1024Byte)。

「一系列随机映射函数」:有多个哈希函数。那什么是哈希函数呢?JDK 里面有计算得到哈希值的方法,那就是一个哈希函数。

布隆过滤器可以用于检索一个元素是否在一个集合中。它的优点是空间效率和查询时间都远远超过一般的算法,缺点是有一定的误识别率和删除困难

这个不就可以解决我们最开始的问题吗?那它是怎么解决的呢?

3. 解决过程

下面我说下大体的过程,细节部分可先不理解,重要的是明白流程,细节我后面补充。

假设,bit 类型数组的长度为 m,每个元素值为 0,有 k 个哈希函数。

首先,当输入一个 url 的时候,此时这个 url 会经过 k 个哈希函数处理,得到多个哈希值(v1,v2,...,vk)。之后得到这些哈希值对应在数组的下标位置,最后将这些下标的元素都置为 1。

那么如何判断一个 url 在黑名单里面呢?输入一条 url,它经过上述处理之后,会得到多个数组的下标位置。如果这些下标的元素值都已经为 1 了,说明该在黑名单里面,否则不在。

总体就是这样的流程,下面说下大家可能存在的疑问:

1、bit 类型的数组如何构建

2、得到 v1,v2,...,vk 这些哈希值后,如何得到其在数组的下标位置,并将其设置为 1 呢?

两个问题我一起说下,Java 里面没有 bit 这样的类型,怎么构建呢?—— 不难,我们可以使用 int,一个 int 是 32 位。

//创建了一个 100 * 32bit 的数组
int[] arr = new int[100]; 
// 代表 bit 数组 0-31 位的元素
arr[0];

因此上面再会说「分别将这些哈希值除以数组的长度 m,和对 m 取模,得到这些哈希值对应在数组的下标位置」。

具体我们可以拿一个哈希值 data 来举个栗子,假设 int 数组长度为 100。

void Set(int data) {
       // ByteNO 是表示在 table 数组中那个元素
       int ByteNo = data / 32;
       // bitNo 是表示在 32 位 bit 中哪个 bit 位。
       int BitNo = data % 32;
       // 置 1
       _table[ByteNo] |= (1 << BitNo); 
   }

4. 使用效果

最开始我们提到,如果将 100 亿 url 放到 HashMap 中需要 640GB,那么使用布隆过滤器后又需要多少空间呢?答案是约等于 23 GB。相比之下,这个空间大小是不是就可以接受很多了。

5. 缺点

布隆过滤器有宁可错杀一百,也不能放过一个的性质。讲人话就是属于黑名单的 url 一定能够正确判断它在黑名单中,但不属于黑名单中的 url 也可能会被认为在黑名单中,存在一定的失误率。

至于失误率要保持在多少,数组长度,哈希函数的个数分别要设置多少就需要根据实际情况来选择了,网上有对应的数学公式计算,这里就不展开讲了。

参考:
https://blog.csdn.net/wenqian...

如果觉得文章不错,希望能得到你的关注:七淅在学Java
点赞
收藏
评论区
推荐文章
Wesley13 Wesley13
4年前
jackson
1.  漏洞描述近日,百度云安全团队跟踪到jacksondatabind在github上更新了一个新的反序列化利用类com.caucho.config.types.ResourceRef,issue编号2660,该类绕过了之前jacksondatabind维护的黑名单类。如果项目中包含resinkernel库,并且JDK版本较低的
马丁路德 马丁路德
4年前
在浏览器输入 URL到页面展示中间发生了什么?
这个问题是前端的经典问题,从这个问题出发我们可以从根本上了解如何解决性能优化问题首先我们可以在开头大概了解下在浏览器输入URL到页面展示,中间有哪些步骤:用户从浏览器进程里输入请求信息网络发起URL请求服务器响应URL请求之后,浏览器进程就要开始准备渲染进程了渲染进程准备好之后,需要先向渲染进程提交页面数据,我
liuzhen007 liuzhen007
4年前
Golang根据URL判断媒体协议
目录问题解决问题如何根据一个流媒体地址URL判断对应的流媒体协议,比如RTMP、RTSP协议等。解决这里提供一个方法,可以直接拿来用。golangfuncgetProtocol(urlstring)(string,error){ifurl""{index:strings.Index(url,":")
Stella981 Stella981
4年前
Proxy SwitchyOmega 使用黑名单和白名单
“黑名单”会告诉代理工具,黑名单(国外)里面的网站要使用代理;“白名单”会告诉代理工具,白名单(大陆网站)里面的网站直接连接,其余使用代理。黑名单PAC!(https://oscimg.oschina.net/oscnet/b4958bbb544e4103998484b934018f4fa4f.png)!(https://i
Wesley13 Wesley13
4年前
Tomcat 正式环境下多个Context配置
Tomcat中给server.xml加入<Context元素<Context代表了运行在<Host上的单个Web应用,一个<Host可以有多个<Context元素,每个Web应用必须有唯一的URL路径,这个URL路径在<Context中的属性path中设定。<Context path"/helloApp1" docBa
Wesley13 Wesley13
4年前
unittest参数化
在写case的时候,如果用例的操作是一样的,就是参数不同,比如说要测一个登录的接口,要测正常登录的,黑名单用户登录的,账号密码错误等等,在unittest里面要写多个case来测试。这样的情况只是调用接口的时候参数不一样而已,再写多个case的话就有点多余了,那怎么办呢,就得把这些参数都写到一个list里面,然后循环去执行这个case,这样就可以省去写多
Stella981 Stella981
4年前
Google布隆过滤器与Redis布隆过滤器详解
一、什么是布隆过滤器?布隆过滤器可以用来判断一个元素是否在一个集合中。它的优势是只需要占用很小的内存空间以及有着高效的查询效率。对于布隆过滤器而言,它的本质是一个位数组:位数组就是数组的每个元素都只占用1bit,并且每个元素只能是0或者1布隆过滤器除了一个位数组,还有K个哈希函数。当一个元素加入布隆过滤器中的时候,会进行如下操作:
Stella981 Stella981
4年前
Linux玩转redis从入门到放肆
1\.缓存穿透在大多数互联网应用中,缓存的使用方式如下图所示:!(https://oscimg.oschina.net/oscnet/6a12e0fbee579fa624b2ea1738e89278c3f.png)1.当业务系统发起某一个查询请求时,首先判断缓存中是否有该数据;2.如果缓存中存在,则直接返回数据;3.如果缓存中
Stella981 Stella981
4年前
Angular最新教程
Angular之所以被称为单页面应用,就是因为我们在改变浏览器URL的时候, 不触发刷新当前页面的行为,我们看到的所有的界面,其实是在一个主URL中。 这个功能(功能?现象?表现?随便吧!)就是通过路由实现的。 下面我们先简单的看一个关于路由的例子。!(https://oscimg.oschina.net/oscnet/4e0e1
Python进阶者 Python进阶者
2年前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这
一文理解布隆过滤器和布谷鸟过滤器
作者:京东保险王奕龙最近在大促中使用到了布隆过滤器,所以本次借着机会整理下相关内容,并了解了布谷鸟过滤器,希望对后续学习的同学有启发\布隆过滤器布隆过滤器是概率性数据结构,用于检查元素是否存在集合中。布隆过滤器并不存储集合中的所有元素,而是存储元素的哈希表