【项目实践03】【布隆过滤器】

文章目录

  • 一、前言
  • 二、项目背景
  • 三、实现方案
    • 1. 谷歌 布隆过滤器
    • 2. Redis 布隆过滤器
  • 四、思路延伸
    • 1. 布隆过滤器的实现原理
    • 2. 布隆过滤器的一些扩展
    • 3. 布谷鸟过滤器
  • 五、参考内容


一、前言

本系列用来记录一些在实际项目中的小东西,并记录在过程中想到一些小东西,因为是随笔记录,所以内容不会过于详细。

二、项目背景

甲方要求,每一个客户的每一份订单里的每个商品如果第一次出现商品金额大于200w 时,需要提示信息。为了保证项目灵活性(,实际实现是通过数据库记录每一份商品出现的最高价格以及时间,同时在缓存中记录着每个客户每个商品当前最大的金额数量。这样如果亲爱的(善变的 )甲方哪一天要求金额变成为100w或者只比对近一年的单子的商品单价时都可以做及时变更,只需要将Redis 中的缓存清一下重新计算即可。

虽说按照上述方案实现了,但是其实当时想到了使用布隆过滤器的方案,当商品金额大于 200w 时将商品放入布隆过滤器中,下次判断如果布隆过滤器中不存在则说明当前商品没有出现过200w金额的订单。但实际上,这里是不适合使用布隆过滤器的,一是布隆过滤器会出现假阳性情况,二是无法处理上面提到的甲方可能的需求变更(事实证明,甲方真的变了 )。

所以本篇只是为了使用布隆过滤器实现玩一玩。


布隆过滤器,Bloom Filter是1970年由Bloom提出的,它是由一组哈希(Hash)函数和一个位阵列组成。布隆过滤器可以用于查询一个元素是否存在于一个集合当中,查询结果为以下二者之一:

  • 这个元素可能存在于这个集合当中。
  • 这个元素一定不存在于这个集合当中。

布隆过滤器的优点是空间效率和查询时间都比一般的算法要好的多,缺点是有一定的误识别率和删除困难。

布隆过滤器在实际中主要用来解决网页URL去重复,垃圾邮件检测,大集合中重复元素判断和缓存击穿等问题。


三、实现方案

1. 谷歌 布隆过滤器

谷歌在 guava 依赖包中实现了基于内存的布隆过滤器,如下:

   <dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId></dependency>

Demo 如下:

    public static void main(String[] args) {int bfSize = 10000;// 创建布隆过滤器,过滤器的元素类型为 Integer, 初始大小为 1000000,差错率为 0.01final BloomFilter<Integer> bloomFilter =BloomFilter.create(Funnels.integerFunnel(), bfSize, 0.01);// 初始化 布隆过滤器的元素for (int i = 0; i < bfSize; i++) {bloomFilter.put(i);}int count = 0;for (int i = 0; i < bfSize; i++) {if (!bloomFilter.mightContain(i)){count++;}}System.out.println("逃脱的数量 :" + count);count = 0;for (int i = bfSize; i < bfSize + 10000; i++) {if (bloomFilter.mightContain(i)) {count++;}}System.out.println("误伤的数量 :" + count);}

2. Redis 布隆过滤器

    public static void main(String[] args) {int bfSize = 10000;Config config = new Config();config.useSingleServer().setTimeout(10000).setDatabase(0).setAddress("redis://127.0.0.1:6379");RedissonClient redissonClient = Redisson.create(config);final RBloomFilter<Object> bloomFilter =redissonClient.getBloomFilter("default");bloomFilter.tryInit(bfSize, 0.01);for (int i = 0; i < bfSize; i++) {bloomFilter.add(i);}int count = 0;for (int i = 0; i < bfSize; i++) {if (!bloomFilter.contains(i)){count++;}}System.out.println("逃脱的数量 :" + count);count = 0;for (int i = bfSize; i < bfSize + bfSize; i++) {if (bloomFilter.contains(i)) {count++;}}System.out.println("误伤的数量 :" + count);}

四、思路延伸

1. 布隆过滤器的实现原理

布隆过滤器的实现其实很简单,下面直接参考其他人的总结(来源:布隆过滤器(Bloom Filter)详解、
布隆过滤器(BloomFilter)详解)


一个Bloom Filter是基于一个m位的位阵列(b1,…bm),这些位阵列的初始值为0。另外,还有一系列的hash函数(h1,…hk),这些hash函数的值域属于1~m。下图是一个bloom filter插入x,y,z并判断某个值w是否在该数据集的示意图:

在这里插入图片描述
上图中,m=18,k=3;

插入x时,三个hash函数分别得到蓝线对应的三个值,并将对应的位向量改为1,插入y,z时,类似的,分别将红线,紫线对应的位向量改为1。

查找时,当查找x时,三个hash值对应的位向量都为1,因此判断x在此数据集中。y,z也是如此。但是当查找w时,w有个hash值对应的位向量为0,因此可以判断不在此集合中。但是,假如w的最后那个hash值比上图中的大1,这是就会认为w在此集合中,而事实上,w可能不在此集合中,因此可能出现误报。显然的,插入数据越多,1的位数越多,误报的概率越大。


总结:

  1. 布隆过滤器由位图和n个hash函数构成。布隆过滤器的操作是一个key经过多个hash函数,然后对位图大小进行取余等到多个槽位并对应置为1。判断时只要有一个槽位为0就一定不存在该key。(需要注意的是多个Hash 函数并非时多种Hash算法,而是由一个Key处理结束后经过某种处理后再次进行Hash,位图的大小和 Hash 的次数跟初始化布隆过滤器的大小和指定的误差率有关)
  2. 布隆过滤器能确定一个key一定不存在,不能判断key一定存在,但可控假阳率确定存在。
  3. 布隆过滤器不支持删除操作,可以通过两个布隆过滤器解决(依然存在假阳率,但会低一些),添加放在第一个布隆过滤器,删除放在第二个布隆过滤器。即要判断key是否存在,首先检查第二个布隆过滤器是否删除过,如果删除过就往第一个布隆过滤器插入。
    布隆过滤器根据n和p算出m和k,hash函数个数是利用开放寻址法来计算的。

2. 布隆过滤器的一些扩展

以下思路参考 布隆过滤器扩容:布隆过滤器由于本身的不可逆性无法完成删除、扩容等操作,因此当 一个布隆过滤器容量到达上限后,创建一个更大的布隆过滤器,将新增的数据都存入新的布隆过滤器中,这样多个布隆过滤器组成过滤器链,判断Key 是否存在的时候需要判断所有的过滤器。此种方案还可以用于带有时效性的布隆过滤器,如需要判断最近30天内的,即可以创建30个布隆过滤器,每个过滤器存储一天的数据,当30天后将第一个过滤器清除重新使用。

3. 布谷鸟过滤器

布谷鸟过滤器可以说是一个增强版的布隆过滤器,可以删除元素,查询效率更高,空间利用率更高。如有需要详参: 布隆过滤器和布谷鸟过滤器详解

五、参考内容

https://blog.csdn.net/LT11hka/article/details/129063873
https://www.xjx100.cn/news/726331.html
https://zhuanlan.zhihu.com/p/616911933
https://www.cnblogs.com/shoshana-kong/p/14759488.html

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

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

相关文章

基于python+控制台的车辆信息管理系统

基于python控制台的车辆信息管理系统 一、系统介绍二、效果展示三、其他系统实现四、获取源码 一、系统介绍 打印功能菜单、添加车辆信息、删除车辆信息、修改车辆信息、显示车辆信息、退出系统&#xff0c;并且需要接收用户的输入&#xff0c;在根据输入内容调用相应函数实现…

Docker部署Grafana+Promethus监控Mysql和服务器

一、Grafana部署所需资源 Grafana 需要最少的系统资源&#xff1a; 建议的最小内存&#xff1a;512 MB建议的最低 CPU&#xff1a;1 官方文档&#xff1a;https://grafana.com/docs/grafana/latest/getting-started/build-first-dashboard/ 可以看到&#xff0c;我的这台服务…

有了Future为什么还要CompletableFuture?

文章目录 Future 接口理论知识复习Future 接口概述场景描述小结 Future 接口常用实现类 FutureTask 异步任务Future 的作用Futrue 编码测试优缺点分析优点缺点小结 面对一些复杂的任务对于简单的业务场景使用 Future 接口完全 OK回调通知创建异步任务多个任务前后依赖可以组合对…

DFS——连通性和搜索顺序

dfs的搜索是基于栈&#xff0c;但一般可以用用递归实现&#xff0c;实际上用的是系统栈。有内部搜索和外部搜索两种&#xff0c;内部搜索是在图的内部&#xff0c;内部搜索一般基于连通性&#xff0c;从一个点转移到另一个点&#xff0c;或者判断是否连通之类的问题&#xff0c…

[Python] opencv - 什么是直方图?如何绘制图像的直方图?

什么是直方图&#xff1f; 直方图是一种统计图&#xff0c;用于展示数据的分布情况。它将数据按照一定的区间或者组进行划分&#xff0c;然后计算在每个区间或组内的数据频数或频率&#xff08;即数据出现的次数或占比&#xff09;&#xff0c;然后用矩形或者柱形图的形式将这…

C++学习Day03之构造函数和析构函数

目录 一、程序及输出1.1 构造函数1.2 析构函数1.3 构造和析构必须要声明在全局作用域 二、分析与总结 一、程序及输出 1.1 构造函数 构造函数 没有返回值 不用写void 函数名 与 类名相同 可以有参数 &#xff0c;可以发生重载 构造函数 由编译器自动调用一次 无须手动调用 创建…

C语言——Q/编译和链接

目录 一、翻译环境和运⾏环境 二、翻译环境 1、预处理&#xff08;预编译&#xff09; 2、编译 2.2.1 词法分析&#xff1a; 2.2.2 语法分析 2.2.3 语义分析 3、汇编 4、链接 三、运行环境 一、翻译环境和运行环境 在ANSI C 的任何⼀种实现中&#xff0c;存在两个不…

CentOS7局域网内搭建本地yum源

CentOS7.6 局域网内搭建本地yum源 一、背景 客户机房服务器无法直连公网&#xff0c;远程通过堡垒机部署环境&#xff0c;因为机器比较多&#xff0c;最终选择通过安装自定义yum源进行部署。以下为自己部署yum源过程&#xff0c;以备后续使用。 二、准备yum源Packages 网上…

【刷题题解】最长回文子序列

给你一个字符串 s &#xff0c;找出其中最长的回文子序列&#xff0c;并返回该序列的长度。 子序列定义为&#xff1a;不改变剩余字符顺序的情况下&#xff0c;删除某些字符或者不删除任何字符形成的一个序列 这道题&#xff0c;一眼动态规划&#xff0c;但是即使动起来也规划…

python_蓝桥杯刷题记录_笔记_全AC代码_入门3

前言 记录我的解法以及笔记思路&#xff0c;谢谢观看。 题单目录 1.P2141 [NOIP2014 普及组] 珠心算测验 2.P1567 统计天数 3.P1055 [NOIP2008 普及组] ISBN 号码 4.P1200 [USACO1.1] 你的飞碟在这儿 Your Ride Is Here 5.P1308 [NOIP2011 普及组] 统计单词数 6.P1047 […

深度学习之循环神经网络进阶

这一讲我们学习如何实现一个循环神经网络的分类器&#xff1a; 我们要解决的问题是名字分类&#xff0c;我们根据名字找到其对应的国家。 上一讲我们介绍了循环神经网络。 我们在处理自然语言的时候我们通常是以上这种方式&#xff0c;我们在处理单词的时候&#xff0c;通常…

一文彻底搞懂MySQL基础:B树和B+树的区别(简洁版)

文章目录 1. 节点结构2. 插入和删除3. 查询4. 性能5. 适用场景6.关于 B树和 B树的常见问题6.1. B树和B树的区别是什么&#xff1f;6.2. 什么情况下应该使用 B树&#xff1f;6.3. 什么情况下应该使用 B树&#xff1f; B树和B树都是多路搜索树&#xff0c;它们都用于数据库索引中…

命令注入漏洞原理以及修复方法

漏洞名称 &#xff1a;命令注入 漏洞描述&#xff1a;Command Injection&#xff0c;即命令注入攻击&#xff0c;是指由于Web应用程序对用户提交的数据过滤 不严格&#xff0c;导致黑客可以通过构造特殊命令字符串的方式&#xff0c;将数据提交至Web应用程序中&#xff0c;并利…

一文讲明Jetpack中的图片组件

Jetpack Compose系列(5) - 图片组件 Jetpack Compose中的常用图片组件有两个&#xff1a;Icon和Image。从命名上就不难看出这两个组件在内容呈现上就是负责图形和图片相关。 需要说明的是&#xff0c;Compose获取资源方式有四种&#xff1a; 文本 -> stringResource(R.s…

比特币ETF广告战大爆发!

作者&#xff1a;秦晋 贝莱德主动发起广告攻势。 2月1日&#xff0c;据外媒Cryptoslate报道&#xff0c;贝莱德在提交给美国SEC的一份文件中显示&#xff0c;其提出一项在建筑物侧面投影比特币ETF广告计划。 据介绍&#xff0c;广告内容为&#xff1a;「IBIT」信号是一个以迈阿…

【Qt+MSVC2017_64bit +Cmake新建项目编译出错】

项目场景&#xff1a; 提示&#xff1a;这里简述项目相关背景&#xff1a; 项目新电脑环境配置 QtMSVC2017_64bit Cmake新建项目编译出错 问题描述 提示&#xff1a;这里描述项目中遇到的问题&#xff1a; QtMSVC2017_64bit Cmake新建项目编译出错 Running C:\Program Fil…

【数据分享】1米分辨率土地覆盖数据集SinoLC-1

数据链接 SinoLC-1: the first 1-meter resolution national-scale land-cover map of China created with the deep learning framework and open-access data (Update data: August, 2023) (zenodo.org)https://zenodo.org/records/8214467 数据分享 数据分享到了公众号&…

Android studio改代码运行不生效

Android studio改代码后运行不生效&#xff0c;尝试卸载apk后&#xff0c;运行能生效&#xff0c;后面尝试手动通过adb命令安装生成的apk能生效。 studio 版本 解决方案&#xff1a; 在File->Settings->Build, Execution, Deployment&#xff0c;找到Android Configura…

BFS——双向广搜+A—star

有时候从一个点能扩展出来的情况很多&#xff0c;这样几层之后搜索空间就很大了&#xff0c;我们采用从两端同时进行搜索的策略&#xff0c;压缩搜索空间。 190. 字串变换(190. 字串变换 - AcWing题库) 思路&#xff1a;这题因为变化规则很多&#xff0c;所以我们一层一层往外…

golang开源的可嵌入应用程序高性能的MQTT服务

golang开源的可嵌入应用程序高性能的MQTT服务 什么是MQTT&#xff1f; MQTT&#xff08;Message Queuing Telemetry Transport&#xff09;是一种轻量级的、开放的消息传输协议&#xff0c;设计用于在低带宽、高延迟或不可靠的网络环境中进行通信。MQTT最初由IBM开发&#xf…