【Redis】Redis中的布隆过滤器

【Redis】Redis中的布隆过滤器

前言

在实际开发中,会遇到很多要判断一个元素是否在某个集合中的业务场景,类似于垃圾邮件的识别,恶意IP地址的访问,缓存穿透等情况。类似于缓存穿透这种情况,有许多的解决方法,如:Redis存储Null值等,而对于垃圾邮件的识别,恶意IP地址的访问,我们也可以直接用 HashMap 去存储恶意IP地址以及垃圾邮件,然后每次访问时去检索一下对应集合中是否有相同数据。这种思路对于数据量小的项目来说是没有问题的,但是对于大数据量的项目,如:垃圾邮件出现有几十万,恶意IP地址出现有上百万,那么这些大量的数据就会占据大量的空间,这个时候就可以考虑一下布隆过滤器了。

布隆过滤器是什么?

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

在这里插入图片描述

可以把布隆过滤器理解为一个不怎么精确的 set 结构,当你使用它的 contains方法判断某个对象是否存在时,它可能会误判。但是布隆过滤器也不是特别不精确,只要参数设置得合理,它的精确度也可以控制得相对足够精确,只会有小小的误判概率。

当布隆过滤器说某个值存在时,这个值可能不存在;当它说某个值不存在时那就肯定不存在。打个比方,当它说不认识你时,肯定就是真的不认识;而当它说认识你时,却有可能根本没见过你,只是因为你的脸跟它认识的某人的脸比较相似(某些熟脸的系数组合),所以误判以前认识你。

一句话总结:由一个初始值为零的bit数组和多个哈希函数构成,用来快速判断集合中是否存在某个元素。

使用bit数组的目的就是减少内存的占用,数组不保存数据信息,只是在内存中存储一个是否存在的表示0或1

布隆过滤器的优缺点:

优点:

​ 高效插入和查询,内存占用空间少

缺点:

  • 存在误判,不能精确过滤
  • 不能删除元素

布隆过滤器的使用场景

黑白名单校验、识别垃圾邮件

发现存在黑名单中的,就执行特定操作。比如:识别垃圾邮件,只要是邮箱在黑名单中的邮件,就识别为垃圾邮件。假设黑名单的数量是数以亿计的,存放起来就是非常耗费存储空间的,布隆过滤器则是一个较好的解决方案。把所有黑名单都放在布隆过滤器中,在收到邮件时,判断邮件地址是否在布隆过滤器中即可。

解决缓存穿透的问题

把已存在数据的key存在布隆过滤器中,相当于Redis前面挡着一个布隆过滤器。当有新的请求时,先到布隆过滤器中查询是否存在:如果布隆过滤器中不存在该条数据则直接返回;如果布隆过滤器中已存在,才去查询缓存Redis,如果Redis里没查询到则再查询MySQL数据库

布隆过滤器的原理

每个布隆过滤器对应到 Redis 的数据结构里面就是一个大型的位数组和几个不-样的无偏 hash函数,如下图中的F、G、H就是这样的hash函数。所谓无偏就是能够把元素的 hash 值算得比较均匀,让元素被 hash映射到位数组中的位置比较随机。

在这里插入图片描述

向布隆过滤器中添加 key 时,会使用多个 hash 函数对 key 进行 hash,算得一个整数索引值,然后对位数组长度进行取模运算得到一个位置,每个 hash 函数都会算得一个不同的位置。再把位数组的这几个位置都置为 1,就完成了 add 操作。

向布隆过滤器询问 key 是否存在时,跟add 一样,也会把 hash 的几个位置都算出来,**看看位数组中这几个位置是否都为 1,只要有一个位为 0,那么说明布隆过滤器中这个 key 不存在。如果这几个位置都是 1,并不能说明这个 key 就一定存在,只是极有可能存在,因为这些位被置为 1 可能是因为其他的 key 存在所致。**如果这个位数组比较稀疏,判断正确的概率就会很大,如果这个位数组比较拥挤,判断正确的概率就会降低。具体的概率计算公式比较复杂,感兴趣可以阅读相关的更深入研究的资料,不过非常烧脑,不建议读者细看。

参考博客:Redis系列–布隆过滤器(Bloom Filter)_redistemplate 布隆过滤器_幼儿园里的山大王的博客-CSDN博客

基于Redisson的布隆过滤器使用实例

1.引入Redisson依赖

<!--原生-->
<dependency><groupId>org.redisson</groupId><artifactId>redisson</artifactId><version>3.13.4</version>
</dependency><!--或者另一种Spring集成starter-->
<dependency><groupId>org.redisson</groupId><artifactId>redisson-spring-boot-starter</artifactId><version>3.13.6</version>
</dependency>

2.配置Redisson

@Configuration
public class RedissionConfig {@Value("${spring.redis.host}")private String redisHost;@Value("${spring.redis.password}")private String password;private int port = 6379;@Beanpublic RedissonClient getRedisson() {Config config = new Config();config.useSingleServer().setAddress("redis://" + redisHost + ":" + port).setPassword(password);config.setCodec(new JsonJacksonCodec());return Redisson.create(config);}
}

3.配置布隆过滤器

@Configuration
public class BloomFilterConfig {@Autowiredprivate RedissonClient redissonClient;/*** 创建订单号布隆过滤器* @return*/@Beanpublic RBloomFilter<Long> orderBloomFilter() {//过滤器名称String filterName = "orderBloomFilter";// 预期插入数量long expectedInsertions = 10000L;// 错误比率double falseProbability = 0.01;RBloomFilter<Long> bloomFilter = redissonClient.getBloomFilter(filterName);bloomFilter.tryInit(expectedInsertions, falseProbability);return bloomFilter;}
}

4.创建订单表

CREATE TABLE `tb_order` (`id` bigint NOT NULL AUTO_INCREMENT COMMENT '订单Id',`order_desc` varchar(50) NOT NULL COMMENT '订单描述',`user_id` bigint NOT NULL COMMENT '用户Id',`product_id` bigint NOT NULL COMMENT '商品Id',`product_num` int NOT NULL COMMENT '商品数量',`total_account` decimal(10,2) NOT NULL COMMENT '订单金额',`create_time` datetime NOT NULL COMMENT '创建时间',PRIMARY KEY (`id`),KEY `ik_user_id` (`user_id`)
) ENGINE=InnoDB AUTO_INCREMENT=51 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

5.编写业务处理代码

@Slf4j
@Service
public class OrderServiceImpl implements OrderService {@Resourceprivate RBloomFilter<Long> orderBloomFilter;@Resourceprivate TbOrderMapper  tbOrderMapper;@Resourceprivate RedisTemplate<String,Object> redisTemplate;@Overridepublic void createOrder(TbOrder tbOrder) {//1、创建订单tbOrderMapper.insert(tbOrder);//2、订单id保存到布隆过滤器log.info("布隆过滤器中添加订单号:{}",tbOrder.getId());orderBloomFilter.add(tbOrder.getId());}@Overridepublic TbOrder get(Long orderId) {TbOrder tbOrder = null;//1、根据布隆过滤器判断订单号是否存在if(orderBloomFilter.contains(orderId)){log.info("布隆过滤器判断订单号{}存在",orderId);String key = "order:"+orderId;//2、先查询缓存Object object = redisTemplate.opsForValue().get(key);if(object != null){log.info("命中缓存");tbOrder =  (TbOrder)object;}else{//3、缓存不存在则查询数据库log.info("未命中缓存,查询数据库");tbOrder = tbOrderMapper.selectById(orderId);redisTemplate.opsForValue().set(key,tbOrder);}}else{log.info("判定订单号{}不存在,不进行查询",orderId);}return tbOrder;}
}

6.单元测试

@Test
public void testCreateOrder() {for (int i = 0; i < 50; i++) {TbOrder tbOrder = new TbOrder();tbOrder.setOrderDesc("测试订单"+(i+1));tbOrder.setUserId(1958L);tbOrder.setProductId(102589L);tbOrder.setProductNum(5);tbOrder.setTotalAccount(new BigDecimal("300"));tbOrder.setCreateTime(new Date());orderService.createOrder(tbOrder);}}
@Test
public void testGetOrder() {TbOrder  tbOrder = orderService.get(25L);log.info("查询结果:{}", tbOrder.toString());
}

总结

布隆过滤器的原理其实非常简单,就是bitmap + 多重hash,主要优势就是利用非常小的空间就可以实现在大规模数据下快速判断某一对象是否存在,缺点是存在误判的可能,但不会漏判,也就是存在的对象一定会判断为存在,而不存在的对象会有较低的概率为误判为存在,且不支持对象的删除,因为会增加误判的概率。最典型的使用是解决缓存穿透的问题。

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

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

相关文章

基于MATLAB开发AUTOSAR软件应用层Code mapping专题-part 2 Inport和Outports 标签页介绍

上篇我们介绍了Function页的内容,这篇我们介绍Inports和Outports页的内容,这里我们再次强调一个概念,code mapping是以simulink的角度去看的,就是先要在模型中建立simulink模块,在code mapping里映射他要对应的autosar的元素,之后生成代码时的c语言的名字是以Autosar的元…

永久设置pip指定国内镜像源(windows内)

1.首先列出国内四个镜像源网站&#xff1a; 一、清华源 https://pypi.tuna.tsinghua.edu.cn/simple/ 二、阿里源 https://mirrors.aliyun.com/pypi/simple 三、中科大源 https://pypi.mirrors.ustc.edu.cn/simple/ 四、豆瓣源 http://pypi.douban.com/simple/ 2.一般下载所需要…

colab释放GPU显存

不用其他博客说的安装包&#xff0c;然后查看进程&#xff0c;kill&#xff0c;本文介绍一种简单的方法。 点击运行过代码的ipynb页面右上角的下三角&#xff0c;然后点击展开菜单栏中的View resources 随后会展开一个侧边栏&#xff0c;点击 manage sessions 3. 在页面中央会…

Docker+Jmeter+InfluxDB+Grafana 搭建性能监控平台

当今互联网发展迅速&#xff0c;应用程序的性能监控显得越来越重要。DockerJmeterInfluxDBGrafana 是一种常用的性能监控平台&#xff0c;可以帮助开发者快速搭建一套可靠的监控体系。在本文中&#xff0c;我们将介绍如何使用这些工具搭建性能监控平台&#xff0c;以便开发人员…

每天一道leetcode:127. 单词接龙(图论困难建图广度优先遍历)

今日份题目&#xff1a; 字典 wordList 中从单词 beginWord 和 endWord 的 转换序列 是一个按下述规格形成的序列 beginWord -> s1 -> s2 -> ... -> sk&#xff1a; 每一对相邻的单词只差一个字母。 对于 1 < i < k 时&#xff0c;每个 si 都在 wordList 中…

【Apollo】阿波罗自动驾驶技术:引领汽车行业革新

前言 Apollo (阿波罗)是一个开放的、完整的、安全的平台&#xff0c;将帮助汽车行业及自动驾驶领域的合作伙伴结合车辆和硬件系统&#xff0c;快速搭建一套属于自己的自动驾驶系统。 开放能力、共享资源、加速创新、持续共赢是 Apollo 开放平台的口号。百度把自己所拥有的强大、…

npm install ffi各种失败,换命令npm i ffi-napi成功

网上各种帖子安装ffi&#xff0c;基本上到了windows build tools这里会卡住。 使用命令npm install --global --production windows-build-tools 安装报错信息如下&#xff1a; PS E:\codes\nodejsPath\tcpTest> npm install --global --production windows-build-tools …

成为创作者的第512天——创作纪念日

​ &#x1f4da;文章目录 &#x1f4e8;官方致信 &#x1f3af;我的第一篇文章 &#x1f9e9;机缘 &#x1f9e9;收获 &#x1f9e9;成就 &#x1f9e9;憧憬与目标 &#x1f4e8;官方致信 ​ &#x1f3af;我的第一篇文章 2022 年 03 月 26 日&#xff0c;那一天我在C…

阿里云ECS服务器企业级和共享型介绍_企业级常见问题解答FAQ

阿里云企业级服务器是什么&#xff1f;企业级和共享型有什么区别&#xff1f;企业级服务器具有独享且稳定的计算、存储、网络资源&#xff0c;如ECS计算型c6、通用型g8等都是企业级实例&#xff0c;阿里云百科分享什么是企业级云服务器、企业级实例的优势、企业级和共享型云服务…

电脑远程接入软件可以进行文件传输吗?快解析内网穿透

电脑远程接入软件的出现&#xff0c;让我们可以在两台电脑之间进行交互和操作。但是&#xff0c;很多人对于这些软件能否进行文件传输还存在一些疑问。下面的文章将解答这个问题。 1.电脑远程接入软件可以进行文件传输。传统上&#xff0c;我们可能会通过传输线或者移动存储设…

R语言实现非等比例风险生存资料分析(1)

#非等比例风险的生存资料分析 ###1 生成模拟数据### library(flexsurv) set.seed(123) # 生成样本数量 n <- 100 # 生成时间数据 time <- sample(1:1000,n,replaceF) # 调整shape和scale参数以控制生存曲线形状 # 生成事件数据&#xff08;假设按比例风险模型&#xff0…

mqtt开关实现

这个项目的主要需求其实并不复杂&#xff0c;只是需要让用户可以在小程序上控制预约后的自习室座位的灯和柜子等的开关。这里的关键是需要通过一个网络应用来转发用户对智能硬件的控制请求。 物联网应用的主要几个难点及对应的思路如下&#xff1a; 通信数据量小、通信环境不…

Qt下拉菜单

1&#xff0c;QComboBox 2&#xff0c;setMenu()---设置下拉菜单 AI对话未来丨智能写作对话: setMenu()是QWidget类的一个成员函数&#xff0c;在Qt中用于将一个菜单作为一个控件的下拉菜单设置。具体来说&#xff0c;它会把相应的菜单对象与该控件关联&#xff0c;并在控件上…

阿里云无影云电脑/云桌面收费价格表_使用申请方法

阿里云无影云电脑配置具体收费价格表&#xff0c;4核8G企业办公型云电脑可以免费使用3个月&#xff0c;无影云电脑地域不同价格不同&#xff0c;无影云电脑费用是由云桌面配置、云盘、互联网访问带宽、AD Connector 、桌面组共用桌面session 等费用组成&#xff0c;阿里云百科分…

Django的模型

定义模型 from django.db import models class User(models.Model):# 类属性是表示表的字段username models.CharField(max_length50,uniqueTrue)password models.CharField(max_length200)create_time models.DateTimeField(auto_now_addTrue) # auto_now_add新增数据时间…

计算机竞赛 垃圾邮件(短信)分类算法实现 机器学习 深度学习

文章目录 0 前言2 垃圾短信/邮件 分类算法 原理2.1 常用的分类器 - 贝叶斯分类器 3 数据集介绍4 数据预处理5 特征提取6 训练分类器7 综合测试结果8 其他模型方法9 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 垃圾邮件(短信)分类算…

NPM 创建和管理组织

目录 1、创建一个组织 2、将用户帐户转换为组织 3、组织中开启双因素身份验证 3.1 关于组织的双因素身份验证 3.2 先决条件 3.3 在您的组织中要求双因素身份验证 3.4 帮助已删除的成员和外部协作者重新加入您的组织 4、重命名组织 5、删除组织 1、创建一个组织 任何n…

ChatGPT和Claude的能力全测评

创造性思维/语言 提示&#xff1a;“写一首 4 行诗&#xff0c;每行只有 3 个词&#xff0c;描写重庆” ChatGPT写诗&#x1f447; Claude写诗&#x1f447; 仁者见仁&#xff0c;您怎么看谁更强&#xff1f; 提示&#xff1a; "如果你随机选择这个问题的答案&#xff0c;…

“维度削减+逻辑回归”:如何使用PCA大幅提升乳腺癌的预测成功率?

一、引言 乳腺癌是女性中最常见的恶性肿瘤之一&#xff0c;也影响着全球范围内许多人们的健康。据世界卫生组织&#xff08;WHO&#xff09;的数据&#xff0c;乳腺癌是全球癌症发病率和死亡率最高的肿瘤之一&#xff0c;其对个体和社会的危害不可忽视。因此&#xff0c;早期乳…

leetcode:字符串相乘(两种方法)

题目&#xff1a; 给定两个以字符串形式表示的非负整数 num1 和 num2&#xff0c;返回 num1 和 num2 的乘积&#xff0c;它们的乘积也表示为字符串形式。 注意&#xff1a;不能使用任何内置的 BigInteger 库或直接将输入转换为整数。 示例 1: 输入: num1 "2", nu…