Redis的中BitMap的应用

一、应用场景

通常用于构建布隆过滤器

业务场景需要频繁的查询数据库里的数据,但是这些数据又不一定都存在,一些大量无效的数据库请求,占用了数据库的链接。

本质上保护数据库,减少无用的请求。

解决:

1、把查询的数据key放入redis Set中,只有存在才会去查询,问题就是set过于大,检查是否存在也会变慢

2、当库中不存在该值时,依然创建一个value设置为空值,等过期时间后,自行删除。有可能上一秒库中不存在,下一秒有了,拿走依然是空值,也不行。

3、布隆过滤器

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

通常我们会遇到很多要判断一个元素是否在某个集合中的业务场景,一般想到的是将集合中所有元素保存起来,然后通过比较确定。链表、树、散列表(又叫哈希表,Hash table)等等数据结构都是这种思路。但是随着集合中元素的增加,我们需要的存储空间也会呈现线性增长,最终达到瓶颈。同时检索速度也越来越慢。上述三种结构的检索时间复杂度分别为:

  • O(n):链表
  • O(logn):树
  • O(1):哈希表

这个时候,布隆过滤器(Bloom Filter)就应运而生。

1.1. 原理

当一个元素被加入集合时,通过N个Hash函数将这个元素进行Hash,算出一个整数索引值,然后对数组长度进行取模运算,从而得到一个位置,每个Hash函数都会得到一个不同的位置,然后再把位数组中的几个位置点都置为1。

检索时,也会把哈希的几个位置算出来,然后看看位数组中对应的几个位置是否都为1,只要有一个位为0,那么就说明布隆过滤器里不存在这个元素。

但是,这几个位置都为1,并不能完全说明这个元素就一定存在其中。因为散列函数是会有碰撞的,不同的输入,可能在哈希后为同一个位置。即有可能这些位置为1是因为其他元素的存在,这就是布隆过滤器会出现误判的原因。

因此查询某个变量的时候我们只要看看这些点是不是都是 1 就可以大概率知道集合中有没有它了

  • 如果这些点有任何一个 0
  • 如果都是 1,则被查询变量很可能存在。

1.2 特性与优缺点

1. 不存在时一定不存在

一个元素如果判断结果为存在的时候元素不一定存在,但是判断结果为不存在的时候则一定不存在。

原因:布隆过滤器的误判是指多个输入经过哈希之后,在相同的bit位的值置1了,这样就无法判断究竟是哪个输入产生的,因此误判的根源在于相同的 bit 位被多次映射且置 1。

2. 只增不删

布隆过滤器可以添加元素,但是不能删除元素。因为删掉元素会导致误判率增加。

原因:上述原因中的情况,多个输入经过哈希之后,在相同的bit位的值置1了,也造成了布隆过滤器的删除问题。因为布隆过滤器的每一个 bit 并不是独占的,很有可能多个元素共享了某一位。如果我们直接删除这一位的话,会影响其他的元素。

如果需要删除一批元素,可以考虑重新初始化一个布隆过滤器,替换原来的。

3. 优点

  • 占用空间极小,插入和查询速度极快;
  • 布隆过滤器可以表示全集,其它任何数据结构都不能;

3. 缺点

  • 误算率随着元素的增加而增加;
  • 一般情况下无法删除元素;

1.3 应用场景

基于上述的功能,我们大致可以把布隆过滤器用于以下的场景之中:

1. 大数据判断是否存在来实现去重

这就可以实现出上述的去重功能,如果你的服务器内存足够大的话,那么使用 HashMap 可能是一个不错的解决方案,理论上时间复杂度可以达到 O(1) 的级别,但是当数据量起来之后,还是只能考虑布隆过滤器。

2. 判断用户是否访问过

判断用户是否阅读过某视频或文章,比如抖音或头条,当然会导致一定的误判,但不会让用户看到重复的内容。

3. 爬虫/邮箱等系统的过滤

平时不知道你有没有注意到有一些正常的邮件也会被放进垃圾邮件目录中,这就是使用布隆过滤器误判导致的。

4. 天然适合缓存穿透场景

布隆过滤器天然就能应对缓存穿透的场景。

首先,布隆过滤器的应用策略正好和缓存是相反的:

  • 缓存策略:缓存中不存在的,再去查db。
  • 布隆过滤器策略:过滤器中存在的,再去查缓存(db)。

然后,由于它的特性:一个元素如果判断结果为存在的时候元素不一定存在,但是判断结果为不存在的时候则一定不存在。

这表明它的误判率并不影响它的策略:

  • 当判断结果为存在时:不一定存在。带来的不好的结果,顶多就是多查一次缓存。
  • 当判断结果为不存在时:一定不存在。策略中判断不存在时,当前请求就会被拦截,这方面是没有误判的。

所以说,布隆过滤器天然适合缓存穿透的场景,它的误判率对与该场景没有丝毫影响。

1.4 实现

有很多布隆过滤器的实现,就如同之前将限流器的实现有 guava 和 redisson,布隆过滤器的实现也一样。

下面两种实现方式十分相似,都会初始化两个参数:

  • 初始容量:当实际元素的数量超过这个初始化容量时,误判率上升。设置的过大,会浪费存储空间,设置的过小,就会影响准确率,所以在使用之前一定要尽可能地精确估计好元素数量,还需要加上一定的冗余空间以避免实际元素可能会意外高出设置值很多。
  • 期望错误率:期望错误率越低,需要的空间就越大。错误率越小,需要的存储空间就越大,对于不需要过于精确的场景,错误率设置稍大一点也可以。

参考文献:https://segmentfault.com/a/1190000043505315

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

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

相关文章

(01)Unity使用在线AI大模型(使用百度千帆服务)

目录 一、概要 二、环境说明 三、申请百度千帆Key 四、使用千帆大模型 四、给大模型套壳 一、概要 在Unity中使用在线大模型分为两篇发布,此篇文档为在Python中使用千帆大模型,整体实现逻辑是:在Python中接入大模型—>发布为可传参的…

护眼台灯的功能作用有哪些?深挖台灯护眼是真的吗

随着现代生活方式的改变,孩子们面临着越来越多的视力挑战。在近视学生中,近10%为高度近视,且占比随年级升高而增长。幼儿园6岁儿童中有1.5%为高度近视,而高中阶段则达到了17.6%。为了守护孩子们的视力健康,在科技飞速发…

关键字 internal

在C#中,internal 关键字是一个访问修饰符,它用于限制类型或类型成员的访问性。当一个类型(类、结构体、接口、枚举等)或类型成员(字段、属性、方法、事件等)被声明为 internal 时,它只能在同一程…

无符号数和有符号数的转换

1、有符号数转换成无符号数 1.1 例一 首先,我们需要清楚 C语言中负数是以补码的形式进行存储的。 示例:负数-1, (此处,假设是8位二进制表示) 对应正数的原码:0000 0001;取反&…

通俗易懂多图透彻讲解二叉树的遍历--前序, 中序和后序

二叉树的遍历是一个数据结构中经常会遇到的知识点, 具体又分为前序, 中序和后序三种. 什么是树? 先来理解一下什么是树, 从一个我们相对熟悉的家谱树(Family Tree)说起吧. 家族的根是爷爷, 然后生了两个娃, 大伯和你爸爸. 继续往下, 有堂哥堂姐, 还有你以及你妹, 等等. 一个…

简化流程,强化协作——揭秘可道云TeamOS文档审批的实用魅力

在团队协作的过程中,文档审批是确保信息安全和流程规范的重要环节。然而,传统的文档审批流程往往繁琐且僵化,难以满足团队快速响应和灵活协作的需求。 可道云teamOS的文档审批功能,以其独特的灵活性和便捷性,为团队带…

吸血鬼之恋

吸血鬼之恋 AI制作,吸血鬼之恋,BGM选自《暮光之城》,希望大家喜欢。 欢迎你分享你的作品到我们的平台上:http://www.shxcj.com 或者 www.2img.ai 让更多的人看到你的才华。 创作不易,觉得不错的话,点个赞吧…

c++字符串实现join方法,使用模板

c字符串实现join方法&#xff0c;使用模板 主要记录下类成员函数&#xff0c;申明为模板函数的写法 注意定义迭代器时&#xff0c;前面需要加上typename关键字 typename std::vector<T>::iterator it;#pragma once #include <vector> #include <string>clas…

java——Junit单元测试

测试分类 黑盒测试&#xff1a;不输入代码&#xff0c;给输入值&#xff0c;看程序能够给出期望的值。 白盒测试&#xff1a;写代码&#xff0c;关注程序具体执行流程。 JUnit单元测试 一个测试框架&#xff0c;供java开发人员编写单元测试。 是程序员测试&#xff0c;即白…

PBT激光穿透率测量仪

在现代材料科学与工业制造领域&#xff0c;激光技术以其高精度、高效率和非接触性等特点&#xff0c;成为了不可或缺的测量与加工手段。其中&#xff0c;PBT&#xff08;聚对苯二甲酸丁二醇酯&#xff09;作为一种重要的热塑性工程塑料&#xff0c;因其优异的机械性能、耐热性和…

嵌入式全栈设计思路:STM32G4+ChibiOS+FreeRTOS+PID控制+PFC算法构建高效智能电源管理系统(附代码示例)

智能电源管理系统是一个基于STM32G4微控制器的高性能数字电源控制解决方案。本项目旨在设计一个功能全面、高效稳定的电源管理系统,可广泛应用于工业控制、新能源、通信设备等领域。 1.1 系统主要特点 高精度数字电源控制&#xff1a;利用STM32G4的高性能ADC和定时器,实现精确…

HTML5+CSS3小实例:纯CSS实现奥运五环

实例:纯CSS实现奥运五环 技术栈:HTML+CSS 效果: 源码: 【HTML】 <!DOCTYPE html> <html lang="zh-CN"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-sca…

Spring MVC中Restful风格引入

一&#xff0c;RESTful概述 在现代Web应用开发中&#xff0c;RESTful架构风格已成为一种标准实践&#xff0c;特别是在构建可扩展的Web服务时。Spring MVC提供了全面的支持来构建遵循REST原则的Web服务。我在此介绍如何在Spring MVC中实现RESTful风格的Web服务&#xff0c;并通…

【八大排序】java版(上)(冒泡、快排、堆排、选择排序)

文章目录 一、冒泡排序(重点)思路代码 二、快排(面试重点)思路代码 三、堆排序(面试重点)思路代码 四、选择排序思路代码 一、冒泡排序(重点) 思路 前后两两数据进行比较&#xff0c;小的数据往前走&#xff0c;大的数据往后走&#xff0c;每一轮结束之后&#xff0c;最大的数…

网页数据抓取:融合BeautifulSoup和Scrapy的高级爬虫技术

网页数据抓取&#xff1a;融合BeautifulSoup和Scrapy的高级爬虫技术 在当今的大数据时代&#xff0c;网络爬虫技术已经成为获取信息的重要手段之一。Python凭借其强大的库支持&#xff0c;成为了进行网页数据抓取的首选语言。在众多的爬虫库中&#xff0c;BeautifulSoup和Scrap…

在Android Jetpack Compose中实现夜间模式

在Android Jetpack Compose中实现夜间模式 随着用户对夜间模式需求的增加,Android开发者需要掌握如何在应用中实现这一功能。Jetpack Compose作为现代Android UI工具包,提供了简便且灵活的方式来实现夜间模式。本文将详细介绍如何在Jetpack Compose中实现夜间模式,包括配置…

Linux系统之玩转fortune命令

Linux系统之好玩的fortune命令 一、fortune命令介绍1.1 fortune简介1.2 fortune中英文 二、本地环境介绍2.1 本地环境规划2.2 本次实践介绍 三、检查本地环境3.1 检查本地操作系统版本3.2 检查系统内核版本 四、fortune英文版的使用4.1 安装fortune英文版4.2 命令帮助4.3 fortu…

69、Flink 的 DataStream Connector 之 Kafka 连接器详解

1.概述 Flink 提供了 Kafka 连接器使用精确一次&#xff08;Exactly-once&#xff09;的语义在 Kafka topic 中读取和写入数据。 目前还没有 Flink 1.19 可用的连接器。 2.Kafka Source a&#xff09;使用方法 Kafka Source 提供了构建类来创建 KafkaSource 的实例。以下代…

安卓手机刷入Magisk面具教程

手机如果想获取 Root 权限&#xff0c;刷入面具是必要的做法。本期文章将会教你如何刷入 Magisk 面具。 准备工作 Magisk: 关注微信公众号 heStudio Community回复 magisk 获取下载链接。第三方 Recovery&#xff08;官方 Recovery 能玩出什么花样&#xff1f;&#xff1f;&a…