布隆过滤器(BloomFilter)
布隆过滤器的使用场景
在架构设计中,通常会涉及这样的场景:
- 词典服务中,查询某个单词是否合法(即是否存在于保存有海量单词的词典文件中)
- 爬虫服务中,检查某个网页是否已经收录(即是否存在于海量的已爬取网页库中)
- 文章/商品推荐服务中,检查某篇文章/某个商品是否已经被推荐过(已推荐过的文章或商品不重复推荐);
- 查询某个元素是否在缓存中存在(假设缓存中的元素非常多)
以上的场景,本质上都是从海量数据中判断某一个元素是否存在。这种场景通常有两种解决方式:
- 假设空间无限且无需考察元素查找的时间复杂度,那么就将海量元素按连续内存或链表结构进行存储,之后以此查询,此种方式的优势在于简单,劣势也非常明显,那就是无论是空间复杂度还是时间复杂度都非常差,空间/时间复杂度均为O(N),假设数据量非常大时,无论是存储空间的占用还是时间的开销都无法满足业务要求;
- 采用空间换时间的方式,比如采用HashSet的存储方式,将元素通过某种hash算法获取hashcode,存储到指定的分桶中。这种方式的优势在于时间复杂度有效地得到了提升,即O(1);但缺点依然很明显,其空间存储要求为O(N)。因此,随着元素个数N的增大,分桶数急剧增多,假设数据量很大时,则无法满足(因为如果分桶数不增多,会频繁发生hash碰撞,导致在某些分桶或绝大多数分桶上退化成链表,虽说在JDK8上采用了红黑树的方式提升查找效率,但依然只是一种权衡,因为不过将时间复杂度从O(N)变成了O(logN)。)
尽管上述的方法2可以采用多级HashSet的方式(先采用某种方法,如取模,将数据切分到多台机器的内存中,有效地减少每一个分片的数据量之后,再重复方法2的方式--典型的分库分表的思路)进行水平扩展,但这其实只是一种打补丁的方法,因为数据量会不断扩大,需要提前预估存储水位,之后提前做迁移,存在一定的繁琐性。那么究竟有没有办法可以解决这个问题呢?
答案是肯定的,采用布隆过滤器可以有效地解决以上的问题。
布隆过滤器的原理
其实布隆过滤器的思路是十分直接的,既然一种hash算法可能会出现碰撞,那么采用多个hash算法之后,再次发生碰撞的概率就会急剧减小。详情如下图所示:
假设我们采用长度为12的数组来做布隆过滤器,注意其长度与存储的元素数无关,因此空间占用为O(1)。
如图所示,我们共采用4种Hash算法,对于Object1而言,其表示为010000010011;同样的,对Object2而言,其表示为001001010010。当我们从布隆过滤器中check Object1是否存在时,仅需要再次进行4次hash运算(这几次Hash计算互相独立,可并行运行),然后检查定位到的数组中的元素是否都为1,如果是,则说明大概率已存在(后边会说为何会出现假真的情况);如果不是,则说明肯定不存在。
刚才提到,可能会出现假真的情况,其产生的根源在于hash碰撞。假设另一个Object3,对于这四种hash算法的结果都与Object1 hash碰撞了,则会出现假真的情况。
布隆过滤器的优点:
- 节省存储空间,其对空间的占用是O(1)的,与存储元素数量无关,正因为如此,它是可以存储全部元素的。
布隆过滤器的缺点:
- 有误判率,当两个元素按照K种hash算法都碰撞的时候,就出现了误判,即本不存在的数据当成了存在;
- 原生的布隆过滤器是不能删除的,但是可以采用改进版在一定程度上解决这个问题,即数组中的元素不是简单的0与1,而是引用计数。
布隆过滤器的使用场景
布隆过滤器的使用场景很多,最为常用的场景就是海量元素集合下,一次写入多次读取的场景下的元素是否存在的判定。
例如:
- 评论中的敏感词识别:评论分词后,以此通过布隆过滤器检查是否命中敏感词,命中的话进行业务处理(打星号或其他操作);
- 已推荐文章去重:通过布隆过滤器检查待推荐的文章是否在已推荐文章集合中存在。
布隆过滤器中元素变更或失效的解决方式
原生的布隆过滤器是适用于一次写入/多次读取的场景的,对于元素变更与失效,并没有提供太好的解决办法。但其实元素变更或失效确实在实际的设计中存在着。例如敏感词表中敏感词的解禁,其本质上是将布隆过滤器中的某个元素(敏感词)删除。
常用的解决方式其实刚才已经提到过,使用引用计数,但实际上对于这样的业务场景,可以考虑在空间与业务复杂度之间取一定的折中。比如,将数组中存储的元素变更为Object,Object带有isDeleted属性,如果需要删除的话,将该属性置1。这样的做法相对于引用计数的方式,会增大存储开销,但是对于易读性/可维护性/可扩展性(后续再加过期时间等)提供了有力的抓手。
布隆过滤器(BloomFilter)相关推荐
- Flink 结合 布隆过滤器(BloomFilter) 实现去重
本文开头附:Flink 学习路线系列 ^ _ ^ 1.实时系统去重方案 使用Redis,将实时系统每条数据都去和 Redis 进行判断: 使用 HashSet,因为 HashSet 本身就是无序不重复 ...
- 布隆过滤器(BloomFilter)原理 实现和性能测试
目录 BloomFilter的原理 如何确定最优的m和k? guava中的BloomFilter 使用案例 和HashSet对比 测试环境 测试方式 BloomFilter vs HashSet 在不 ...
- 布隆过滤器 - Redis 布隆过滤器,Guava 布隆过滤器 BloomFilter
文章目录 布隆过滤器 - Redis 布隆过滤器,Guava 布隆过滤器 BloomFilter 1.布隆过滤器的起源,用途 2.布隆过滤器的概念 3.布隆过滤器的优缺点 1.优点 2.缺点 4.应用 ...
- 04 布隆过滤器BloomFilter
是什么 布隆过滤器(英语:Bloom Filter)是 1970 年由布隆提出的. 它实际上是一个很长的二进制数组+一系列随机hash算法映射函数,主要用于判断一个元素是否在集合中. 通常我们会遇到很 ...
- Redis 高级主题之布隆过滤器(BloomFilter)
最近计划准备整理几篇关于Reids高级主题的博文,本文整理的是关于布隆过滤器在Redis中如何应用,先来一张思维导图浏览全文. 1. 认识BloomFilter 1.1 原理 布隆过滤器,英文叫Blo ...
- 网络爬虫:URL去重策略之布隆过滤器(BloomFilter)的使用
前言: 最近被网络爬虫中的去重策略所困扰.使用一些其他的"理想"的去重策略,不过在运行过程中总是会不太听话.不过当我发现了BloomFilter这个东西的时候,的确,这里是我目前找 ...
- C语言布隆过滤器BloomFilter
在实现BloomFilter,首先实现一个位图: BitMap 在位图中,每个元素为"0"或"1",表示其对应的元素不存在或者存在. typedef struc ...
- Hbase 解析(四) 布隆过滤器(BloomFilter)
1.简介 1.1 介绍 Bloom filter是1970年引入的一种数据结构,在过去的十年中,由于它为网络主机之间的组成员信息传输提供了带宽效率,因此被网络研究界采用.发送者将信息编码成一个比特向量 ...
- 布隆过滤器-BloomFilter
目录 一.概述 二.详解 三.实现 四.适用业务场景 一.概述 简单讲布隆过滤器就是判断一个列表中是否存在某个元素.一般在JAVA判断是否存在,我们可以Map,Set等容器.但是当数据量特别大的时候, ...
- 【redis】详解布隆过滤器BloomFilter的原理,使用场景和注意事项
文章目录 1. 什么是布隆过滤器 2. 实现原理 2.1 HashMap 的问题 2.2 布隆过滤器数据结构 2.3 BloomFilter 的缺点 2.4 如何选择哈希函数个数和布隆过滤器长度 3. ...
最新文章
- 关于自动驾驶汽车法律政策的十点思考
- leetcode345——Reverse Vowels of a String(C++)
- bootsect.s文件阅读问题集
- linux下socket连接下的心跳机制
- java.logging的重定向?
- web前端开发论文写作_外语论文文献引言格式—MLA Style
- 最优化学习笔记(十六)——拟牛顿法(2)
- python之list[index1:index2]是左闭右开
- GeoTools计算线与面的交点
- Javascript中的!-- //--
- 形象标识 新松机器人_新松SIASUN工业机器人标志logo设计,品牌设计vi策划
- http接口公网对接时用到的RSA加密/解密实现示例
- 将python代码转换为flowchart代码
- 【C# 练习】最少需要准备多少张人民币,才能在给每个人发工资的时候都不用找零呢,人民币一共有100元、50元、10元、5元、2元和1元六种
- “血洗”Twitter,“杀疯了”的马斯克究竟想干啥?
- BIM用C语言编程,实现BIM技术的三个重要方面是()。A.BIM的建立B.BIM的应用C.BIM的管理D.BIM的粒度E.BIM的概念...
- CSU - 2135 Appositive Body
- 基础知识 十进制转二进制
- 【JavaGUI demo】swing仿Windows气泡屏保动画(含源码)
- 一篇文章读懂,物联网项目的5大技术要素