【从零开始学习Redis | 第五篇】基于布隆过滤器解决Redis的穿透问题

前言:

         在如今的开发中,使用缓存中间件Redis已经成为一项很广泛的技术,Redis的高性能大大优化了我们的服务器性能,缓解了在高并发的情况下服务器的压力。它基于缓存的形式,在内存中保存数据,减少对磁盘的IO操作。然而尽管Redis有着很多的优点,但仍然有三朵乌云漂浮在Redis的上空:穿透击穿雪崩。而我们今天就把焦点聚焦于Redis的穿透问题。

目录

前言:

什么是Redis的穿透问题:

布隆过滤器:

基于Spring Boot实现布隆过滤器:

总结:


什么是Redis的穿透问题:

        Redis的穿透问题是指当应用程序查询一个不存在于缓存中的数据时,请求会直接穿透到后端存储系统(如数据库),导致缓存无法发挥作用,增加了后端负载并降低了系统性能。

穿透问题通常发生在以下情况下:

  1. 缓存击穿:某个热门数据在缓存过期后被大量并发请求访问,此时缓存失效,请求会直接访问后端存储系统,导致后端负载过高。
  2. 恶意攻击:有意发送不存在的数据请求,以触发系统的请求流量,浪费服务器资源。

为了解决Redis的穿透问题,可以采取以下措施:

  1. 布隆过滤器(Bloom Filter):使用布隆过滤器可以在缓存层面进行快速的数据存在性检查。布隆过滤器是一种概率型的数据结构,可以高效地判断一个元素是否可能存在于集合中,通过在缓存层进行预先判断,可以防止不存在的数据请求直接穿透到后端存储系统。

  2. 空值缓存:对于后端存储中不存在的数据,可以将其在缓存中设置为空值缓存,即存储一个特殊的空值标识。这样,在下一次查询该数据时,即使缓存中为空值标识,也可以避免请求直接穿透到后端存储系统。

  3. 互斥锁(Mutex):当缓存失效时,可以使用互斥锁来保护后续的查询操作。在获取到锁之后,再从后端存储系统加载数据到缓存中。其他并发请求会等待锁的释放,避免了多个请求同时穿透到后端存储系统。

  4. 热点数据预加载:对于热门数据,可以在系统启动时或低峰期通过批量查询或模拟请求将其提前加载到缓存中,避免缓存冷启动时的穿透问题。

  5. 异步更新缓存:当缓存失效后,可以异步地从后端存储系统加载数据到缓存中,而不是阻塞请求等待数据加载完成。这样可以减少请求的等待时间,提高系统的响应速度。

需要根据具体的业务场景和系统需求选择合适的解决方案,综合考虑性能、复杂度和数据准确性等因素,以确保Redis的穿透问题得到有效解决。

而我们今天就来详细介绍一下布隆过滤器

布隆过滤器:

我们先来简单说一下布隆表达器的思想:

既然 直接访问Redis 可能会存在Redis的穿透问题,那么我们就设置一个容器,这个容器里面记录了Redis中都有哪些数据,而我们以后所有的对于Redis的数据操作,都需要先在这个存储装置中查找我们想要操作的数据是否存在,如果存在,才可以进入Redis进行相关数据操作。

例如这个容器里面说明了Redis中有张三,李四,王五 这三个数据。那么如果我们要查询赵六这个数据,按照以前的思想,就是直接在Redis中查询赵六这个数据。但Redis中并不存在,这就造成了Redis的穿透问题。而为了解决这个问题,我们就使用这个容器,我们先在这个容器中查询是否有赵六这个数据,如果有再查询Redis,如果没有就直接Return false就可以了。

相信通过这么说,大家肯定已经理解了布隆过滤器的思想:布隆过滤器就是一个记录Redis中存在哪些数据的容器

那么现在问题的核心已经变为:我们如何高效的构建这个容器?

因为容器的目的只是为了证明Redis中存在这个数据,如果我们要通过存储这个元素的全部信息来证明Redis中存在这个数据,那简直是太扯淡了。

相信大家自己可以想出很多简化存储数据形式的方法,而我们直接来为大家介绍一下布隆过滤器是怎么构建自己的存储方式的:

整个布隆过滤器,我们可以认为是一个存储0和1的一维数组

而他是怎么通过这些0和1来说明一个元素是否存在于Redis中呢?

布隆过滤器内部有自己的哈希算法,可以对数据进行哈希映射,将其映射为一个一维数组的下标,那么我们就修改这个下标对应的值为1。当我们判断当前数据在Redis中是否存在的时候,我们就使用相同的哈希算法,再次得到一个下标值,检查这个下标对应的位置是否为1。就可以快速判断当前数据是否在Redis中存在了。

例如我们的Redis中有张三这个数据,我们把他存储到布隆过滤器中:

此时如果我们输入一个数据是李四,而Hash(李四)=4,我们一查询这个一维数组,下标为4的位置数值为0,这就说明了Redis中不存在李四这个数据,那么我们就直接返回,避免了Redis的穿透问题。

看到这里,相信有善于思考的同学已经发现了问题:万一两个数据经过Hash函数得到的下标值是一样的呢?

假设Redis中存在数据A,Hash(A)=3,而我们输入的数据B,经过Hash算法之后,也得到了下标3,那么岂不是造成错误了?

其实这种情况是存在的,也就是说随之数据量的增加,布隆过滤器是一定会出现错误判断的情况的。而为了减少这种错误,我们的思维也很简单:我多使用几个Hash函数不就好了 ,既然一次得到的下标会重复,我就对一个数据进行多次Hash,把得到的下标所对应的空间都标记为1。在判断数据的时候,我们就进行同样的操作,只有对应的下标空间都为1的时候,才证明该数据在Redis中存在。

例如我们在布隆过滤器中记录张三这个数据的时候,就多进行几次Hash,把得到的下标空间都标记为1。在进行判断数据是否存在的时候,就使用相同Hash函数进行相同次数的操作,判断得到的下标的空间是否为1

也就是说:布隆过滤器的误判率可以通过哈希函数的数量来进行调整。

而哈希函数越多,所映射出来的下标值就越多,下标值越多,一维数组的长度就越长,布隆过滤器的空间复杂度就越高。

基于Spring Boot实现布隆过滤器:

我们不手动实现布隆过滤器,而是直接使用Google Guava中提供的BloomFilter。

1.导入依赖:

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

2.创建并配置布隆过滤器:

import com.google.common.hash.BloomFilter;
import com.google.common.hash.Funnels;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class BloomFilterConfig {@Beanpublic BloomFilter<String> bloomFilter() {int expectedInsertions = 1000; // 期望的插入数量double fpp = 0.01; // 期望的误判率BloomFilter<String> bloomFilter = BloomFilter.create(Funnels.unencodedCharsFunnel(), expectedInsertions, fpp);return bloomFilter;}
}

3.使用布隆过滤器:

import com.google.common.hash.BloomFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service
public class MyService {@Autowiredprivate BloomFilter<String> bloomFilter;public boolean isElementExists(String element) {return bloomFilter.mightContain(element);}public void addElement(String element) {bloomFilter.put(element);}
}

 在这里我们再贴一下我自己的一个练手项目的使用:

跟上述的代码其实都差不多,主要在Service层中多添加一个方法,用于把Redis中的所有KEY 都放到布隆过滤器中:然后要设置在启动之后自动执行这个注入:

之后就可以在使用到Redis的方法中使用这个server层类:

这样,我们就在这个项目中实现了基于布隆过滤器来缓解Redis的穿透问题。

所以其实我们可以看到,布隆过滤器的使用难点主要在于:如何在真实业务海量数据的背景下。实现对布隆过滤器的初始化,因为我们要直接从数据库中拿数据,这种大规模的IO操作势必会给服务器来带很大的压力

而我由于能力限制,想不出太多的方法,也无法真实模拟海量数据背景,所以在这方面有所欠缺。

而我能够想出的方法有:

1.创建定时任务,分批存储数据到布隆过滤器中。

2.创建多个布隆切片,分批处理数据。

不知道在实际业务开发中,我们是怎么使用布隆过滤器的,如果有知道的大佬还请赐教。

总结:

布隆过滤器是一种高效的概率型数据结构,用于快速判断一个元素是否可能存在于一个集合中。通过位数组和多个哈希函数的组合,布隆过滤器可以实现高效的元素插入和查询操作,并且占用较少的内存空间。

总的来说,布隆过滤器具有以下几个关键优点:

  1. 高效的插入和查询性能:布隆过滤器的时间复杂度都是O(k),其中k为哈希函数的数量。这使得它能够在常数时间内快速地判断一个元素是否可能存在于集合中,对于大规模数据集的重复查询非常有效。
  2. 节省内存空间:布隆过滤器只需要存储每个元素的哈希值对应的位数组位置信息,而不需要存储元素本身。相比于其他数据结构,它能够节省大量的内存空间,尤其适用于处理大规模数据集。
  3. 可调控的误判率:通过调整哈希函数的数量和位数组的大小,可以控制布隆过滤器的误判率。根据实际需求和应用场景,可以选择合适的参数配置,以达到平衡误判率和内存消耗的目标。

然而,布隆过滤器也有一些缺点需要注意:

  1. 存在一定的误判率:由于哈希函数的计算结果有可能冲突,布隆过滤器会出现一定程度的误判。这意味着在判断一个元素存在时,可能会出现一定的虚警情况,需要进行进一步的确认。
  2. 无法删除元素:由于布隆过滤器的位数组中的位只能置为1而不能置为0,所以无法从布隆过滤器中删除已插入的元素。如果需要删除元素的功能,布隆过滤器可能不适用。

综上所述,布隆过滤器是一种高效、节省内存的数据结构,通过牺牲一定的精确性来提高查询效率。它在多个领域应用广泛,特别适用于大规模数据集的查询和去重场景。在使用布隆过滤器时,需要根据实际需求选择合适的参数配置,并注意误判率和删除元素的限制。

如果我的内容对你有帮助,请点赞,评论,收藏。创作不易,大家的支持就是我坚持下去的动力!

69e9169c980f43e0aad31ff9ada88a9c.png

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

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

相关文章

制造行业数字化运维破局之道

项目背景 某大型汽车制造集团&#xff0c;致力于通过数字化、智能化运营手段为用户提升提供高品质的汽车产品和服务。IT部门不仅为内外部持续提供服务&#xff0c;同时为业务运营与核心系统运行提供重要支撑。数字化运维作为数字化转型的核心基础&#xff0c;不但要保障数据安…

网络编程 - HTTP协议

目录 HTTP协议格式 一&#xff0c;请求格式 1.1 URL的基本格式 1.2 方法(method) 1.3 请求头header 二&#xff0c;响应格式 2.1 状态码 HTTP协议格式 HTTP协议与之前讲的TCP/IP协议不同&#xff0c;HTTP协议要分为两个部分——请求和响应&#xff0c;也就是一种"一…

尚硅谷Docker基础篇和Dockerfile超详细整合笔记

Docker基础篇DockerFile Docker&#xff1a;您要如何确保应用能够在这些环境中运行和通过质量检测&#xff1f;并且在部署过程中不出现令人头疼的版本、配置问题&#xff0c;也无需重新编写代码和进行故障修复&#xff1f;而这个就是使用容器。Docker解决了运行环境和配置问题…

linux 创建git项目并提交到gitee(保姆式教程)

01、git安装与初始化设置 mhzzjmhzzj-virtual-machine:~/work/skynetStudy$ apt install mhzzjmhzzj-virtual-machine:~/work/skynetStudy$ git config --global user.name "用户名" mhzzjmhzzj-virtual-machine:~/work/skynetStudy$ git config --global user.ema…

Java 8 新特性 Stream 的使用场景(不定期更新)

方便在写代码的过程中直接使用&#xff0c;好记性不如好文章&#xff0c;直接 CV 改了直接用。提高 办&#xff08;摸&#xff09;公&#xff08;鱼&#xff09;效&#xff08;时&#xff09;率&#xff08;间&#xff09;&#xff0c; 不然就直接问 GPT 也不是说不行。 只符合…

操作系统学习与思考

x86体系架构 x86是因特尔8086代芯片的CPU总线位数以及寄存器种类的规范&#xff0c;大部分操作系统都是以该规范作为基准来生产的 计算机组成 CPU&#xff0c;可以根据程序计数器进行取指令操作&#xff0c;并根据指令执行运算&#xff08;加、减、乘、除&#xff09;。运算所…

【hcie-cloud】【1】华为云Stack解决方案介绍、华为文档获取方式 【上】

文章目录 华为文档获取方式前言云计算发展背景国家政策、社会发展驱动数字经济开启新时代深化数字化转型提升效率&#xff0c;国家数字主权云进入落地阶段从Cloud-Based到Cloud-Native&#xff0c;两种模式长期并存适合政企智能升级的云华为云Stack&#xff0c;政企智能升级首选…

MySQL InnoDB数据存储结构

1. 数据库的存储结构&#xff1a;页 索引结构给我们提供了高效的索引方式&#xff0c;不过索引信息以及数据记录都是保存在文件上的&#xff0c;确切说是存储在页结构中。另一方面&#xff0c;索引是在存储引擎中实现的&#xff0c;MySQL服务器上的存储引擎负责对表中数据的读…

如何远程访问WAMP搭建的内网Web站点?

花生壳是由贝锐自主研发的域名解析工具&#xff0c;可帮助用户实现外网访问到局域网内搭建的各类办公系统。以发布网站服务为例&#xff0c;下面就给大家演示下如何通过花生壳实现外网访问WAMP站点。 1. 搭建WAMP站点 &#xff08;1&#xff09;首先&#xff0c;用户需在本地…

Photoshop图片处理

工具 Photoshop剪映 步骤 打开photoshop 工具主界面 2. 导入素材图片 或者直接将图片拖入主界面 3. 双击图层&#xff0c;将背景图改为可编辑图层 4. 使用多边形套索工具勾画需要搽除的区域 5. 希望删除的区域使用多边形套索工具勾画出来后&#xff0c; 按“del”键&a…

关于编程不得不说的事

这些年&#xff0c;互联网爆炸式的发展&#xff0c;促生了无数程序员&#xff0c;也促生了大量 IT培训机构。短短数年间&#xff0c;科班出生的程序员和培训机构出生的程序员呈指数增长。程序员的职业也不再是金饭碗。写了这么多代码&#xff0c;有些感触&#xff0c;所以写下来…

搭建WAMP网站教程(windows+apache+mysql+php)

之前为了学习网络安全&#xff0c;从搭建网站学起&#xff0c;对网站运行有个初步的了解。 今天翻到了之前的笔记&#xff0c;顺手发到csdn上了。 搭建网站步骤 一、Apache 安装Apache&#xff0c;下载Apache之后把Apache解压&#xff0c;此处解压到C:\目录下 2.然后要记得安…

【Java 进阶篇】Java Cookie共享:让数据穿越不同应用的时空隧道

在Web开发中&#xff0c;Cookie是一种常见的会话管理技术&#xff0c;用于存储和传递用户相关的信息。通常&#xff0c;每个Web应用都会在用户的浏览器中设置自己的Cookie&#xff0c;以便在用户与应用之间保持状态。然而&#xff0c;有时我们需要在不同的应用之间共享Cookie数…

Docker DeskTop安装与启动(Windows版本)

一、官网下载Docker安装包 Docker官网如下&#xff1a; Docker官网不同操作系统下载页面https://docs.docker.com/desktop/install/windows-install/ 二、安装Docker DeskTop 2.1 双击 Docker Installer.exe 以运行安装程序 2.2 安装操作 默认勾选&#xff0c;具体操作如下…

【安全】Java幂等性校验解决重复点击(6种实现方式)

目录 一、简介1.1 什么是幂等&#xff1f;1.2 为什么需要幂等性&#xff1f;1.3 接口超时&#xff0c;应该如何处理&#xff1f;1.4 幂等性对系统的影响 二、Restful API 接口的幂等性三、实现方式3.1 数据库层面&#xff0c;主键/唯一索引冲突3.2 数据库层面&#xff0c;乐观锁…

TensorFlow案例学习:使用 YAMNet 进行迁移学习,对音频进行识别

前言 上一篇文章 TensorFlow案例学习&#xff1a;简单的音频识别 我们简单学习了音频识别。这次我们继续学习如何使用成熟的语音分类模型来进行迁移学习 官方教程&#xff1a; 使用 YAMNet 进行迁移学习&#xff0c;用于环境声音分类 模型下载地址&#xff08;需要科学上网&…

Spring Boot 3 整合 xxl-job 实现分布式定时任务调度,结合 Docker 容器化部署(图文指南)

目录 前言初始化数据库Docker 部署 xxl-job下载镜像创建容器并运行访问调度中心 SpringBoot 整合 xxl-jobpom.xmlapplication.ymlXxlJobConfig.java执行器注册查看 定时任务测试添加测试任务配置定时任务测试结果 结语附录xxl-job 官方文档xxl-job 源码测试项目源码 前言 xxl-…

在ffmpeg中,如何把h264转换为rgb格式

在ffmpeg中&#xff0c;网络视频流h264为什么默认的转为YUV而不是其他格式 文章中介绍了&#xff0c;h264解码的时候是直接解码为yuv的&#xff0c;如果在使用的过程中 需要用到rgb的格式&#xff0c;我们该如何来转换这种格式呢&#xff1f; 在上面的文章中&#xff0c;我们已…