一文读懂什么是布隆过滤器

本文涉及的产品
函数计算FC,每月15万CU 3个月
简介: 一文读懂什么是布隆过滤器

1. 什么是布隆过滤器(Bloom Filter)

布隆过滤器(Bloom Filter)是1970年由布隆提出的。

它实际上是一个很长的二进制位数组和一系列随机映射函数。

布隆过滤器可以用于检索一个元素是否在一个集合中。

它的优点是空间效率和查询时间都比一般的算法要好的多,缺点是有一定的误识别率和删除困难。

2. 布隆过滤器的原理

2.1. 数据结构

  1. 以Redis中的布隆过滤器实现为例,Redis中的布隆过滤器底层是一个大型位数组(二进制数组)+ 多个无偏hash函数。
  2. 一个大型位数组(二进制数组):
  3. 多个无偏hash函数:无偏hash函数就是能把元素的hash值计算得比较均匀的hash函数,能使得计算后的元素下标比较均匀的映射到位数组中。如下就是一个简单的布隆过滤器示意图,其中k1、k2代表增加的元素,a、b、c即为无偏hash函数,最下层则为二进制数组。

2.2. 空间计算

  1. 在布隆过滤器增加元素之前,首先需要初始化布隆过滤器的空间,也就是上面说的二进制数组,除此之外还需要计算无偏hash函数的个数。
  2. 布隆过滤器提供了两个参数,分别是预计加入元素的大小n,运行的错误率f。
  3. 布隆过滤器中有算法根据这两个参数会计算出二进制数组的大小l,以及无偏hash函数的个数k。它们之间的关系比较简单:
  4. 错误率越低,位数组越长,控件占用较大;
  5. 错误率越低,无偏hash函数越多,计算耗时较长;
  1. 如下地址是一个免费的在线布隆过滤器在线计算的网址:

https://krisives.github.io/bloom-calculator/

2.3. 增加元素

1.往布隆过滤器增加元素,添加的key需要根据k个无偏hash函数计算得到多个hash值,然后对数组长度进行取模得到数组下标的位置,然后将对应数组下标的位置的值置为1;

1.通过k个无偏hash函数计算得到k个hash值;

2.依次取模数组长度,得到数组索引;

3.将计算得到的数组索引下标位置数据修改为1

例如,key = Liziba,无偏hash函数的个数k=3,分别为hash1、hash2、hash3。三个hash函数计算后得到三个数组下标值,并将其值修改为1;如图所示:


2.4. 查询元素

布隆过滤器最大的用处就在于判断某样东西一定不存在或者可能存在,而这个就是查询元素的结果。其查询元素的过程如下:

  1. 通过k个无偏hash函数计算得到k个hash值;
  2. 依次取模数组长度,得到数组索引;
  3. 判断索引处的值是否全部为1,如果全部为1则存在(这种存在可能是误判),如果存在一个0则必定不存在;

2.关于误判,其实非常好理解,hash函数在怎么好,也无法完全避免hash冲突,也就是说可能会存在多个元素计算的hash值是相同的,那么它们取模数组长度后的到的数组索引也是相同的,这就是误判的原因。

2.5. 修改元素

不支持;

2.6. 删除元素

  1. 布隆过滤器对元素的删除不太支持,但是目前有一些变形的特定布隆过滤器支持元素的删除;
  2. 关于为什么对删除不太支持,其实也非常好理解,hash冲突必然存在,删除肯定是很困难的!


3. 假阳性率及最佳实践

  1. 所谓假阳性率就是本来在集合中不存在的元素,被判定为存在的概率。
  2. 假阳性是BF最大的痛点,因此有必要权衡,比如计算一下假阳性的概率。为了简单一点,就假设我们的哈希函数选择位数组中的比特时,都是等概率的。当然在设计哈希函数时,也应该尽量满足均匀分布。
  3. 在位数组长度m的BF中插入一个元素,它的其中一个哈希函数会将某个特定的比特置为1。因此,在插入元素后,该比特仍然为0的概率是:


  1. 现有k个哈希函数,并插入n个元素,自然就可以得到该比特仍然为0的概率是:
  2. 反过来讲,它已经被置为1的概率就是:
  3. 也就是说,如果在插入n个元素后,我们用一个不在集合中的元素来检测,那么被误报为存在于集合中的概率(也就是所有哈希函数对应的比特都为1的概率)为:
  4. 当n比较大时,根据重要极限公式,可以近似得出假阳性率:

因此,可以得出如下结论,在哈希函数的个数k一定的情况下:

  1. 位数组长度m越大,假阳性率越低;
  2. 已插入元素的个数n越大,假阳性率越高;
  3. 如何选择适合业务的 k 和 m 值呢,直接贴一个公式:

4. 布隆过滤器的优点

  1. 相比于其它的数据结构,布隆过滤器在空间和时间方面都有巨大的优势。布隆过滤器存储空间和插入/查询时间都是常数(即hash函数的个数),增加和查询元素的时间复杂为O(N);
  2. 布隆过滤器不需要存储元素本身,在某些对保密要求非常严格的场合有优势;
  3. 存储空间小,如果允许存在一定的误判,布隆过滤器是非常节省空间的(相比其他数据结构如Set集合);
  4. 布隆过滤器可以表示全集,其它任何数据结构都不能。

5. 布隆过滤器的缺点

  1. 有点一定的误判率,但是可以通过调整参数来降低;
  2. 无法获取元素本身;
  3. 很难删除元素;


6. 布隆过滤器的使用场景

利用布隆过滤器减少磁盘 IO 或者网络请求,因为一旦一个值必定不存在的话,就可以直接结束查询,比如以下场景:

  1. 大数据去重;
  2. 网页爬虫对 URL 的去重,避免爬取相同的 URL 地址;
  3. 解决Redis缓存穿透问题,将已存在的缓存放到布隆过滤器中,访问不存在的缓存时迅速返回避免缓存及数据库挂掉;
  4. 邮件过滤,使用布隆过滤器来做邮件黑名单过滤;
  5. 推荐算法,推荐过的不再推荐(类似抖音刷过的往下滑动不再刷到);
  6. HBase、RocksDB、LevelDB等数据库内置布隆过滤器,用于判断数据是否存在,可以减少数据库的IO请求;


相关实践学习
【AI破次元壁合照】少年白马醉春风,函数计算一键部署AI绘画平台
本次实验基于阿里云函数计算产品能力开发AI绘画平台,可让您实现“破次元壁”与角色合照,为角色换背景效果,用AI绘图技术绘出属于自己的少年江湖。
从 0 入门函数计算
在函数计算的架构中,开发者只需要编写业务代码,并监控业务运行情况就可以了。这将开发者从繁重的运维工作中解放出来,将精力投入到更有意义的开发任务上。
目录
相关文章
|
监控 算法
独立成分分析(Independent Component Analysis,ICA)原理及代码实现
独立成分分析(Independent Component Analysis,ICA)原理及代码实现
独立成分分析(Independent Component Analysis,ICA)原理及代码实现
|
Prometheus 监控 Cloud Native
Prometheus VS InfluxDB
前言 除了传统的监控系统如 Nagios,Zabbix,Sensu 以外,基于时间序列数据库的监控系统随着微服务的兴起越来越受欢迎,比如 Prometheus,比如 InfluxDB。gtt 也尝试了一下这两个系统,希望能找到两者的差别,为以后选型提供一些帮助。
9724 0
|
4月前
|
传感器 人工智能 自然语言处理
魔搭社区模型速递(7.26-8.2)
🙋魔搭ModelScope本期社区进展:1498个模型,130个数据集,85个创新应用, 7 篇内容
510 0
|
SQL 安全 PHP
PHP安全性深度剖析:防范常见漏洞与最佳实践####
本文深入探讨了PHP编程中不可忽视的安全隐患,重点介绍了SQL注入、XSS攻击、CSRF攻击及文件包含漏洞等四大常见安全威胁。通过详尽的案例分析与防御策略阐述,为开发者提供了一套实用的安全编码指南。文章强调,提升代码安全性是保障Web应用稳健运行的关键,鼓励开发者在日常开发中积极践行安全最佳实践。 ####
|
人工智能 自然语言处理 语音技术
通用模型和垂直模型的比较
通用模型和垂直模型的比较
1259 1
|
10月前
|
人工智能 移动开发 机器人
智能体 | 快速构建专属英语口语陪练助手,这下雅思再也不用愁了
智能体是以云为基础、AI为核心的智能系统,不同于通义千问等AI工具,用户可自建专注于特定领域的智能体,如英语口语陪练助手。通过阿里云百炼平台,开通服务、创建智能体、选择模型、设计Prompt并测试优化,最终发布到多渠道。用户能随时随地进行英语口语练习,提升语言能力。
|
关系型数据库 MySQL
启动mysql时报错"/etc/init.d/mysqld: Permission denied"
请谨慎操作,并根据你的具体情况选择适当的解决方法。如果问题仍然存在,你可能需要查看MySQL的文档或寻求进一步的支持。
946 1
|
机器学习/深度学习 自然语言处理 数据挖掘
使用Python和大模型进行数据分析和文本生成
Python语言以其简洁和强大的特性,成为了数据科学、机器学习和人工智能开发的首选语言之一。随着大模型(Large Language Models, LLMs)如GPT-4的崛起,我们能够利用这些模型实现诸多复杂任务,从文本生成到智能对话、数据分析等等。在这篇文章中,我将介绍如何用Python连接和使用大模型,并通过示例展示如何在实际项目中应用这些技术。
|
机器学习/深度学习 算法 数据挖掘
【Python 机器学习专栏】K-means 聚类算法在 Python 中的实现
【4月更文挑战第30天】K-means 是一种常见的聚类算法,用于将数据集划分为 K 个簇。其基本流程包括初始化簇中心、分配数据点、更新簇中心并重复此过程直到收敛。在 Python 中实现 K-means 包括数据准备、定义距离函数、初始化、迭代和输出结果。虽然算法简单高效,但它需要预先设定 K 值,且对初始点选择敏感,可能陷入局部最优。广泛应用在市场分析、图像分割等场景。理解原理与实现对应用聚类分析至关重要。
696 1
|
关系型数据库 MySQL 数据库
轻松入门:使用Docker安装MySQL数据库的完全指南
轻松入门:使用Docker安装MySQL数据库的完全指南