Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >面试题,如何在千万级的数据中判断一个值是否存在?

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

作者头像
ImportSource
发布于 2019-05-06 07:58:44
发布于 2019-05-06 07:58:44
4.6K0
举报
文章被收录于专栏: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 删除。

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

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Guava -- Bloom Filter原理
去重在软件开发中经常需要用到,在Java当中一般使用Set集合,面对大量数据则可以利用取MD5签名等值后再进行去重,然而Set集合的实现原理决定了如果有大量的key需要判断,必然会需要大量的内存来支撑,且随着数据量增大效率也变得不那么尽人意。另外业务中存在着很多对精确性不需要那么高的场景,此时使用Set集合则是一种资源浪费,因此就可以利用布隆过滤器等算法手段进行去重。
屈定
2020/02/10
1.7K0
布隆过滤器:判断一定不存在或者可能存在的算法
布隆过滤器(BloomFilter)是由只存0或1的位数组和多个hash算法, 进行判断数据一定不存在或者可能存在的算法.
一个架构师
2022/06/20
1.4K0
布隆过滤器:判断一定不存在或者可能存在的算法
如何判断一个元素是否存在于一个亿级数据集中?
布隆过滤器(Bloom Filter)于 1970 年由布隆提出的,是专门用于检索一个元素是否存在于一个集合中的算法。
dys
2019/11/29
1.2K0
Guava的布隆过滤器
 程序世界的算法都要在时间,资源占用甚至正确率等多种因素间进行平衡。同样的问题,所属的量级或场景不同,所用算法也会不同,其中也会涉及很多的trade-off。
程序员历小冰
2019/04/28
1.2K0
Guava的布隆过滤器
牛逼哄哄的布隆过滤器,到底有什么用?
本文是站在小白的角度去讨论布隆过滤器,如果你是科班出身,或者比较聪明,又或者真正想完全搞懂布隆过滤器的可以移步。
Java技术栈
2020/07/02
5330
巧用布隆过滤器提取数据摘要
在telemetry采集中,由于数据量极大,一般采用分布式架构;使用消息队列来进行各系统的解耦。有系统如下:
超级大猪
2022/11/29
4360
巧用布隆过滤器提取数据摘要
品味布隆过滤器 Bloom filter的设计之美
你可能没想到: RocketMQ、 Hbase 、Cassandra 、LevelDB 、RocksDB 这些知名项目中都有布隆过滤器的身影。
勇哥java实战
2023/04/14
2.4K0
品味布隆过滤器 Bloom filter的设计之美
【C++修炼之路】25.哈希应用--布隆过滤器
我们在使用新闻客户端看新闻时,它会给我们不停地推荐新的内容,它每次推荐时要去重,去掉那些已经看过的内容。问题来了,新闻客户端推荐系统如何实现推送去重的? 用服务器记录了用户看过的所有历史记录,当推荐系统推荐新闻时会从每个用户的历史记录里进行筛选,过滤掉那些已经存在的记录。 如何快速查找呢?
每天都要进步呀
2023/03/28
8840
【C++修炼之路】25.哈希应用--布隆过滤器
Redis实现布隆过滤器解析
    1)布隆过滤器(Bloom Filter)是1970年由布隆提出的。它实际上是一个很长的二进制向量和一系列随机映射函数。布隆过滤器可以用于检索一个元素是否在一个集合中。它的优点是空间效率和查询时间都远远超过一般的算法,缺点是有一定的误识别率和删除困难。
忧愁的chafry
2022/10/30
1.4K0
Redis实现布隆过滤器解析
大数据量下的集合过滤—Bloom Filter
算法背景 如果想判断一个元素是不是在一个集合里,一般想到的是将集合中所有元素保存起来,然后通过比较确定。链表、树、散列表(又叫哈希表,Hash table)等等数据结构都是这种思路,存储位置要么是磁盘,要么是内存。很多时候要么是以时间换空间,要么是以空间换时间。 在响应时间要求比较严格的情况下,如果我们存在内里,那么随着集合中元素的增加,我们需要的存储空间越来越大,以及检索的时间越来越长,导致内存开销太大、时间效率变低。 此时需要考虑解决的问题就是,在数据量比较大的情况下,既满足时间要求,又满足空间的要求。
欠扁的小篮子
2018/07/04
1.9K0
Reids(4)——神奇的HyperLoglog解决统计问题
上一次 我们学会了使用 HyperLogLog 来对大数据进行一个估算,它非常有价值,可以解决很多精确度不高的统计需求。但是如果我们想知道某一个值是不是已经在 HyperLogLog 结构里面了,它就无能为力了,它只提供了 pfadd 和 pfcount 方法,没有提供类似于 contains 的这种方法。
我没有三颗心脏
2020/03/20
7630
Reids(4)——神奇的HyperLoglog解决统计问题
基于Guava布隆过滤器的海量字符串高效去重实践
使用Google Guava库来实现基于布隆过滤器的海量字符串去重是一个很好的选择。布隆过滤器是一种空间效率极高的概率型数据结构,它利用位数组表示集合,并使用哈希函数将元素映射到位数组的某些位置。布隆过滤器可以高效地检查一个元素是否可能属于某个集合,但有一定的误报率。
公众号:码到三十五
2024/03/19
2750
基于Guava布隆过滤器的海量字符串高效去重实践
海量数据处理之BloomFilter
一提到元素查找,我们会很自然的想到HashMap。通过将哈希函数作用于key上,我们得到了哈希值,基于哈希值我们可以去表里的相应位置获取对应的数据。除了存在哈希冲突问题之外,HashMap一个很大的问题就是空间效率低。引入Bloom Filter则可以很好的解决空间效率的问题。
Spark学习技巧
2018/12/18
1.3K0
布隆过滤器:原理与应用
这个时候,布隆过滤器(Bloom Filter)就派上了用场。作为一种空间高效的概率型数据结构,布隆过滤器能够快速有效地检测一个元素是否属于一个集合。其应用广泛,从网络爬虫的网页去重,到数据库查询优化,乃至比特币网络的交易匹配,都离不开它的身影。
BookSea
2023/10/16
5380
布隆过滤器:原理与应用
【C++从小白到大牛】布隆过滤器
上一篇文章我们已经学习了位图的应用,但是位图一般只能处理整形,如果内容编号是字符串,就无法处理了。而我们又知道如果只用哈希表存储用户记录,缺点就是浪费空间。但是我们将哈希表和位图结合起来呢,就是我们的布隆过滤器!
用户11316056
2024/10/16
1200
【C++从小白到大牛】布隆过滤器
详解布隆过滤器原理,及分布式运用方法_布隆过滤器最小误差
布隆过滤器是一个叫“布隆”的人提出的,本质上布隆过滤器是一种数据结构,比较巧妙的概率型数据结构(probabilistic data structure)。它本身是一个很长的二进制向量,特点是高效地插入和查询,可以用来确定 “某一条数据一定不存在或者可能存在一个集合中”。
全栈程序员站长
2022/11/08
1.4K0
详解布隆过滤器原理,及分布式运用方法_布隆过滤器最小误差
位图与布隆过滤器
此篇文章针对大量数据进行筛选或者判断重复,存在等一系列侧重于在特定空间,时间等允许范围内进行选择的问题提出解决方案。
羑悻的小杀马特.
2025/01/23
1110
位图与布隆过滤器
Java|存储|Guava Bloom Filter源码剖析
Bloom Filter(布隆过滤器)以牺牲少量正确率为代价,利用较少的空间实现O(1)的查询,在LSM Tree、Cache中作为常见的读优化手段。本文结合谷歌的Guava源码介绍Bloom Filter的实现。
朝闻君
2021/11/22
7770
Java|存储|Guava Bloom Filter源码剖析
Redis进阶-布隆过滤器
我们在 Redis进阶-Redis缓存优化中 讲到了 缓存穿透 的解决防范: 比缓存空值更好的一种解决方式 布隆过滤器 ,这里我们详细讲解下。
小小工匠
2021/08/17
9020
解密hash算法:散列表、布隆过滤器和分布式一致性hash的原理与应用
了解平衡二叉树: 平衡二叉树查找数据采用二分查找,每次查找排除一半。平衡的目的是增删改之后,保证下次搜索能够稳定排除一半的数据。
Lion 莱恩呀
2024/07/29
2610
解密hash算法:散列表、布隆过滤器和分布式一致性hash的原理与应用
推荐阅读
相关推荐
Guava -- Bloom Filter原理
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档