前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >面试题,如何在千万级的数据中判断一个值是否存在?

面试题,如何在千万级的数据中判断一个值是否存在?

作者头像
ImportSource
发布2019-05-06 15:58:44
4K0
发布2019-05-06 15:58:44
举报
文章被收录于专栏:ImportSourceImportSource

当你看到这个标题的时候,你也许会想我可以使用hashmap之类的来存储值,然后get就是了。又或者把数据存在数据库里然后去判断就可以了。

但你有没有想过数据量那么大全部存储起来是不是有点太重了。为了判断是否存在得把所有的数据都存储起来,这个数据量得有多大。

所以我们先把map这种数据结构先排除掉,去看看本期的主角:Bloom Filter。

Bloom Filter初识

在东方大地,它的名字叫:布隆过滤器。该过滤器在一些分布式数据库中被广泛使用,比如我们熟悉的hbase等。它在这些数据库中扮演的角色就是判断一个值是否存在。这些分布式数据库之所以青睐它,就是因为它有很强大的性能,而且存储空间又小。

布隆过滤器核心就是两点,bit数组和hash。

你听到这里是不是表示不屑,废话,map还不是一个数组和hash。没错,存放数据无非就是个数组和hash。但布隆过滤器的数组和hash有点不一样。

它的数组里的值只有两种可能,要么是1,要么是0,没有其他第三个值。1表示存在,0表示不存在。

它的hash有多个hash。注意,可以是多个hash,不是一个hash。

那布隆过滤器数据结构究竟是怎么存储的呢?我们简单的画个图你就明白了。

没错,就是一个数组,然后里边的值都是一些0和1。数组的初始状态是全部为0。然后每插入一个值,就会把该值的几个hash后的映射值改为1。如上图所示。

那如何去添加一个值进去呢?然后又如何判断该值是否存在呢?现在需要确定位置,这个道理和hashmap的道理是一样的,使用hash来确定位置。

比如我要判断x是否存在,那么我就通过生成的三个hash函数来分别hash到数组的三个位置去,然后获取这个三个位置的值是否都为1,如果是,就认为x是存在(极有可能)的。反之,如果有一个位置的值为0,那么x必然不存在。

那么你现在肯定纳闷,这个hash函数是固定几个hash函数吗?还是怎么样?

hash生成的规则

嗯,这是布隆过滤器核心思想之一,通过查找布隆过滤器的论文可知,它有一个公式,通过这个公式来计算hash。

gi(x) = h1(x) + i*h2(x);

首先是要有两个初始hash,分别为h1和h2,然后通过h1和h2生成新的hash。i表示hash函数个数。

在google guava库里的BloomFilter中就是按照这个公式来生成hash的。

另外可以看到hash1和hash2的生成规则,hash1是通过murmur算法来生成一个long值,然后通过转int来得到hash1,然后通过位运算得到hash2。

合适的数组大小和hash数量

此时你也许会纳闷一个事情,你不是说千万级数据量,那么hash后取模落到数组中,如果数组比较小,是不是就会重叠,那么此时即使每个hash函数查出来都为1也不一定就表示某值存在啊?

没错,确实有这个问题。为了解决这个问题,布隆过滤器引入了误报率这个概念,说的就是这个问题。

所以数组的大小至关重要。另外hash functions的个数也至关重要。既然这么重要,怎么才能计算出合适的数量呢?有下面两个公式,分别用来计算推荐的数组size以及hash functions的个数。这里数组的大小用m表示,hash functions的个数用k来表示。n则表示数据量的大小。

选择合适的hash算法

另外选择一个好的hash算法也是至关重要的,好的hash算法可以确保hash值比较均匀的分布。guava里的Bloom Filter使用的就是Murmur哈希算法。

MurmurHash 是一种非加密型哈希函数,适用于一般的哈希检索操作。由Austin Appleby在2008年发明,并出现了多个变种,都已经发布到了公有领域(public domain)。与其它流行的哈希函数相比,对于规律性较强的key,MurmurHash的随机分布特征表现更良好。

总之,Bloom Filter就三点:数组、hash生成规则、hash算法(Murmour)。

上代码

通过上面的介绍,相信你应该知道了布隆过滤器的基本原理,现在我们就以guava的Bloom Filter为例,体验一下,千万级的感觉吧:

返回结果:

上面的代码中我们设置了误报率以及预估数据量,然后生成了Bloom Filter实例,然后插入一个“importsource”字符串,然后判断是否存在,最后返回结果是存在。

使用场景

主要使用场景:

1、黑名单。如果某个IP或账号不存在,则允许通过;否则不让通过。

2、爬虫重复URL检测。爬取数据时,需要检测某个url是否已被爬取过。

3、字典纠错。检测单词是否拼写正确。

4、磁盘文件检测。检测要访问的数据是否在磁盘或数据库中。

5、CDN缓存。先查找本地有无cache,如果没有则到其他兄弟cache服务器上去查找。为了避免无谓的查询,在每个cache服务器上保存其兄弟服务器的缓存关键字,以bloomfilter方式存储。在去指定兄弟服务器查找之前,先检查boomfilter中是否有url,如果有,再去对应服务器查找。

总结

Bloom Filter核心就是数组和hash。数组中1表示存在,0表示不存在。Bloom Filter有一定的误报率。多个hash映射都为1,表示指定值极有可能存在(也有可能不存在),多个hash映射有一个为0,则该值必定不存在。选择合适的hash function数量以及数组大小以及合适的hash算法对于准确率至关重要。

误报率在线计算:https://hur.st/bloomfilter/

论文:http://www.eecs.harvard.edu/~michaelm/postscripts/tr-02-05.pdf

在线体验示例:https://llimllib.github.io/bloomfilter-tutorial/

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-02-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 ImportSource 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
分布式数据库 TDSQL
分布式数据库(Tencent Distributed SQL,以下简称 TDSQL)是腾讯打造的一款企业级数据库产品,具备强一致高可用、全球部署架构、高 SQL 兼容度、分布式水平扩展、高性能、完整的分布式事务支持、企业级安全等特性,同时提供智能 DBA、自动化运营、监控告警等配套设施,为客户提供完整的分布式数据库解决方案。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档