高并发架构去重难?架构必备技能 - 布隆过滤器

news2024/10/6 8:38:35

系列文章目录

当Dubbo遇到高并发:探究流量控制解决方案
主从选举机制,架构高可用性的不二选择


高并发架构去重难?架构必备技能 - 布隆过滤器

  • 系列文章目录
  • 前言
  • 一、布隆过滤器简介
  • 二、特性与应用场景
  • 三、参数定制
  • 四、java版本的Demo
  • 五、总结


前言

相信熟悉高并发架构的同学,一定都接触过一个名词————“布隆过滤器”,又或者一些朋友接触其实是在学习Redis的时候,了解到其中有这么一种数据类型。但实际上,除了Redis,在高并发或者各种存储性质的架构中,你经常能见到这种设计的存在,那么今天我们就好好说一说这个布隆过滤器

📕作者简介:战斧,从事金融IT行业,有着多年一线开发、架构及管理经验;爱好广泛,乐于分享,致力于创作更多高质量内容
📗本文收录于 JAVA架构,有需要者,可直接订阅专栏实时获取更新
📘高质量专栏 RabbitMQ、Spring全家桶 等仍在更新,欢迎指导
📙Zookeeper Redis kafka docker netty等诸多框架,以及架构与分布式专题即将上线,敬请期待


一、布隆过滤器简介

布隆过滤器是1970年由布隆(Burton Howard Bloom)提出的概率型数据结构:它通过位数组和哈希函数的巧妙结合它可以快速地判断一个元素是否属于某个集合,而且具有高效的存储和查询。虽然布隆过滤器是概率性的,但其性能却相当出色,尤其在处理大规模数据集时,能够显著减少资源消耗。

如下图:我们预先准备一块bit空间存放位数组,(所谓位数组就是一个数组,数组每个位置就是一个bit大小,只有0和1两种情况)。并定义两种哈希算法H1、H2。然后分别计算Orange 和 Lemon 这两个单词,显而易见的,我们将得到4个值,找到这4个值在bit空间的bit位,将其置为1。这就代表我们存入了Orange 和 Lemon 这两个单词。
必须清楚的一点是:布隆过滤器并不存储数据原文,只存数据经过哈希计算后的得到的位置,所以严格来说它能判重,但并不算容器。当下次再存Orange 或 Lemon的时候,执行上述步骤,我们就能发现对应bit位全为1,则代表数据可能存储过了
在这里插入图片描述
之所以说可能,是因为可能有别的单词,经过上述H1、H2计算后,落在同样的的两个bit位上,而恰好此时两个bit位都已经被置为1,从而导致误判(如上图的Onion单词)


二、特性与应用场景

其实从上面举得例子,不难总结出布隆过滤器至少有这么几个特性:

  • 快速查询:布隆过滤器具有非常快速的查询操作。无论数据规模多大,查询的时间复杂度都是O(k),其中k是哈希函数的数量

  • 节省空间:相对于其他数据结构,布隆过滤器在存储大规模数据时非常节省空间。它使用位数组来存储数据,而不需要存储实际的元素本身。

  • 概率性判断:布隆过滤器是一个概率性数据结构,意味着在判断一个元素是否存在时,有一定的误判率。如果判断元素不存在,那么它一定不存在;但如果判断元素存在,那么它可能并不存在,因为存在哈希冲突。

  • 元素插入不可逆:一旦将元素插入布隆过滤器,就无法删除或修改该元素。因为删除元素需要将对应的位数组位置置为0,这可能会影响其他元素的判断。

  • 哈希函数的重要性:布隆过滤器的性能和效果与使用的哈希函数密切相关。合理选择和设计哈希函数可以有效降低误判率

结合上述特性,其实我们可以看到布隆过滤器 最适合的场景就是在大数据量下的判重, 因为其速度快、节约空间。虽然可能有“假阳性”(即不存在的数据也判重了)、bit位不可逆的问题,但这些问题通过哈希函数的选择,定好初始bit空间的大小,能很大的程度上的缓解。因此,至今,高并发或重存储的架构下,布隆过滤器,都有着广阔的应用。


三、参数定制

布隆过滤器的大小和哈希函数的个数是根据实际应用场景来确定的,需要平衡误判率和存储空间之间的关系。

一般来说,布隆过滤器的大小是根据预期要处理的数据量和误判率来确定的。误判率越小,需要的空间就越大。哈希函数的个数一般根据预期要处理的数据量和布隆过滤器的大小来确定,一般情况下,哈希函数的个数越多,误判率越小

所以,使用布隆过滤器,有几个方面是我们一开始就要敲定的,就是对未来数据量的预估,以及误差率的限制。我们可以直接给出以下两个公式:

  • m = - (n * ln(p)) / (ln(2)^2)

  • k = (m / n) * ln(2)

其中,m 表示布隆过滤器的大小,k 表示哈希函数的个数,n 表示要处理的数据量,p 表示允许的误差率。我们假设有如下场景:

我们要建立一个网盘产品,为避免一个文件重复存储,预计文件数量将达到20亿条数据,要求在用户上传文件时进行文件判重,误差率要求3%以内。

利用上面的公式:可以计算出:
m = - (20亿 * ln(0.03)) / (ln(2)^2) ≈ 14596881675.7 bits ≈ 1740 MB
k = ( 14596881675.7 / 20亿) * ln(2) ≈ 5.05

因此,可以将布隆过滤器的大小设置为 1740 MB,哈希函数的个数设置为 5个
如果你懒得计算,这里也有一个现成的网站来帮你算: 布隆过滤器参数计算网站 ,可以看到结果是一致的。
在这里插入图片描述


四、java版本的Demo

我们可以利用JAVA中自带的hashCode函数,和BitSet类来写一个布隆过滤器的Demo

public class BloomFilter<T> {
    private final int size;
    private final BitSet bitSet;

    public BloomFilter(int size) {
        this.size = size;
        this.bitSet = new BitSet(size);
    }

    private int hashFunction1(T value) {
        return Math.abs(value.hashCode()) % size;
    }

    private int hashFunction2(T value) {
        return Math.abs(value.hashCode() / 31) % size;
    }

    public void add(T value) {
        int hash1 = hashFunction1(value);
        int hash2 = hashFunction2(value);
        bitSet.set(hash1);
        bitSet.set(hash2);
    }

    public boolean contains(T value) {
        int hash1 = hashFunction1(value);
        int hash2 = hashFunction2(value);
        return bitSet.get(hash1) && bitSet.get(hash2);
    }
}

再写一个main函数进行验证,结果符合预期。

public static void main(String[] args) {
        BloomFilter<String> bloomFilter = new BloomFilter<>(1000);

        bloomFilter.add("apple");
        bloomFilter.add("banana");

        System.out.println(bloomFilter.contains("apple"));  // Output: true
        System.out.println(bloomFilter.contains("orange")); // Output: false
}

在这里插入图片描述


五、总结

虽然,我们在第四章使用java写出了一个布隆过滤器的Demo,但显然是不够好的,比如其设计容量得太小,还使用了两个关联的哈希函数。在真实环境中,如果要我们写过滤器,我们还是要严格遵守第三章的公式进行容量和哈希函数的计算。同时哈希函数也应该具有以下几个特点:

  1. 哈希函数需要快速计算,因为布隆过滤器的效率很大程度上依赖于哈希函数的效率
  2. 哈希函数需要输出的哈希值应该尽可能分散、均匀,并且无法推断出输入元素的信息,这样可以使得误判率最小
  3. 哈希函数互相之间应该独立,这样可以保证哈希值之间相互独立,降低误判率

当然,业界也有现成的布隆过滤器供我们使用,比如Google Guava BloomFilter 、Apache Commons Collections BloomFilter 还有很多人熟知的Redis BloomFilter。

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

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

相关文章

安全学习DAY13_WEB应用源码获取

信息打点-WEB应用-源码获取 文章目录 信息打点-WEB应用-源码获取小节概述-思维导图资产架构-源码获取&#xff08;后端&#xff09;后端-开源后端-闭源-源码泄露源码泄露原因源码泄露方式集合网站备份压缩包git&#xff0c;svn源码泄露DS_Store文件泄露composer.json 泄露资源搜…

网络安全 Day24-select高级用法和多表连接

select高级用法和多表连接 1. select 多子句单表高级实践1.1 select 多子句高级语法1.2 聚合函数1.3 group by 实践1.4 having 筛选1.5 order by 排序1.6 limit 2. 多表连接 1. select 多子句单表高级实践 1.1 select 多子句高级语法 where 和 having 区别是后者是分组后进行…

计算机视觉实验:人脸识别系统设计

实验内容 设计计算机视觉目标识别系统&#xff0c;与实际应用有关&#xff08;建议&#xff1a;最终展示形式为带界面可运行的系统&#xff09;&#xff0c;以下内容选择其中一个做。 1. 人脸识别系统设计 (1) 人脸识别系统设计&#xff08;必做&#xff09;&#xff1a;根据…

【iOS】Cydia Impactor 错误:file http.hpp; line:37; what: _assert(code == 200)

Cydia Impactor 报错&#xff0c;信息如下 file http.hpp; line:37; what: _assert(code 200)解决方案&#xff1a;Cydia Impactor 已被弃用&#xff0c;切换到sideloadly 即可&#xff0c;亲测成功&#xff0c;并且支持双重验证登录 csdn备份地址 HERE

kotlin 编写一个简单的天气预报app(四)增加界面显示

编写界面来显示返回的数据 用户友好性&#xff1a;通过界面设计和用户体验优化&#xff0c;可以使天气信息更易读、易理解和易操作。有效的界面设计可以提高用户满意度并提供更好的交互体验。 增加城市名字的TextView <TextViewandroid:id"id/textViewCityName"…

华为OD机试 Java 实现【批量处理任务】【2023 B卷 200分】,二分查找

目录 专栏导读一、题目描述二、输入描述三、输出描述四、二分查找五、解题思路六、Java算法源码七、效果展示1、输入2、输出3、说明 华为OD机试 2023B卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试&#xff08;JAVA&#xff09;真题&#xff08;…

SPSS常见图表一览

SPSS是一个统计分析软件&#xff0c;而不是可视化分析工具&#xff0c;它输出的图表主要便于我们更好的理解输出结果&#xff0c;了解数据的基本分布形态。 因此&#xff0c;SPSS中的图表并不复杂&#xff0c;但不能说不重要&#xff0c;我们不需要花费太多时间深究&#xff0…

Postgresql源码(109)并行框架实例与分析

1 PostgreSQL并行参数 系统参数 系统总worker限制&#xff1a;max_worker_processes 默认8 系统总并发限制&#xff1a;max_parallel_workers 默认8 单Query限制&#xff1a;max_parallel_workers_per_gather 默认2 表参数限制&#xff1a;parallel_workers alter table tbl …

什么是 DNS ANAME 解析?

本人使用谷歌搜索了简中互联网&#xff0c;完全没有找到任何有关 ANAME 的文章……本文该不会是头一份吧 相信大家对于 DNS 的解析方式都不陌生&#xff0c;常见的有 A、CNAME、MX、TXT 记录等等。其中&#xff0c;网站常用的是 A 记录和 CNAME 记录&#xff1a;A 记录用于将域…

SQL Developer中的Active Data Guard

这篇文章 Display Data Guard configuration in SQL Developer 中&#xff0c;用SQL Developer展示了多种ADG的拓扑。 今天自己也试了一下&#xff0c;还蛮简单的&#xff0c;其实最麻烦的部分在于搭建一个ADG环境。 假设我已有一个ADG环境&#xff0c;即最典型的环境&#x…

数据库事务--数据库事务基本概念

2、认识事务 2.1、为什么需要事务 如何解决呢 使用事务 2.2、什么是事务 事务的概念: 数据库事务是访问并可能更新数据库中各种数据项的一个程序执行单元 事务的组成: 一个数据库事务通常包含对数据库进行读或写的的一个操作序列 事务的相关特性: 数据库事务可以包含一个或多…

EPICS通道访问介绍以及练习

提纲 1&#xff09; 通道访问概念 2&#xff09;通道访问API 3&#xff09; 简单的CA客户端 4&#xff09;使用回调的简单CA客户端 EPICS概要 搜索和连接过程 搜索请求 1&#xff09;搜索请求由一系列UDP包组成 只发送给EPICS_CA_ADDR_LIST从短时间间隔开始&#xff0c;每…

vue部署在iis的字体获取报错,请求404 - 找不到文件或目录

配置MIME即可 在添加MIME类型中&#xff0c;增加以下信息&#xff1a; 文件扩展名&#xff1a;.woff MIME类型&#xff1a;application/x-font-woff

DHorse v1.3.0 发布,基于k8s的发布平台

综述 DHorse是一个简单易用、以应用为中心的云原生DevOps系统&#xff0c;具有持续集成、持续部署、微服务治理等功能&#xff0c;无需安装依赖Docker、Maven、Node等环境即可发布Java、Vue、React应用&#xff0c;主要特点&#xff1a;部署简单、操作简洁、功能快速。 新增特…

《ChatGPT原理最佳解释,从根上理解ChatGPT》

【热点】 2022年11月30日&#xff0c;OpenAI发布ChatGPT&#xff08;全名&#xff1a;Chat Generative Pre-trained Transformer&#xff09;&#xff0c; 即聊天机器人程序 &#xff0c;开启AIGC的研究热潮。 ChatGPT是人工智能技术驱动的自然语言处理工具&#xff0c;它能够…

深入理解 SQL:从基本查询到高级聚合

目录 背景理论知识示例1211. 查询结果的质量和占比&#xff08;Round group by&#xff09;1204. 最后一个能进入巴士的人 &#xff08;Having limit order by&#xff09;1193. 每月交易 I&#xff08;if group by&#xff09;1179. 重新格式化部门表1174. 即时食物配送 II&am…

关于DC电源模块输入电压范围的问题

BOSHIDA 关于DC电源模块输入电压范围的问题 DC电源模块是一种将交流电转换为直流电的设备&#xff0c;它非常常见且广泛应用于电子设备、通讯设备、工业自动化等领域。而其输入电压范围也是我们在使用和选购DC电源模块时需要特别关注的一个参数。 首先&#xff0c;我们需要了解…

java的空引用null和空字符串““

java中如果字符串变量指向null&#xff0c;表示空引用&#xff0c;此时对字符串求长度会抛出异常。 而""表示一个空字符串&#xff0c;对字符串求长度是可以的&#xff0c;求出来的字符串长度为0。 举例&#xff1a; package com.thb;public class Test6 {public s…

数字电路(一)

1、例题 1、进行DA数模转换器选型时&#xff0c;一般要选择主要参数有&#xff08; A&#xff09;、转换精度和转换速度。 A、分辨率 B、输出电流 C、输出电阻 D、模拟开关 2、下图所示电路的逻辑功能为&#xff08; B&#xff09; A、与门 B、或门 C、与非门 D、或非门 分析该…

导出文件下载进度条简单实现

前言 今天要跟大家分享的是一个导出数据进度条的简单实现&#xff0c;适用场景用在数据量大、组织数据耗时的情况下的简单实现。 一、设计思路 1、导出数据生成文件上传到OSS&#xff0c; 2、导出数据状态存redis缓存&#xff0c; 3、前端发导出请求后&#xff0c;返回的文件k…