【Redis篇】详解布隆过滤器(原理 | 操作 | 代码)

news2025/1/23 17:53:51

文章目录

  • 🍔简述布隆过滤器
  • 🌺原理
    • 🛸存入过程
    • 🛸查询过程
  • 🏳️‍🌈优缺点
    • ⭐优点
    • ⭐缺点
  • 🌹代码实现(本地)
  • 🌹代码实现(分布式)

在这里插入图片描述

🍔简述布隆过滤器

布隆过滤器的由来可以追溯到1970年代,由一个名叫Burton Howard Bloom的美国计算机科学家提出。他在1970年的一篇论文中首次描述了这个概念,并将其称为"Bloom filter"。

Bloom当时的目标是设计一种高效的数据结构,用于在大规模数据库中进行快速查询。他的主要思想是通过使用一个位数组和多个哈希函数,能够在不存储实际数据的情况下,快速判断一个元素是否存在于集合中。这种数据结构的提出,为解决大规模数据的查找问题提供了一种经济高效的方法。

布隆过滤器最初的应用场景是在数据库系统中,用于加速查询操作。它可以有效地减少磁盘I/O操作,提高查询效率,并节省存储空间。后来,布隆过滤器得到了广泛的应用,在各种领域都发挥了重要作用。

随着互联网的迅速发展和大数据时代的到来,布隆过滤器的应用范围越来越广泛。它被用于网络缓存、分布式系统、垃圾邮件过滤、URL去重、爬虫的URL判重、密码学等领域。由于其高效的查询性能和低存储成本,布隆过滤器成为了解决大规模数据处理和高并发访问的重要工具。

总结来说,布隆过滤器是由美国计算机科学家Burton Howard Bloom提出的一种高效的概率型数据结构,用于快速判断一个元素是否存在于集合中。它的提出解决了大规模数据查询的问题,并在各个领域得到了广泛的应用和发展。

🌺原理

布隆过滤器其实就是一个很长的二进制向量和一系列随机映射函数,主要用来判断一个元素是否存在一个集合中,存储的数据不是0就是1,默认是0
1代表存在某个数据,0代表不存在

🛸存入过程

因为布隆过滤器就是一个二进制数据的集合,当有一个数据加入到这个集合的时候,会经过下面的步骤

  • 通过k个哈希函数计算该数据,返回k个计算得到的hash值
  • 这些k个hash值映射到对应的k个二进制的数组下标
  • 将k个下标对应的二进制数据改为1

在这里插入图片描述

🛸查询过程

布隆过滤器主要就是来查询一个数据在不在这个二进制集合中,具体方法如下

  • 通过k个hash函数计算该数据,得到hash值
  • 通过hash值找到对应的二进制数字的下标
    如果某一处的二进制数据为0,那么该数据不存在,如果都是1,那么该数据存在集合中

🏳️‍🌈优缺点

⭐优点

布隆过滤器具有以下几个主要的优点:

  • 高效的查询性能:布隆过滤器通过位数组和多个哈希函数实现了快速的元素判断。在查询一个元素是否存在于集合中时,只需要进行多次哈希计算和位数组查询操作,而不需要真正地存储和比较元素本身。因此,查询的时间复杂度是常数级别的,具有非常高的查询效率。
  • 较低的存储需求:布隆过滤器使用位数组表示元素的存在情况,而不需要存储实际的元素本身。且通过多个哈希函数的映射,可以将元素分散到位数组的多个位置上,从而进一步减少存储空间的需求。相比于直接存储元素本身的数据结构,布隆过滤器在存储方面具有较低的空间复杂度。
  • 支持高并发访问:由于布隆过滤器的查询操作只涉及位数组的查询和哈希函数的计算,不需要对实际元素进行读写操作,所以在并发访问的场景下,不会出现数据读写冲突的问题。这使得布隆过滤器非常适合于高并发环境下的数据处理和查询。
  • 可扩展性强:布隆过滤器可以根据需要动态地调整位数组的大小和哈希函数的个数,以适应不同规模和需求的数据集。通过增加位数组的长度和增加哈希函数的数量,可以提高布隆过滤器的准确性和容错性。
  • 简单高效的实现:布隆过滤器的实现相对简单,只需要一个位数组和多个哈希函数即可。哈希函数的选择和设计也相对容易,可以根据实际需求进行调整。这使得布隆过滤器在实际应用中具有较好的可用性和灵活性。

综上所述,布隆过滤器具有高效的查询性能、较低的存储需求、支持高并发访问、可扩展性强和简单高效的实现等优点,使其成为解决大规模数据查询和去重等问题的有效工具。

⭐缺点

布隆过滤器虽然有很多优点,但也存在一些缺点,主要包括以下几个方面:

  • 误判率(False Positive):由于布隆过滤器的设计特性,它可能会产生一定的误判率,即认为一个元素存在于集合中,但实际上并不存在。这是因为多个元素经过哈希函数映射后可能会映射到相同的位数组位置上,从而导致冲突。误判率随着位数组的大小和哈希函数的数量增加而降低,但无法完全消除。
  • 不支持删除操作:布隆过滤器的位数组中存储的是元素是否存在的信息,而不存储元素本身。因此,在布隆过滤器中删除一个元素是比较困难的,通常需要重新创建一个新的布隆过滤器。这限制了布隆过滤器在某些场景下的灵活性和可用性。
  • 无法获取具体元素:由于布隆过滤器只存储元素是否存在的信息,而不存储元素本身,因此无法直接获取具体的元素内容。如果需要获取具体元素,仍需使用其他数据结构进行进一步查询。
  • 存储空间的浪费:虽然布隆过滤器相比其他数据结构具有较低的存储需求,但在一些特定情况下,由于需要保证较低的误判率,可能需要增加位数组的大小和哈希函数的数量,从而导致存储空间的浪费。
  • 初始化时的时间和计算开销:布隆过滤器在初始化时需要分配位数组并进行哈希函数的计算,这个过程可能需要较多的时间和计算资源。尤其是在处理大规模数据集时,初始化的时间和计算开销会比较大。

综上所述,布隆过滤器的主要缺点包括误判率、不支持删除操作、无法获取具体元素、存储空间浪费以及初始化时的时间和计算开销。在使用布隆过滤器时,需要根据实际需求和场景权衡其优缺点,选择合适的数据结构。

假如“你好”和“hello”这2个数据的hash值一样,那么他们将会存储到同一位置
当我们要删除“hello”这个数据的时候,我们会删除存储“hello”这个数据的hash值的位置,由于“hello”和“你好”存储在同一位置,这样子会造成误删
同理
如果仅仅存储了hello,没有存储“你好”,当我们查询“你好”的时候,由于 假设“你好”和“hello”这2个数据的hash值一样,会造成误判

🌹代码实现(本地)

引入依赖

<dependency>
  <groupId>com.google.guava</groupId>
  <artifactId>guava</artifactId>
  <version>29.0-jre</version>
</dependency>

编写核心代码,我们使用下面的代码来测试一下布隆过滤器的误判率

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

public class BloomFilterCase {

  /**
   * 预计要插入多少数据
   */
  private static int size = 1000000;

  /**
   * 期望的误判率
   */
  private static double fpp = 0.01;

  /**
   * 布隆过滤器
   */
  private static BloomFilter<Integer> bloomFilter = BloomFilter.create(Funnels.integerFunnel(), size, fpp);


  public static void main(String[] args) {
    // 插入10万样本数据
    for (int i = 0; i < size; i++) {
      bloomFilter.put(i);
    }

    // 用另外十万测试数据,测试误判率
    int count = 0;
    for (int i = size; i < size + 100000; i++) {
      if (bloomFilter.mightContain(i)) {
        count++;
        System.out.println(i + "误判了");
      }
    }
    System.out.println("总共的误判数:" + count);
  }
}

这里的误判率可以通过fpp参数进行调节,fpp越小,需要的内存空间就越大:0.01需要900多万位数,0.03需要700多万位数。
fpp越小,集合添加数据时,就需要更多的hash函数运算更多的hash值,去存储到对应的数组下标里。

🌹代码实现(分布式)

上面使用Guava实现的布隆过滤器是把数据放在了本地内存中。分布式的场景中就不合适了,无法共享内存。

我们还可以用Redis来实现布隆过滤器,这里使用Redis封装好的客户端工具Redisson。

引入依赖

<dependency>
  <groupId>org.redisson</groupId>
  <artifactId>redisson-spring-boot-starter</artifactId>
  <version>3.13.4</version>
</dependency>

编写核心代码

public class RedissonBloomFilter {

  public static void main(String[] args) {
    Config config = new Config();
    config.useSingleServer().setAddress("redis://127.0.0.1:6379");
    config.useSingleServer().setPassword("1234");
    //构造Redisson
    RedissonClient redisson = Redisson.create(config);

    RBloomFilter<String> bloomFilter = redisson.getBloomFilter("phoneList");
    //初始化布隆过滤器:预计元素为100000000L,误差率为3%
    bloomFilter.tryInit(100000000L,0.03);
    //将号码10086插入到布隆过滤器中
    bloomFilter.add("10086");

    //判断下面号码是否在布隆过滤器中
    //输出false
    System.out.println(bloomFilter.contains("123456"));
    //输出true
    System.out.println(bloomFilter.contains("10086"));
  }
}

代码参考文章:https://mp.weixin.qq.com/s/vwy5oGEWNuQ7k5DQfGrhCQ

在技术的道路上,我们不断探索、不断前行,不断面对挑战、不断突破自我。科技的发展改变着世界,而我们作为技术人员,也在这个过程中书写着自己的篇章。让我们携手并进,共同努力,开创美好的未来!愿我们在科技的征途上不断奋进,创造出更加美好、更加智能的明天!

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1454529.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【鸿蒙系统学习笔记】TypeScript开发语言

一、背景 HarmonyOS 应用的主要开发语言是 ArkTS&#xff0c;它由 TypeScript&#xff08;简称TS&#xff09;扩展而来&#xff0c;在继承TypeScript语法的基础上进行了一系列优化&#xff0c;使开发者能够以更简洁、更自然的方式开发应用。值得注意的是&#xff0c;TypeScrip…

第二篇【传奇开心果系列】Python的文本和语音相互转换库技术点案例示例:深度解读pyttsx3支持多种语音引擎

传奇开心果短博文系列 系列短博文目录Python的文本和语音相互转换库技术点案例示例系列 短博文目录前言一、三种语音引擎支持介绍和示例代码二、SAPI5引擎适用场景介绍和示例代码三、nsss引擎适用场景介绍和示例代码四、eSpeak适用场景介绍和示例代码五、归纳总结 系列短博文目…

【STM32 CubeMX】SPI_Flash_W25Q64的操作方法

文章目录 前言一、W25Q64操作方法基本概念1.1 读数据1.2 写使能1.3 读状态1.4 擦除扇区1.5 烧写页 总结 前言 在嵌入式系统开发中&#xff0c;使用外部 SPI Flash 存储器可以为 STM32 微控制器提供额外的存储空间&#xff0c;以存储程序代码、配置数据等。W25Q64 是一款常见的…

说说对BOM的理解(常见的BOM对象了解哪些)

文章目录 一、是什么二、window三、location四、navigator五、screen六、history 一、是什么 BOM (Browser Object Model)&#xff0c;浏览器对象模型&#xff0c;提供了独立于内容与浏览器窗口进行交互的对象 其作用就是跟浏览器做一些交互效果,比如如何进行页面的后退&…

数据库小技能:事务隔离级别

文章目录 引言I 数据库1.1 事务的隔离级别1.2 报表业务场景:可重复读1.3 高并发场景:读已提交1.4 读写分离1.5 分表规范1.6 分析数据库死锁引言 事务隔离级别的选择: 报表业务场景:可重复读报表业务场景需要同一时间维度进行统计,反应数据趋势,进行查询的时候需要使用re…

基于springboot车辆充电桩管理系统源码和论文

随着信息化时代的到来&#xff0c;管理系统都趋向于智能化、系统化&#xff0c;车辆充电桩管理系统也不例外&#xff0c;但目前国内仍都使用人工管理&#xff0c;市场规模越来越大&#xff0c;同时信息量也越来越庞大&#xff0c;人工管理显然已无法应对时代的变化&#xff0c;…

Qt实用技巧:QCustomPlot做北斗GPS显示绝对位置运动轨迹和相对位置运动轨迹图的时,使图按照输入点顺序连曲线

若该文为原创文章&#xff0c;转载请注明原文出处 本文章博客地址&#xff1a;https://hpzwl.blog.csdn.net/article/details/136131310 红胖子网络科技博文大全&#xff1a;开发技术集合&#xff08;包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬…

2023年全球架构师峰会(ArchSummit北京站2023):核心内容与学习收获(附大会核心PPT下载)

本次峰会是一场集结了全球顶级技术专家和行业领袖的盛会。作为一年一度的重要技术交流活动&#xff0c;本次峰会聚焦当前及未来软件架构的发展趋势、技术挑战与创新实践&#xff0c;旨在为参会者提供一个深度交流、学习与合作的平台。在为期两天的会议中&#xff0c;与会者不仅…

宠物赛道都卷出了哪些花样?媒介盒子分享

如今的宠物市场&#xff0c;已经从让宠物吃饱喝足的基本生理需求&#xff0c;拓展到五花八门的精神需求&#xff0c;与“马斯洛需求定理”高度一致。商家们看到宠物经济的潜力&#xff0c;不再满足于给人类造节&#xff0c;给毛孩子造节也是重中之重&#xff0c;今天媒介盒子就…

vcruntime140.dll文件下载的多种方案分享,最新下载安装方法解析

安装或运行软件时常遇到缺失系统文件的相关问题&#xff0c;一个典型的例子是vcruntime140.dll​丢失错误&#xff0c;这种情况经常发生在运行那些基于Visual Studio 2015开发的应用上。缺乏这个文件的提示可能会严重拖慢程序的响应速度&#xff0c;并有可能阻碍用户使用受影响…

[每周一更]-(第87期):主流软件负载均衡器对比(LVS、Nginx、HAproxy)

负载均衡的实现方式一般来说有以下三种&#xff1a; 基于DNS负载均衡&#xff1a;直接通过DNS来实现负载均衡。优点是非常简单&#xff0c;缺点是调整后不知道啥时生效(当然正常情况下几十分钟&#xff0c;长的也可能更长) 基于硬件负载均衡&#xff1a;购买硬件&#xff0c;也…

三勾点餐系统源码,java后台+微信小程序 实现完整的餐厅点餐

三勾点餐系统基于javaspringbootelement-plusuniapp打造的面向开发的小程序商城&#xff0c;方便二次开发或直接使用&#xff0c;可发布到多端&#xff0c;包括微信小程序、微信公众号、QQ小程序、支付宝小程序、字节跳动小程序、百度小程序、android端、ios端。 功能介绍 1.…

(22.12.20)matlab2022+yalmip+cplex安装教程,win11 x64

前言 Hi,你好&#xff01;最近刚刚更换新的电脑设备&#xff0c;安装软件时尽量选择最新版本&#xff0c;但也遇到了大大小小的安装问题&#xff0c;这里把踩到的坑一并总结出来&#xff0c;给出一份还算合理的MATLAByalmipCPLEX安装教程&#xff08;win11&#xff09;。 MAT…

Code Composer Studio (CCS) - Build All

Code Composer Studio [CCS] - Build All 1. Build AllReferences 1. Build All Project -> Build All (Ctrl B) References [1] Yongqiang Cheng, https://yongqiang.blog.csdn.net/

LeetCode LCR 085. 括号生成

题目链接https://leetcode.cn/problems/IDBivT/description/ 正整数 n 代表生成括号的对数&#xff0c;请设计一个函数&#xff0c;用于能够生成所有可能的并且 有效的 括号组合。 class Solution {public List<String> generateParenthesis(int n) {List<String>…

Ubuntu开启SSH远程登录

正文共&#xff1a;555 字 13 图&#xff0c;预估阅读时间&#xff1a;1 分钟 很久很久之前&#xff0c;我们装了一台Ubuntu&#xff08;66%的经验丰富开发者和69%的学生更喜欢的Ubuntu的安装初体验&#xff09;&#xff0c;今天翻出来准备重新使用一下&#xff0c;突然发现它竟…

boost搜索引擎项目

目录 一、对数据源的数据清洗(去标签)操作&#xff1a;parse.cc二、根据去标签之后的干净的数据构建正排和倒排索引&#xff1a;index.hpp三、提供搜索功能&#xff1a;searcher.hpp四、放公用方法的头文件(包括boost库中的一些方法以及jieba分词的方法)&#xff1a;util.hpp五…

【IntelliJ IDEA】IDEA自动生成serialVersionUID的办法

digest&#xff1a;实体对象实现了java.io.Serializable接口后&#xff0c;一般都会提供一个serialVersionUID一做版本区分。在IDEA里&#xff0c;可以通过一些设置&#xff0c;帮助我们快速生成serialVersionUID。 1.IDEA设置序列化类检测序列化标识 File --> Settings --…

王力宏胜诉,事实胜于雄辩,真相终将大白。

♥ 为方便您进行讨论和分享&#xff0c;同时也为能带给您不一样的参与感。请您在阅读本文之前&#xff0c;点击一下“关注”&#xff0c;非常感谢您的支持&#xff01; 文 |猴哥聊娱乐 编 辑|徐 婷 校 对|侯欢庭 好的&#xff0c;以下是对“2月5日&#xff0c;王力宏工作室在…

中小学信息学奥赛CSP-J认证 CCF非专业级别软件能力认证-入门组初赛模拟题第三套(阅读程序题)

CSP-J入门组初赛模拟题第三套 二、阅读程序题 (程序输入不超过数组或字符串定义的范围&#xff0c;判断题正确填√错误填X;除特殊说明外&#xff0c;判断题 1.5分&#xff0c;选择题3分&#xff0c;共计40分) 第一题 1 #include<iostream> 2 #include<cstdio> …