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

系列文章目录

当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: trueSystem.out.println(bloomFilter.contains("orange")); // Output: false
}

在这里插入图片描述


五、总结

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

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

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

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

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

相关文章

<findbugs>静态代码分析工具

背景&#xff1a; IDEA安装的findbug插件目前无法和jenkins的扫描结果保持一致&#xff0c;因为&#xff1a;没有对应jenkins上findbug的版本&#xff1b; 原理&#xff1a; 将jenkins服务器上的findbugs插件&#xff0c;拷贝到本地&#xff0c;修改build.xml内容以匹配目录…

Resnet与Pytorch花图像分类

1、介绍 1.1数据集介绍 flower_data├── train│ └── 1-102&#xff08;102个文件夹&#xff09;│ └── XXX.jpg&#xff08;每个文件夹含若干张图像&#xff09;├── valid│ └── 1-102&#xff08;102个文件夹&#xff09;└── ─── └── XXX.jp…

Python读取csv、Excel文件生成图表

简介 本文章介绍了通过读取 csv 或 Excel 文件内容&#xff0c;将其转换为折线图或柱状图的方法&#xff0c;并写入 html 文件中。 目录 1. 读取CSV文件 1.1. 生成折线图 1.1.1. 简单生成图表 1.1.2. 设置折线图格式 1.2. 生成柱状图 1.2.1. 简单生成图表 1.2.2. 设置柱…

关于阿里云OSS服务器绑定域名及Https证书

这是一个没有套路的前端博主&#xff0c;热衷各种前端向的骚操作&#xff0c;经常想到哪就写到哪&#xff0c;如果有感兴趣的技术和前端效果可以留言&#xff5e;博主看到后会去代替大家踩坑的&#xff5e; 主页: oliver尹的主页 格言: 跌倒了爬起来就好&#xff5e; 关于阿里云…

零基础玩转C语言—结构体【初阶】

大家好&#xff0c;我是深鱼~ 目录 【前言】&#xff1a; 一、结构体的声明 1.1结构的基本知识 1.2结构的声明 1.3结构体成员的类型 1.4结构体变量的定义和初始化 二、结构体成员的访问 【前言】&#xff1a;本章来介绍结构体的部分知识&#xff0c;并不会深入讲解&…

NOSQL之Redis配置及优化

目录 一、关系型数据库 二、非关系型数据库 三、关系型数据库和非关系型数据库区别 1、数据存储方式不同 2、扩展方式不同 3、对事务性的支持不同 四、Redis简介 五、Redis优点 &#xff08;1&#xff09;具有极高的数据读写速度 &#xff08;2&#xff09;支持丰富的…

基于解析法和遗传算法相结合的配电网多台分布式电源降损配置(Matlab实现)

目录 1 概述 2 数学模型 2.1 问题表述 2.2 DG的最佳位置和容量&#xff08;解析法&#xff09; 2.3 使用 GA 进行最佳功率因数确定和 DG 分配 3 仿真结果与讨论 3.1 33 节点测试配电系统的仿真 3.2 69 节点测试配电系统仿真 4 结论 1 概述 为了使系统网损达到最低值&a…

C 语言 - 存储类说明符

【预备知识】 1&#xff09;C 语言 - 存储时期 2&#xff09;C 语言 - 链接属性 3&#xff09;C 语言 - 作用域 1. 分类&#xff1a; C 语言为变量提供了 5 中不同的存储模型&#xff08;即存储类&#xff09;。 &#xff08;此外还有基于指针的第 6 种存储模型&#xff0c…

html实现蜂窝菜单

效果图 CSS样式 keyframes _fade-in_mkmxd_1 {0% {filter: blur(20px);opacity: 0}to {filter: none;opacity: 1} } keyframes _drop-in_mkmxd_1 {0% {transform: var(--transform) translateY(-100px) translateZ(400px)}to {transform: var(--transform)} } ._examples_mkmx…

uniapp小程序,根据小程序的环境版本,控制的显页面功能按钮的示隐藏

需求&#xff1a;根据小程序环境控制控制页面某个功能按钮的显示隐藏&#xff1b; 下面是官方文档和功能实现的相关代码&#xff1a; 实现上面需要&#xff0c;用到了uni.getAccountInfoSync()&#xff1a; uni.getAccountInfoSync() 是一个 Uniapp 提供的同步方法&#xff0c…

rsync远程同步

文章目录 一.rsync简介1.一款快速增量备份工具2.rsync应用场景2.1 rsyncinotify的应用场景2.2 rsynccron的应用场景 二.配置rsync备份源&#xff08;同步方式&#xff09;1.rsync同步源2.同步方式3.备份的方式 三.常用rsync命令1.基本格式2.常用选项3.配置源的两种表达 四.配置…

Android 面试题 内存泄露的原因 二

&#x1f525; 什么是内存泄漏 &#x1f525; 在Android开发过程中&#xff0c;当一个对象已经不需要再使用了&#xff0c;本该被回收时&#xff0c;而另个正在使用的对象持有它引用从而导致它不能被回收&#xff0c;这就导致本该被回收的对象不能被回收而停留在堆内存中&#…

SQL-每日一题【626.换座位】

题目 表: Seat 编写SQL查询来交换每两个连续的学生的座位号。如果学生的数量是奇数&#xff0c;则最后一个学生的id不交换。 按 id 升序 返回结果表。 查询结果格式如下所示。 示例 1: 解题思路 前置知识 MySQL 的 MOD() 函数是取模运算的函数&#xff0c;它返回两个数相除…

【自用记录】常见的第三方接口加密签名方式(ASCll码字典序、URL键值对、 SHA-256加密、MD5加密)

案例1: 案例2: 以上第三方接口都用类似的加密签名方式,两者有类似的部分: 方案1的: $kdata = array(parkId=>$parkId,ts => $ts,serviceCode=>getParkingPaymentList,reqId => $reqId,plateNo => $car_code,//车牌 可为空pageIndex => 1,//第几页page…

无涯教程-jQuery - innerHeight( )方法函数

innerHeight()方法获取第一个匹配元素的内部高度(不包括边框&#xff0c;包括填充)。 innerHeight( ) - 语法 selector.innerHeight( ) innerHeight( ) - 示例 以下是一个简单的示例&#xff0c;简单说明了此方法的用法- <html><head><title>The jQuery…

适合做笔记的软件有哪些?8款好用强大的笔记软件推荐!

除了Goodnotes和Notability&#xff0c;你还知道哪些值得推荐的免费笔记软件吗&#xff1f;本文结合自己的使用经验&#xff0c;推荐笔记软件的同时&#xff0c;亦推荐一些不错的绘图软件供大家选择使用。 1.OneNote 基本的笔记功能都有&#xff0c;加粗、倾斜、下划线、突…

TPlink云路由器界面端口映射设置方法?快解析内网穿透能实现吗?

有很多网友在问&#xff1a;TPlink路由器端口映射怎么设置&#xff1f;因为不懂端口映射的原理&#xff0c;所以无从下手&#xff0c;下面小编就给大家分享TPlink云路由器界面端口映射设置方法&#xff0c;帮助大家快速入门TP路由器端口映射设置方法。 1.登录路由器管理界面&a…

高等数学中如何求间断点

高等数学中求间断点是一项重要的技巧&#xff0c;特别适用于分析函数的性质和图像的特征。在本文中&#xff0c;我们将深入探讨如何在给定函数中找到间断点&#xff0c;并解释其数学原理和实际应用。 什么是间断点&#xff1f; 在高等数学中&#xff0c;间断点是指函数在某个点…

【C++从0到王者】第十四站:list基本使用及其介绍

文章目录 一、list基本介绍二、list基本使用1.尾插头插接口使用2.insert接口使用3.查找某个值所在的位置4.erase接口使用以及迭代器失效5.reverse6.sort7.merge8.unique9.remove11.splice 三、list基本使用完整代码 一、list基本介绍 如下所示&#xff0c;是库里面对list的基本…

pytorch学习——正则化技术——权重衰减

一、概念介绍 权重衰减&#xff08;Weight Decay&#xff09;是一种常用的正则化技术&#xff0c;它通过在损失函数中添加一个惩罚项来限制模型的复杂度&#xff0c;从而防止过拟合。 在训练参数化机器学习模型时&#xff0c; 权重衰减&#xff08;weight decay&#xff09;是…