布隆过滤器实战!垃圾邮件识别?重复元素判断?缓存穿透?

大数据笔记--Bloom Filter 应用场景:现有10亿个邮件地址,都是非垃圾邮件地址,存在集合S中。那么对于输入的任意邮件地址,如何判断是否在集合S中。    如果将10亿个地址都放入内存中查找,假设一个地址是10个字符,占用10个字节,那么10亿个地址需要占用10G内存,很显然是非常浪费资源的。    Bloom Filter 的思路:                                     1. 在内存中 阅读详情

作者:semlinker  
https://segmentfault.com/a/1190000021136424

在程序的世界中,布隆过滤器是程序员的一把利器,利用它可以快速地解决项目中一些比较棘手的问题。如网页 URL 去重、垃圾邮件识别、大集合中重复元素的判断和缓存穿透等问题。

布隆过滤器(Bloom Filter)是 1970 年由布隆提出的。它实际上是一个很长的二进制向量和一系列随机映射函数。布隆过滤器可以用于检索一个元素是否在一个集合中。它的优点是空间效率和查询时间都比一般的算法要好的多,缺点是有一定的误识别率和删除困难。

一、布隆过滤器简介

当你往简单数组或列表中插入新数据时,将不会根据插入项的值来确定该插入项的索引值。这意味着新插入项的索引值与数据值之间没有直接关系。这样的话,当你需要在数组或列表中搜索相应值的时候,你必须遍历已有的集合。若集合中存在大量的数据,就会影响数据查找的效率。

针对这个问题,你可以考虑使用哈希表。利用哈希表你可以通过对 “值” 进行哈希处理来获得该值对应的键或索引值,然后把该值存放到列表中对应的索引位置。这意味着索引值是由插入项的值所确定的,当你需要判断列表中是否存在该值时,只需要对值进行哈希处理并在相应的索引位置进行搜索即可,这时的搜索速度是非常快的。

根据定义,布隆过滤器可以检查值是 “可能在集合中” 还是 “绝对不在集合中”。“可能” 表示有一定的概率,也就是说可能存在一定为误判率。那为什么会存在误判呢?下面我们来分析一下具体的原因。

布隆过滤器(Bloom Filter)本质上是由长度为 m 的位向量或位列表(仅包含 0 或 1 位值的列表)组成,最初所有的值均设置为 0,如下图所示。

为了将数据项添加到布隆过滤器中,我们会提供 K 个不同的哈希函数,并将结果位置上对应位的值置为 “1”。在前面所提到的哈希表中,我们使用的是单个哈希函数,因此只能输出单个索引值。而对于布隆过滤器来说,我们将使用多个哈希函数,这将会产生多个索引值。

如上图所示,当输入 “semlinker” 时,预设的 3 个哈希函数将输出 2、4、6,我们把相应位置 1。假设另一个输入 ”kakuqo“,哈希函数输出 3、4 和 7。你可能已经注意到,索引位 4 已经被先前的 “semlinker” 标记了。此时,我们已经使用 “semlinker” 和 ”kakuqo“ 两个输入值,填充了位向量。当前位向量的标记状态为:

当对值进行搜索时,与哈希表类似,我们将使用 3 个哈希函数对 ” 搜索的值 “进行哈希运算,并查看其生成的索引值。假设,当我们搜索”fullstack“ 时,3 个哈希函数输出的 3 个索引值分别是 2、3 和 7:

从上图可以看出,相应的索引位都被置为 1,这意味着我们可以说 ”fullstack“ 可能已经插入到集合中。事实上这是误报的情形,产生的原因是由于哈希碰撞导致的巧合而将不同的元素存储在相同的比特位上。幸运的是,布隆过滤器有一个可预测的误判率(FPP):

  • n 是已经添加元素的数量;

  • k 哈希的次数;

  • m 布隆过滤器的长度(如比特数组的大小);

极端情况下,当布隆过滤器没有空闲空间时(满),每一次查询都会返回 true 。这也就意味着 m 的选择取决于期望预计添加元素的数量 n ,并且 m 需要远远大于 n 。

实际情况中,布隆过滤器的长度 m 可以根据给定的误判率(FFP)的和期望添加的元素个数 n 的通过如下公式计算:

了解完上述的内容之后,我们可以得出一个结论,当我们搜索一个值的时候,若该值经过 K 个哈希函数运算后的任何一个索引位为 ”0“,那么该值肯定不在集合中。但如果所有哈希索引值均为”1“,则只能说该搜索的值可能存在集合中。

二、布隆过滤器应用

在实际工作中,布隆过滤器常见的应用场景如下:

  • 网页爬虫对 URL 去重,避免爬取相同的 URL 地址;

  • 反垃圾邮件,从数十亿个垃圾邮件列表中判断某邮箱是否垃圾邮箱;

  • Google Chrome 使用布隆过滤器识别恶意 URL;

  • Medium 使用布隆过滤器避免推荐给用户已经读过的文章;

  • Google BigTable,Apache HBbase 和 Apache Cassandra 使用布隆过滤器减少对不存在的行和列的查找。
    除了上述的应用场景之外,布隆过滤器还有一个应用场景就是解决缓存穿透的问题。所谓的缓存穿透就是服务调用方每次都是查询不在缓存中的数据,这样每次服务调用都会到数据库中进行查询,如果这类请求比较多的话,就会导致数据库压力增大,这样缓存就失去了意义。

利用布隆过滤器我们可以预先把数据查询的主键,比如用户 ID 或文章 ID 缓存到过滤器中。当根据 ID 进行数据查询的时候,我们先判断该 ID 是否存在,若存在的话,则进行下一步处理。若不存在的话,直接返回,这样就不会触发后续的数据库查询。需要注意的是缓存穿透不能完全解决,我们只能将其控制在一个可以容忍的范围内。

三、布隆过滤器实战

布隆过滤器有很多实现和优化,由 Google 开发著名的 Guava 库就提供了布隆过滤器(Bloom Filter)的实现。在基于 Maven 的 Java 项目中要使用 Guava 提供的布隆过滤器,只需要引入以下坐标:


   
  1. <dependency>

  2.    <groupId>com.google.guava</groupId>

  3.    <artifactId>guava</artifactId>

  4.    <version>28.0-jre</version>

  5. </dependency>

在导入 Guava 库后,我们新建一个 BloomFilterDemo 类,在 main 方法中我们通过 BloomFilter.create 方法来创建一个布隆过滤器,接着我们初始化 1 百万条数据到过滤器中,然后在原有的基础上增加 10000 条数据并判断这些数据是否存在布隆过滤器中:


   
  1. import com.google.common.base.Charsets;

  2. import com.google.common.hash.BloomFilter;

  3. import com.google.common.hash.Funnels;

  4. public class BloomFilterDemo {

  5.     public static void main(String[] args) {

  6.         int total = 1000000; // 总数量

  7.         BloomFilter<CharSequence> bf = 

  8.           BloomFilter.create(Funnels.stringFunnel(Charsets.UTF_8), total);

  9.         // 初始化 1000000 条数据到过滤器中

  10.         for (int i = 0; i < total; i++) {

  11.             bf.put("" + i);

  12.         }

  13.         // 判断值是否存在过滤器中

  14.         int count = 0;

  15.         for (int i = 0; i < total + 10000; i++) {

  16.             if (bf.mightContain("" + i)) {

  17.                 count++;

  18.             }

  19.         }

  20.         System.out.println("已匹配数量 " + count);

  21.     }

  22. }

当以上代码运行后,控制台会输出以下结果:


   
  1. 已匹配数量 1000309

很明显以上的输出结果已经出现了误报,因为相比预期的结果多了 309 个元素,误判率为:


   
  1. 309/(1000000 + 10000) * 100 ≈ 0.030594059405940593

如果要提高匹配精度的话,我们可以在创建布隆过滤器的时候设置误判率 fpp:


   
  1. BloomFilter<CharSequence> bf = BloomFilter.create(

  2.   Funnels.stringFunnel(Charsets.UTF_8), total, 0.0002

  3. );

在 BloomFilter 内部,误判率 fpp 的默认值是 0.03:


   
  1. // com/google/common/hash/BloomFilter.class

  2. public static <T> BloomFilter<T> create(Funnel<? super T> funnel, long expectedInsertions) {

  3.   return create(funnel, expectedInsertions, 0.03D);

  4. }

在重新设置误判率为 0.0002 之后,我们重新运行程序,这时控制台会输出以下结果:


   
  1. 已匹配数量 1000003

通过观察以上的结果,可知误判率 fpp 的值越小,匹配的精度越高。当减少误判率 fpp 的值,需要的存储空间也越大,所以在实际使用过程中需要在误判率和存储空间之间做个权衡。

四、总结

本文主要介绍的布隆过滤器的概念和常见的应用场合,在实战部分我们演示了 Google 著名的 Guava 库所提供布隆过滤器(Bloom Filter)的基本使用,同时我们也介绍了布隆过滤器出现误报的原因及如何提高判断准确性。最后为了便于大家理解布隆过滤器,我们介绍了一个简易版的布隆过滤器 SimpleBloomFilter。

(end)

【推荐阅读】

Lucene&Solr&ElasticSearch-面试题

 Java 9 ← 2017,2019 → Java 13 ,来看看Java两年来的变化

永远不要在代码中使用「User」这个单词

ElasticSearch最全详细使用教程:入门、索引管理、映射详解

ElasticSearch最全详细使用教程:索引别名、分词器、文档管理、路由、搜索详解

(java思维导图)

长按关注,每天java一下,成就架构师

我就知道你在看!

JavaMail 具备垃圾邮件过滤功能的邮箱 使用Java完成的简单邮箱系统,界面由Java Swing实现,具有以下功能: 1、邮件收发等邮箱基本功能 2、可设置黑名单、白名单,并过滤邮件 3、使用朴素贝叶斯算法检测评估邮件是否为垃圾邮件 立即下载

相关推荐

基于cat12搞定SBM的ROI的统计分析——vertex水平和ROI水平的双样本T检验

前言 一、Atlas皮层图谱介绍 二、SBM分析——主要以皮层四种常用指标中的厚度(thickness)和沟深(depth)为主

Sophia2023的博客 8755

【布隆过滤器】如何防止缓存穿透、海量邮箱的垃圾邮件过滤等问题?

它是一种概率型数据结构,特点是高效的插入和查询,作用是可以告诉你“某个数据一定不存在,或是可能存在”,原理是通过多个哈希函数,将一个数据映射到位图中,好处是不仅提高了查询效率,也可以节省大量的内存空间,底层相当于哈希表+位图;

CYK_byte的博客 1248

ONNC Open Neural Network Compiler 开源神经网络编译器 一个 开源、模块化、可重用编译器算法和工具链的库,专门针对深度学习加速器(DLA)部署导入ONNX模型

ONNC是一个集合了开源、模块化、可重用编译器算法和工具链的库,专门针对深度学习加速器(DLA)。ONNC从底层开始构建,旨在将ONNX中间表示(IR)翻译成专有DLA代码。其软件架构设计强调可移植性和可重用性,从而简化了开发新后端的工作。上图展示了ONNC软件栈的顶层框图。软件栈从导入ONNX计算图模型到输出相应的硬件二进制文件,展示了各个功能块。

万有文的博客 1997

布隆过滤器

前言 我们之前讲了Redis的缓存雪崩、穿透、击穿。在文章里我们说了解决缓存穿透的办法之一,就是布隆过滤器,但是上次并没有讲如何使用布隆过滤器。 什么是布隆过滤器 布隆过滤器(Bloom Filter),是1970年,由一个叫布隆的小伙子提出的,距今已经五十年了,和老哥一样老。 它实际上是一个很长的二进制向量和一系列随机映射函数,二进制大家应该都清楚,存储的数据不是0就是1,默认是0。 主要用于判断一个元素是否在一个集合中,0代表不存在某个数据,1代表存在某个数据。 懂了吗?作为暖男的老哥在给你

新技术革命 416

STM32F103电压采集proteus仿真

基于HAL库,仿真单片机型号为stm32f103R6,代码keil5。通过单片机的ADC采集功能,测量四路电压,数据经由DMA传输,并将结果通过串口输出,结果比较确,误差在0.01V左右。目前仿真采集四路比较稳定,多了会乱码。proteus版本8.11安装包链接:https://pan.baidu.com/s/1yhNKLl1lGSU9KU0tTuAxcg?pwd=dxe8提取码:dxe8项目下载地址:.

weixin_42490599的博客 4768

CocosCreator 面试题(十七)Cocos creator 固定宽度与固定高度的底层原理是什么?Cocos creator是如何做适配的?

通过固定宽度或固定高度的适配方式,可以使游戏在不同屏幕尺寸上保持一定的一致性,确保游戏中的元素的大小和位置相对稳定。具体选择哪种适配方式取决于你的游戏需求和设计考虑。在 Cocos Creator 中,你可以通过设置「设计分辨率」和使用相对坐标和布局方式来实现固定宽度或固定高度的适配。总之,Cocos Creator 提供了多种适配方式和工具,帮助你在不同屏幕尺寸上保持游戏画面的一致性。在 Cocos Creator 中,固定宽度和固定高度是两种常见的适配方式,用于在不同屏幕尺寸上保持游戏画面的一致性。

w风雨无阻w的专栏 1688

使用BloomFilter布隆过滤器解决缓存击穿、垃圾邮件识别、集合判重

Bloom Filter是一个占用空间很小、效率很高的随机数据结构,它由一个bit数组和一组Hash算法构成。可用于判断一个元素是否在一个集合中,查询效率很高(1-N,最优能逼近于1)。 在很多场景下,我们都需要一个能迅速判断一个元素是否在一个集合中。譬如: 网页爬虫对URL的去重,避免爬取相同的URL地址; 反垃圾邮件,从数十亿个垃圾邮件列表中判断某邮箱是否垃圾邮箱(同理,垃圾短信);

tianyaleixiaowu的专栏 2万+

SAP PP模块MRP控制参数实战指南:从NETCH到NEUPL的深度解析

本文深入解析SAP PP模块中MRP控制参数的配置与应用,涵盖NETCH、NETPL和NEUPL三种运行模式的优化策略。通过实战案例和参数对比,帮助用户提升物料需求计划的效率和准确性,优化库存周转率和生产交付能力。

weixin_28419039的博客 244

Python实验数据集:垃圾邮件数据集(http://archive.ics.uci.edu/ml/datasets/Spambase)。请从spambase.csv读入数据。 数据集基本信息如下:样

实验数据集:垃圾邮件数据集(http://archive.ics.uci.edu/ml/datasets/Spambase)。请从spambase.csv读入数据。 数据集基本信息如下:样本数: 4601,特征数量: 57, 类别:1为垃圾邮件,0为非垃圾邮件。 将样本集划分为70%的训练集,30%作为测试集。分别完成以下内容。 决策树 (1)分别取节点分裂标准为“gini”或“entropy”,分别建立决策树模型,计算训练误差和测试误差;画出对应的决策树。 (2)设置树高,由3到30,分别建模,计算训

missionnn的博客 2万+

5-DOF机械臂课程设计(一)之正逆运动学

文章目录基本要求基本概念关节坐标系的建立正运动学求解DH参数表的建立逆运动学求解多解下解的选取源码下载后续 基本要求 ​ 开发上位机程序,要求有良好的界面,能提供关节空间下和笛卡尔坐 标下表示的目标位姿点和中间若干经过点的输入功能,进行轨迹规划, 并控制机械臂沿轨迹运动,最终完成目标抓取的任务。 基本概念 连杆长度 :2个相邻关节轴线之间的距离 连杆扭角 :2个相邻关节轴线之间的角度 连杆偏距 :2个关节坐标系的X轴之间的距离 关节角度 :关节变量 计算时需要加初始角度偏移 关节坐标系的建立 ​ 根据《机

Rosen的博客 5861

基于深度学习的茶叶等级检测识别系统:YOLOv8 + UI界面 + 数据集完整实现

随着深度学习技术的不断进步,基于计算机视觉的茶叶等级检测系统可以大大提高检测效率,提供客观一致的评估标准。本系统将利用YOLOv8进行茶叶等级的检测与识别,通过图形用户界面(UI)实现与用户的交互,提供茶叶等级分类的实时反馈。本文将详细介绍如何使用YOLOv8结合UI界面,建立一个完整的茶叶等级检测与识别系统,包括数据集的准备、模型的训练、UI的设计及完整的代码实现。本系统的目标是通过深度学习技术,结合YOLOv8模型和图形用户界面(UI),实现对茶叶等级的自动化检测与识别。

YOLO 972

布隆过滤器解决缓存击穿问题

布隆过滤器

hauchun的博客 8263

CAP CDS 和 ABAP Cloud 的 CDS 有什么区别?

摘要:SAP生态中的CAP CDS与ABAP CDS虽同名但存在显著差异。CAP CDS定位为全栈应用的领域模型与服务契约语言,支持声明式建模并直接编译为服务接口;而ABAP CDS更侧重数据语义层,与ABAP平台深度集成,服务于SQL优化和服务发布链路。两者在语法、持久化方式、服务暴露机制及权限模型上均有不同:CAP CDS采用CDL语法,支持模型即服务;ABAP CDS基于ABAP DDL,通过视图定义语义并与RAP框架紧密耦合。这些差异反映了二者在不同平台中的设计哲学和应用场景。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 207

布隆过滤器详解

布隆过滤器(Bloom Filter)是 1970 年由布隆提出的。它实际上是一个很长的二进制向量和一系列随机映射函数。主要用于判断一个元素是否在一个集合中。

eyes++的博客 1万+

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

高性能缓存实践-解决缓存穿透-基于内存布隆过滤器

文章目录目标布隆过滤器应用我的理解实践引入 goole guava 依赖业务类controller 层 目标 实践基于内存的布隆过滤器 参考:大白话布隆过滤器 布隆过滤器的方式解决缓存穿透问题 布隆过滤器 参考:百度百科-布隆过滤器 布隆过滤器(Bloom Filter)是1970年由布隆提出的。它实际上是一个很长的二进制向量和一系列随机映射函数。布隆过滤器可以用于检索一个元素是否在一个集合中。它的优点是空间效率和查询时间都比一般的算法要好的多,缺点是有一定的误识别率和删除困难。 应用 网页URL的

qq1164014750 503

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

亿级数据过滤算法----布隆过滤器

亿级数据过滤算法----布隆过滤器

不更了,主打一个陪伴 1275

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

布隆过滤器(Bloom Filter)详解

什么是布隆过滤器 介绍+优点 应用场景 设计原理 布隆实战 总结 存在的问题 + 总结

心中的执念的博客 5822

Bloom filter(布隆过滤器)学习与使用总结

一、简介 当我们使用主流数据结构如 Lists, Maps, Sets, Trees等等时,我可以得到确切的结果,无论这个数据存在或是不存在。概率数据结构能够提供一种基于内存的,快速的查找出一种可能而非确切的结果。这种概率数据结构就是布隆过滤器(Bloom filter)。 布隆过滤器可以检查值是“可能在集合中”还是“绝对不在集合中”。 定义 Bloom过滤器实质上由长度为m的位向量或位列表(仅包含0或1位值的列表)组成,最初所有值均设置为0,如下所示: 在哈希表中,我们使用单个哈希函数,因此仅获得单个索

weixin_43927773的博客 4075

5 分钟搞懂布隆过滤器,亿级数据过滤算法你值得拥有!

点击蓝色“架构文摘”关注我哟加个“星标”,每天上午 09:25,干货推送!在程序的世界中,布隆过滤器是程序员的一把利器,利用它可以快速地解决项目中一些比较棘手的问题。如网页 URL 去重...

架构文摘 1208

布隆过滤器简单实现添加和判断功能

是 1970 年由布隆提出的。它实际上是一个很长的向量和一系列随机映射函数。主要用于判断一个元素是否在一个集合中。通常我们会遇到很多要判断一个元素是否在某个集合中的业务场景,一般想到的是将集合中所有元素保存起来,然后通过比较确定。、树、散列表(又叫哈希表,Hash table)等等数据结构都是这种思路。但是随着集合中元素的增加,我们需要的存储空间也会呈现线性增长,最终达到瓶颈。...

m0_52012606的博客 1916

布隆过滤器速度_5 分钟搞懂布隆过滤器,过滤亿级数据

在程序的世界中,布隆过滤器是程序员的一把利器,利用它可以快速地解决项目中一些比较棘手的问题。如网页 URL 去重、垃圾邮件识别、大集合中重复元素的判断和缓存穿透等问题。布隆过滤器(Bloom Filter)是 1970 年由布隆提出的。它实际上是一个很长的二进制向量和一系列随机映射函数。布隆过滤器可以用于检索一个元素是否在一个集合中。它的优点是空间效率和查询时间都比一般的算法要好的多,缺点是有一定...

weixin_39638801的博客 511

布隆过滤器,Guava实现布隆过滤器(本地内存),Redis实现布隆过滤器(分布式)

利用布隆过滤器可以快速地解决项目中一些比较棘手的问题。如网页 URL 去重、垃圾邮件识别、大集合中重复元素的判断和缓存穿透等问题。不知道从什么时候开始,本来默默无闻的布隆过滤器一下子名声大噪,在面试中面试官问到怎么避免缓存穿透,你的第一反应可能就是布隆过滤器,缓存穿透=布隆过滤器成了标配;布隆过滤器(Bloom Filter)是 1970 年由布隆提出的。它实际上是一个很长的二进制向量和一系列随机映射函数。布隆过滤器可以用于检索一个元素是否在一个集合中。

一个学习Java开发的老头 2012

缓存穿透、缓存击穿、缓存雪崩

什么数据适合缓存 缓存穿透 缓存穿透是指缓存和数据库中都没有的数据,而用户不断发起请求。这时的用户很可能是攻击者,攻击会导致数据库压力过大。 假如客户端每秒发送5000个请求,其中4000个为黑客的恶意攻击,即在数据库中也查不到。举个例子,用户id为正数,黑客构造的用户id为负数,如果黑客每秒一直发送这4000个请求,缓存就不起作用,数据库也很快被打死。 解决方案: 1.接口层增加校验,如用户鉴权校验,id做基础校验,id<=0的直接拦截; 2.从缓存取不到的数据,在数据库中也没有取到,

qq_36281031的博客 192

布隆过滤器简介 侵删

在程序的世界中,布隆过滤器是程序员的一把利器,利用它可以快速地解决项目中一些比较棘手的问题。如网页 URL 去重、垃圾邮件识别、大集合中重复元素的判断和缓存穿透等问题。 布隆过滤器(Bloom Filter)是 1970 年由布隆提出的。它实际上是一个很长的二进制向量和一系列随机映射函数。布隆过滤器可以用于检索一个元素是否在一个集合中。它的优点是空间效率和查询时间都比一般的算法要好的多,缺点是有...

心神沫沫的收藏 341
上一篇: mybatis思维导图,让mybatis不再难懂(一)
下一篇: 必懂系列!Java并发面试题
Java思维导图
博客等级 码龄10年 306粉丝 71原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值