【大数据实战】亿级数据量: 检索一个元素是否在一个集合中 [bloom过滤器及其应用]

目录

  • 亿级数据量: 检索一个元素是否在一个集合中 [bloom过滤器]
    • 问题描述
    • bloom过滤器简介
      • 传统方法
      • 哈希表
      • bloom的思路
    • bloom过滤器为什么快?
    • bloom过滤器更加节省空间!
    • 优缺点
    • 实际应用
      • java
      • go
      • python

亿级数据量: 检索一个元素是否在一个集合中 [bloom过滤器]

问题描述

在实际项目中,我们经常会遇到判断单个元素是否在一个集合中的情况,比如:网页URL去重、垃圾邮件识别、大集合中重复元素、海量数据去重和缓存穿透(本来要查数据库,但如果我们可以提前感知这个元素是否在数据库中,就可以减少数据库的压力)等问题。在数据量很小(几千或者几万)的时候,利用一些常见的数据结构,比如Set, HashSet等,可以比较轻易的判断,但是当数据规模达到亿级别的情况下,想要在s甚至ms级别返回结果的话,就比较捉襟见肘了。此时,bloom过滤器这个利器就登场了,bloom过滤器主要解决的就是 海量数据的存在性问题

bloom过滤器简介

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

传统方法

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

哈希表

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

bloom的思路

bloom过滤器可以实现的功能:

  • 某个值可能在集合中
  • 某个值绝对不在集合中
    也就是说:bloom过滤器来判断某个值在某个大集合中,是有一定概率的,表示存在一定的误判率。那为什么会存在误判呢?这是由它的原理决定的。

内部原理

  • 本质结构
    长度为m的位向量或位列表(仅包含0或者1值的列表)组成。最初的情况下所有值都为0:
    在这里插入图片描述

  • 数据映射
    当我们将一个数据加入到bloom过滤器中的时候,会提供k个不同的哈希函数(没错,这里会用到哈希函数,但是注意不止一个,是有k个不同的哈希函数)
    在前面所提到的哈希表中,我们使用的是单个哈希函数,因此只能输出单个索引值。而对于布隆过滤器来说,我们将使用多个哈希函数,这将会产生多个索引值。
    在这里插入图片描述
    1)如上图所示,当输入 “semlinker” 时,预设的 3 个哈希函数将输出 2、4、6,我们把相应位置 1。
    2)假设另一个输入 ”kakuqo“,哈希函数输出 3、4 和 7。(你可能已经注意到,索引位 4 已经被先前的 “semlinker” 标记了。此时,我们已经使用 “semlinker” 和 ”kakuqo“ 两个输入值,填充了位向量。)
    上图变成:
    在这里插入图片描述

  • 数据检索
    根据上图所示,当我们检索kakuqo的时候,通过三个hash函数,会映射到3,4,7三个位置,结果可以看到都是1,表示存在对应的值。
    当我们检索fullstack的时候,假如输出的三个索引为2,3,7 可以看到其实也命中了。但是:我们并没有向其中插入fullstack数据,所以这里存在误判了
    产生的原因是由于哈希碰撞导致的巧合而将不同的元素存储在相同的比特位上

  • 误判率 FPP
    上面误判的概率其实可以有公式进行计算的:
    在这里插入图片描述
    n 是已经添加元素的数量;
    k 哈希的次数;
    m 布隆过滤器的长度(如比特数组的大小);
    注意:当bloom过滤器满的时候,每一次查询都会返回true;所以m的选择取决于想要放入的数据量,并且m要远远大于n。
    布隆过滤器的长度 m 可以根据给定的误判率(FFP)的和期望添加的元素个数 n 的通过如下公式计算:
    在这里插入图片描述

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

bloom过滤器为什么快?

使用类似hashMap的原理,使得它的插入和查询速度是非常快的,时间复杂度是O(K),可以联想一下HashMap的过程。

bloom过滤器更加节省空间!

Bloom Filter 会使用一个较大的 bit 数组来保存所有的数据,数组中的每个元素都只占用 1 bit ,并且每个元素只能是 0 或者 1(代表 false 或者 true),这也是 Bloom Filter 节省内存的核心所在。这样来算的话,申请一个 100w 个元素的位数组只占用 1000000Bit / 8 = 125000 Byte = 125000/1024 KB ≈ 122KB 的空间。
在这里插入图片描述

优缺点

  • 优点:性能好 && 高效&&安全性好,本身不存储任何原始数据,只有二进制数据
  • 缺点:一定的错误识别率 && 删除难度大

实际应用

java

在Java中,你可以使用第三方库来实现布隆过滤器,比如Google的Guava库或Apache的Commons库。下面我将介绍如何在Java中使用Guava库来应用布隆过滤器。

首先,你需要在你的Java项目中添加Guava库的依赖。你可以在你的构建工具(如Maven或Gradle)的配置文件中添加以下依赖:

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

一旦你添加了依赖,你就可以在你的Java代码中使用Guava的布隆过滤器了。下面是一个简单的示例:

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

public class BloomFilterExample {
    public static void main(String[] args) {
        // 创建一个布隆过滤器,设置期望插入的元素个数和误判率
        BloomFilter<String> bloomFilter = BloomFilter.create(Funnels.unencodedCharsFunnel(), 1000, 0.01);

        // 向布隆过滤器中插入元素
        bloomFilter.put("apple");
        bloomFilter.put("banana");
        bloomFilter.put("orange");

        // 判断元素是否存在于布隆过滤器中
        System.out.println(bloomFilter.mightContain("apple"));   // true
        System.out.println(bloomFilter.mightContain("pear"));    // false
        System.out.println(bloomFilter.mightContain("banana"));  // true
    }
}

在上面的示例中,我们首先创建了一个布隆过滤器,设置了期望插入的元素个数为1000,误判率为0.01。然后我们向布隆过滤器中插入了几个元素,最后使用mightContain方法来判断元素是否存在于布隆过滤器中。

go

在Go语言中应用布隆过滤器相对简单,并且Go标准库中提供了github.com/willf/bloom包,可以方便地实现布隆过滤器功能。下面是一个在Go中使用布隆过滤器的示例:

首先,你需要安装github.com/willf/bloom包,可以使用以下命令进行安装:

go get github.com/willf/bloom

安装完成后,你可以在你的Go代码中导入该包并使用布隆过滤器。下面是一个简单的示例:

package main

import (
	"fmt"
	"github.com/willf/bloom"
)

func main() {
	// 创建一个布隆过滤器,设置期望插入的元素个数和误判率
	bf := bloom.New(1000, 0.01)

	// 向布隆过滤器中插入元素
	bf.Add([]byte("apple"))
	bf.Add([]byte("banana"))
	bf.Add([]byte("orange"))

	// 判断元素是否存在于布隆过滤器中
	fmt.Println(bf.Test([]byte("apple")))   // true
	fmt.Println(bf.Test([]byte("pear")))    // false
	fmt.Println(bf.Test([]byte("banana")))  // true
}

在上面的示例中,我们首先使用bloom.New函数创建了一个布隆过滤器,设置了期望插入的元素个数为1000,误判率为0.01。然后我们使用Add方法向布隆过滤器中插入了几个元素,最后使用Test方法来判断元素是否存在于布隆过滤器中。

python

在Python中,你可以使用pybloom_liveredisbloom等第三方库来实现布隆过滤器。下面我将演示如何在Python中使用pybloom_live库来应用布隆过滤器。

首先,你需要安装pybloom_live库。你可以使用以下命令通过pip来安装:

pip install pybloom_live

安装完成后,你可以在Python代码中导入pybloom_live库并使用布隆过滤器。下面是一个简单的示例:

from pybloom_live import BloomFilter

# 创建一个布隆过滤器,设置期望插入的元素个数和误判率
bf = BloomFilter(capacity=1000, error_rate=0.01)

# 向布隆过滤器中插入元素
bf.add("apple")
bf.add("banana")
bf.add("orange")

# 判断元素是否存在于布隆过滤器中
print("apple" in bf)   # True
print("pear" in bf)    # False
print("banana" in bf)  # True

在上面的示例中,我们首先使用BloomFilter类创建了一个布隆过滤器,设置了期望插入的元素个数为1000,误判率为0.01。然后我们使用add方法向布隆过滤器中插入了几个元素,最后使用in关键字来判断元素是否存在于布隆过滤器中。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

uniapp中用户登录数据的存储方法探究

Hello大家好&#xff01;我是咕噜铁蛋&#xff01;作为一个博主&#xff0c;我们经常需要在应用程序中实现用户登录功能&#xff0c;并且需要将用户的登录数据进行存储&#xff0c;以便在多次使用应用程序时能够方便地获取用户信息。铁蛋通过科技手段帮大家收集整理了些知识&am…

python解决一维动态规划问题,寻找丑数

对于一维动态规划问题中&#xff0c;还有一个可能会经常遇到的问题&#xff0c;就是寻找丑数。 对于丑数的概念是&#xff0c;把只包含质因子2、3和5的数称作丑数&#xff08;Ugly Number&#xff09;。 添加图片注释&#xff0c;不超过 140 字&#xff08;可选&#xff09; 添…

8、VS中Git使用

VS中Git使用 1.基础操作1.1 VS配置Git1.2 操作界面 2.本地库版本管理2.1 创建管理本地库2.2 暂存、存储2.3 提交2.4 版本切换 3.分支操作3.1 分支应用3.2 新建分支3.3 合并分支、解决冲突3.4 删除分支 4.远程库版本管理4.1 新建、克隆4.2 提取、拉取、推送与同步4.3 团队开发 最…

基于随机颜色反转合成和双分支学习的单模态内镜息肉分割

Single-Modality Endoscopic Polyp Segmentation via Random Color Reversal Synthesis and Two-Branched Learning 基于随机颜色反转合成和双分支学习的单模态内镜息肉分割背景难点贡献实验方法Color Reversal Strategy&#xff08;颜色反转策略&#xff09; 损失函数Thinking…

Python 箱线图的绘制(Matplotlib篇-13)

Python 箱线图的绘制(Matplotlib篇-13)         🍹博主 侯小啾 感谢您的支持与信赖。☀️ 🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ�…

[DevOps-02] Code编码阶段工具

一、简要说明 在code阶段,我们需要将不同版本的代码存储到一个仓库中,常见的版本控制工具就是SVN或者Git,这里我们采用Git作为版本控制工具,GitLab作为远程仓库。 Git安装安装GitLab配置GitLab登录账户二、Git安装 Git官网 Githttps://git-scm.com/

【Java进阶篇】Java中Timer实现定时调度的原理(解析)

Java中Timer实现定时调度的原理 ✔️ 引言✔️JDK 中Timer类的定义✔️拓展知识仓✔️优缺点 ✔️ 引言 Java中的Timer类是用于计划执行一项任务一次或重复固定延迟执行的简单工具。它使用一个名为TaskQueue的内部类来存储要执行的任务&#xff0c;这些任务被封装为TimerTask对…

小肥柴慢慢手写数据结构(C篇)(5-2 AVL树)

小肥柴慢慢学习数据结构笔记&#xff08;C篇&#xff09;&#xff08;5-2 AVL树 目录5-5 AVL出现的原因5-5-1 平衡树5-5-2 平衡二叉树的具体案例 5-6 AVL平衡策略的讨论5-7 不使用平衡因子的实现&#xff08;黑皮书&#xff0c;训练思维&#xff09;5-8 使用平衡因子的实现&…

【RocketMQ每日一问】RocketMQ SQL92过滤用法以及原理?

1.生产端 public class SQLProducer {public static int count 10;public static String topic "xiao-zou-topic";public static void main(String[] args) {DefaultMQProducer producer MQUtils.createLocalProducer();IntStream.range(0, count).forEach(i -&g…

管程-第三十五天

目录 为什么要引入管程 管程的定义和基本特征 用管程解决生产者消费者问题 结论 本节思维导图 为什么要引入管程 原因&#xff1a;在解决进程的同步与互斥问题时&#xff0c;信号量机制存在编写困难和易出错的问题 能不能设计一种机制&#xff0c;让程序员写程序时不再需…

从 YOLOv1 到 YOLO-NAS 的所有 YOLO 模型:论文解析

在计算机视觉的浩瀚领域&#xff0c;有一支耀眼的明星&#xff0c;她的名字传颂着革新与突破的传奇——YOLO&#xff08;You Only Look Once&#xff09;。回溯时光&#xff0c;走进这个引人注目的名字背后&#xff0c;我们仿佛穿越进一幅画卷&#xff0c;一幅展现创新魅力与技…

【elfboard linux开发板】4. 文件点灯与创建多进程

ps&#xff1a;提升效率的小tips&#xff1a; 灵活运用vim操作命令&#xff0c;gg快速跳转到文件开头&#xff0c;G跳转到结尾 多行操作 ctrl V shift i 插入修改内容 esc退出编辑 sudo vi /etc/vim/vimrc 在文件中添加如下内容省略重复工作&#xff1a; autocmd BufNewFile …

飞腾Ubantu22.04.3安装OpenNebula测试

1.概述 因OpenneBula官方镜像源只有AMD架构的镜像包不存在ARM的镜像包&#xff0c;借此用源码编译进行测试。 2.官网github地址 下载解压存放在服务器上&#xff1a; https://github.com/OpenNebula/minione/blob/master文件目录&#xff1a; 3.安装依赖包 sudo apt -y …

智慧农田使用的自动虫情测报灯的作用

TH-CQ3S随着科技的不断进步&#xff0c;智慧农业正在全球范围内兴起。作为智慧农业的重要组成部分&#xff0c;智慧农田已经成为提高农业生产效率、保障农产品质量安全的重要手段。而在智慧农田中&#xff0c;自动虫情测报灯的作用不可忽视。 自动虫情测报灯&#xff0c;顾名思…

腾讯云轻量服务器2核2G4M带宽118元一年,3年540「新老用户均可」

它急了&#xff0c;腾讯云急了&#xff0c;继阿里云推出99元新老用户同享的云服务器后&#xff0c;腾讯云轻量应用服务器2核2G4M配置也支持新老用户同享了&#xff0c;一年118元&#xff0c;3年540元&#xff0c;老用户也能买&#xff0c;50GB SSD系统盘&#xff0c;300GB 月流…

数据分析中常见的问题之一:怎么用SPSS来读取Stata数据文件?

我们以本书附带的“数据1F”为例进行读取Stata数据文件的讲解。“数据1F”是一个Stata数据文件&#xff0c;如图所示。 首先启动SPSS软件或者在一个已经打开的SPSS数据文件的数据视图中从菜单栏选择“文件| 打开 | 数据”命令&#xff0c;如图所示。 然后就会出现如图1.77所示的…

php安装扩展event 提示 No package ‘openssl‘ found 解决方法

在使用pecl编译安装最新版event模块的时候提示 No package openssl found , 可是本机是安装了openssl的, 编译时找不到, 大概率就是环境配置的问题了, 增加 OPENSSL_CFLAGS OPENSSL_LIBS环境变量即可解决. 异常提示信息: checking for openssl > 1.0.2... no configure: …

基于SSM的网络游戏交易平台设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;Vue 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#xff1a;是 目录…

线程的深入学习(二)

前言 上一篇讲了线程池的相关知识&#xff0c;这篇文章主要讲解一个 1.并发工具类如CountDownLatch、CyclicBarrier等。 2.线程安全和并发集合&#xff1a; 3.学习如何使用Java提供的线程安全的集合类&#xff0c;如ConcurrentHashMap、CopyOnWriteArrayList等。 并发工具类 …

2023-12-11 LeetCode每日一题(最小体力消耗路径)

2023-12-11每日一题 一、题目编号 1631. 最小体力消耗路径二、题目链接 点击跳转到题目位置 三、题目描述 你准备参加一场远足活动。给你一个二维 rows x columns 的地图 heights &#xff0c;其中 heights[row][col] 表示格子 (row, col) 的高度。一开始你在最左上角的格…
最新文章