【项目实践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.hqwc.cn/news/453545.html

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

相关文章

神经网络 | 基于 CNN 模型实现土壤湿度预测

Hi&#xff0c;大家好&#xff0c;我是半亩花海。在现代农业和环境监测中&#xff0c;了解土壤湿度的变化对于作物生长和水资源管理至关重要。通过深度学习技术&#xff0c;特别是卷积神经网络&#xff0c;我们可以利用过去的土壤湿度数据来预测未来的湿度趋势。本文将使用 Pad…

基于深度学习的SSVEP分类算法简介

基于深度学习的SSVEP分类算法简介 1、目标与范畴2、深度学习的算法介绍3、参考文献 1、目标与范畴 稳态视觉诱发电位&#xff08;SSVEP&#xff09;是指当受试者持续注视固定频率的闪光或翻转刺激时&#xff0c;在大脑枕-额叶区域诱发的与刺激频率相关的电生理信号。与P300、运…

从领域外到领域内:LLM在Text-to-SQL任务中的演进之路

导语 本文介绍了ODIS框架&#xff0c;这是一种新颖的Text-to-SQL方法&#xff0c;它结合了领域外示例和合成生成的领域内示例&#xff0c;以提升大型语言模型在In-context Learning中的性能。 标题&#xff1a;Selective Demonstrations for Cross-domain Text-to-SQL会议&am…

计算机网络第6章(应用层)

6.1、应用层概述 我们在浏览器的地址中输入某个网站的域名后&#xff0c;就可以访问该网站的内容&#xff0c;这个就是万维网WWW应用&#xff0c;其相关的应用层协议为超文本传送协议HTTP 用户在浏览器地址栏中输入的是“见名知意”的域名&#xff0c;而TCP/IP的网际层使用IP地…

ubuntu离线安装k8s

目录 一、前期准备 二、安装前配置 三、安装docker 四、安装cri-dockerd 五、部署k8s master节点 六、整合kubectl与cri-dockerd 七、网络等插件安装 八、常见问题及解决方法 一、前期准备 ①ubuntu系统 本地已安装ubuntu系统&#xff0c;lsb_release -a命令查看版本信…

论文阅读-CARD:一种针对复制元数据服务器集群的拥塞感知请求调度方案

论文名称&#xff1a;CARD: A Congestion-Aware Request Dispatching Scheme for Replicated Metadata Server Cluster 摘要 复制元数据服务器集群&#xff08;RMSC&#xff09;在分布式文件系统中非常高效&#xff0c;同时面对数据驱动的场景&#xff08;例如&#xff0c;大…

计算机网络——03网络核心

网络核心 网络核心 网络核心&#xff1a;路由器的网络状态基本问题&#xff1a;数据怎样通过网络进行传输 电路交换&#xff1a;为每个呼叫预留一条专有电路分组交换 将要传送的数据分成一个个单位&#xff1a;分组将分组从一个路由器传到相邻路由器&#xff08;hop&#xff…

JavaScript鼠标拖放(Drag and Drop)

&#x1f9d1;‍&#x1f393; 个人主页&#xff1a;《爱蹦跶的大A阿》 &#x1f525;当前正在更新专栏&#xff1a;《VUE》 、《JavaScript保姆级教程》、《krpano》、《krpano中文文档》 ​ ​ ✨ 前言 拖放是现代界面不可或缺的交互方式之一。本文将介绍如何用JavaScript…

Django前后端分离之后端实践

django-admin startproject djweb 生成djweb项目 django-admin startapp news 生成news应用 配置models文件 class NewInfo(models.Model):title models.CharField(max_length30)content models.TextField()b_date models.DateField()read models.IntegerFie…

代码随想录算法训练营第18天 | 513.找树左下角的值, 112. 路径总和,113. 路径总和 ||,106.从中序与后序遍历序列构造二叉树

二叉树理论基础&#xff1a; https://programmercarl.com/%E4%BA%8C%E5%8F%89%E6%A0%91%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80.html#%E7%AE%97%E6%B3%95%E5%85%AC%E5%BC%80%E8%AF%BE 513.找树左下角的值 题目链接&#xff1a;https://leetcode.cn/problems/find-bottom-left…

【算法与数据结构】647、516、LeetCode回文子串+最长回文子序列

文章目录 一、647、回文子串二、516、最长回文子序列三、完整代码 所有的LeetCode题解索引&#xff0c;可以看这篇文章——【算法和数据结构】LeetCode题解。 一、647、回文子串 思路分析&#xff1a;判断一个字符串是否为回文串那么必须确定回文串的所在区间&#xff0c;而一维…

Quartus IP 之mif与hex文件创建与使用

一、mif与hex概述 ROM IP的数据需要满足断电不丢失的要求&#xff0c;ROM IP数据的文件格式一般有三种文件格式&#xff1a;.mif、.hex、.coe&#xff0c;Xilinx与Intel Altera支持的ROM IP数据文件格式如下&#xff1a; Xilinx与Altera支持的ROM文件格式 Alterahex、mifAM&am…