一道腾讯面试题:如何快速判断某 URL 是否在 20 亿的网址 URL 集合中?布隆过滤器
何为布隆过滤器
还是以上面的例子为例:
判断逻辑:
多次哈希:
Guava的BloomFilter
创建BloomFilter
最终还是调用:
使用:
算法特点
使用场景
假设遇到这样一个问题:一个网站有 20 亿 url 存在一个黑名单中,这个黑名单要怎么存?若此时随便输入一个 url,你如何快速判断该 url 是否在这个黑名单中?并且需在给定内存空间(比如:500M)内快速判断出。
可能很多人首先想到的会是使用 HashSet,因为 HashSet基于 HashMap,理论上时间复杂度为:O(1)。达到了快速的目的,但是空间复杂度呢?URL字符串通过Hash得到一个Integer的值,Integer占4个字节,那20亿个URL理论上需要:20亿*4/1024/1024/1024=7.45G的内存,不满足空间复杂度的要求。
这里就引出本文要介绍的“布隆过滤器”。
何为布隆过滤器
百科上对布隆过滤器的介绍是这样的:
布隆过滤器(Bloom Filter)是1970年由布隆提出的。它实际上是一个很长的二进制向量和一系列随机映射函数。布隆过滤器可以用于检索一个元素是否在一个集合中。它的优点是空间效率和查询时间都比一般的算法要好的多,缺点是有一定的误识别率和删除困难。
是不是描述的比较抽象?那就直接了解其原理吧!
还是以上面的例子为例:
哈希算法得出的Integer的哈希值最大为:Integer.MAX_VALUE=2147483647,意思就是任何一个URL的哈希都会在0~2147483647之间。
那么可以定义一个2147483647长度的byte数组,用来存储集合所有可能的值。为了存储这个byte数组,系统只需要:2147483647/8/1024/1024=256M。
比如:某个URL(X)的哈希是2,那么落到这个byte数组在第二位上就是1,这个byte数组将是:000….00000010,重复的,将这20亿个数全部哈希并落到byte数组中。
判断逻辑:
如果byte数组上的第二位是1,那么这个URL(X)可能存在。为什么是可能?因为有可能其它URL因哈希碰撞哈希出来的也是2,这就是误判。
但是如果这个byte数组上的第二位是0,那么这个URL(X)就一定不存在集合中。
多次哈希:
为了减少因哈希碰撞导致的误判概率,可以对这个URL(X)用不同的哈希算法进行N次哈希,得出N个哈希值,落到这个byte数组上,如果这N个位置没有都为1,那么这个URL(X)就一定不存在集合中。
Guava的BloomFilter
Guava框架提供了布隆过滤器的具体实现:BloomFilter,使得开发不用再自己写一套算法的实现。
创建BloomFilter
BloomFilter提供了几个重载的静态 create方法来创建实例:
public static <T> BloomFilter<T> create(Funnel<? super T> funnel, int expectedInsertions, double fpp);
public static <T> BloomFilter<T> create(Funnel<? super T> funnel, long expectedInsertions, double fpp);
public static <T> BloomFilter<T> create(Funnel<? super T> funnel, int expectedInsertions);
public static <T> BloomFilter<T> create(Funnel<? super T> funnel, long expectedInsertions);
最终还是调用:
static <T> BloomFilter<T> create(Funnel<? super T> funnel, long expectedInsertions, double fpp, Strategy strategy);
// 参数含义:
// funnel 指定布隆过滤器中存的是什么类型的数据,有:IntegerFunnel,LongFunnel,StringCharsetFunnel。
// expectedInsertions 预期需要存储的数据量
// fpp 误判率,默认是0.03。
BloomFilter里byte数组的空间大小由 expectedInsertions, fpp参数决定,见方法:
static long optimalNumOfBits(long n, double p) {
if (p == 0) {
p = Double.MIN_VALUE;
}
return (long) (-n * Math.log(p) / (Math.log(2) * Math.log(2)));
}
真正的byte数组维护在类:BitArray中。
使用:
最后通过:put和 mightContain方法,添加元素和判断元素是否存在。
算法特点
1、因使用哈希判断,时间效率很高。空间效率也是其一大优势。2、有误判的可能,需针对具体场景使用。3、因为无法分辨哈希碰撞,所以不是很好做删除操作。
使用场景
1、黑名单 2、URL去重 3、单词拼写检查 4、Key-Value缓存系统的Key校验 5、ID校验,比如订单系统查询某个订单ID是否存在,如果不存在就直接返回。
一道腾讯面试题:如何快速判断某 URL 是否在 20 亿的网址 URL 集合中?布隆过滤器的更多相关文章
- Linux fork函数具体图解-同一时候分析一道腾讯笔试题
原创blog.转载请注明出处 头文件: #include<unistd.h> #include<sys/types.h> 函数原型: pid_t fork( void); (p ...
- 如何快速判断一个key是否存在在亿级数据中(bloomFilters)
面试题 现在有一个非常庞大的数据(亿级),假设全是 int 类型.现在我给你一个数,你需要告诉我它是否存在其中(尽量高效) 分析 采用bloomFilters进行实现(时间&空间尽可能的有效) ...
- 20 亿的 URL 集合,如何快速判断其中一个?
假设遇到这样一个问题:一个网站有 20 亿 url 存在一个黑名单中,这个黑名单要怎么存?若此时随便输入一个 url,你如何快速判断该 url 是否在这个黑名单中?并且需在给定内存空间(比如:500M ...
- 腾讯面试题 腾讯面试题:给40亿个不重复的unsigned int的整数,没排过序的,然后再给一个数,如何快速判断这个数是否在那40亿个数当中?
腾讯面试题:给40亿个不重复的unsigned int的整数,没排过序的,然后再给一个数,如何快速判断这个数是否在那40亿个数当中? 这个题目已经有一段时间了,但是腾讯现在还在用来面试.腾讯第一次面 ...
- 腾讯面试题:10G 个整数,乱序排列,要求找出中位数。内存限制为 2G。
腾讯面试题:10G 个整数,乱序排列,要求找出中位数.内存限制为 2G. 题目和基本思路都来源网上,本人加以整理. 题目:在一个文件中有 10G 个整数,乱序排列,要求找出中位数.内存限制为 2G.只 ...
- 解析js中作用域、闭包——从一道经典的面试题开始
如何理解js中的作用域,闭包,私有变量,this对象概念呢? 就从一道经典的面试题开始吧! 题目:创建10个<a>标签,点击时候弹出相应的序号 先思考一下,再打开看看 //先思考一下你会怎 ...
- 布隆过滤器 - 如何在100个亿URL中快速判断某URL是否存在?
题目描述 一个网站有 100 亿 url 存在一个黑名单中,每条 url 平均 64 字节.这个黑名单要怎么存?若此时随便输入一个 url,你如何快速判断该 url 是否在这个黑名单中? 题目解析 这 ...
- 从一道高大上的面试题来学习位图算法BitMap
今天我偶然刷到了一篇文章,"华为二面:一个文件里面有5亿个数据,一行一个,没有重复的,进行排序".不知道又是哪个无良媒体瞎起的标题,夺人眼球. 不过说归说,这题听着就很高大上,5亿 ...
- 【Android】一道Android OpenGL笔试题
一道Android OpenGL笔试题 SkySeraph May. 5th 2016 Email:skyseraph00@163.com 更多精彩请直接访问SkySeraph个人站点:www.sky ...
随机推荐
- 一些idea
二分答案似乎和最小生成树有着不可描述的奇怪关系.(滑稽 联赛级别的在矩形上乱搞的题无非几个思路(按出现概率排序):建图,二维前缀和,dp 涉及到求合法区间数的问题往往要用到桶.等差数列等思想,或者尝试 ...
- tomcat7以下线程控制
web server允许的最大线程连接数还受制于操作系统的内核参数设置,通常Windows是2000个左右,Linux是1000个左右. 1.编辑tomcat安装目录下的conf目录下的server. ...
- What size do you use for varchar(MAX) in your parameter declaration?
What size do you use for varchar(MAX) in your parameter declaration? In this case you use -1. See al ...
- Django框架(十六)—— cookie和session组件
目录 cookie和session组件 一.cookie 1.cookie的由来 2.什么是cookie 3.cookie的原理 4.cookie的覆盖 5.在浏览器中查看cookie 6.cooki ...
- java 重新学习 (五)
Set 集合 一.HashSet按照Hash算法存储集合元素(hashCode方法获取hashCode值,根据hashCode值获取元素位置,通过equals判断对象是否相等并且hashCode值是否 ...
- 实用maven笔记四-打包&其他
通过使用maven的生命周期和丰富多样的插件,可以方便的将项目代码编译打包为自己需要的构件. maven默认项目主代码位置src/main/java目录,测试代码位置src/test/java目录.主 ...
- Python最快的方式来读取大文本文件(几GB)
我有一个大文本文件(约7 GB).我正在寻找是否存在阅读大文本文件的最快方法.我一直在阅读有关使用多种方法作为读取chunk-by-chunk以加快进程的过程. 例如,effbot建议 # File: ...
- 分布式-技术专区-Redis分布式锁原理实现
在很多场景中,我们为了保证数据的最终一致性,需要很多的技术方案来支持,比如分布式事务.分布式锁等.那具体什么是分布式锁,分布式锁应用在哪些业务场景.如何来实现分布式锁呢?今天来探讨分布式锁这个话题. ...
- 3.3-Cypher语言及语法使用
Cypher是一种图数据库查询语言,表现力丰富,查询效率高,其地位和作用与关系型数据库中的SQL语言相当. Cypher具备的能力: Cypher通过模式匹配图数据库中的节点和关系,来提取信息或者修改 ...
- 最新版react16.9中按需加载antd和使用less
使用create-react-app创建应用 yarn create react-app my-app cd my-app yarn start 引入 antd 这是 create-react-app ...