Redis中的缓存穿透,缓存击穿和缓存雪崩

news/2025/2/23 23:12:09/文章来源:https://www.cnblogs.com/chenshibao/p/18733041

概述

缓存击穿、缓存穿透、缓存雪崩这三个问题是Reids在实际项目中会经常遇到问题,同时,这三个问题也是面试的热点问题,下面,就本篇文章搞懂缓存穿透、缓存击穿、缓存雪崩三大问题的原因及解决方法。

Redis在项目中作为缓存中间件是如何工作的?如图所示
image

客户端发起一个查询请求的时候,首先去缓存中查询,如果数据在缓存中存在,则直接将缓存中的数据返回给客户端;如果数据在缓存中不存在,则继续查询数据库,如果数据在数据库中存在,则将该数据放入缓存中,并返回给客户端,如果数据在数据库中也不存在,则直接返回null给客户端。

1.缓存穿透

1.1 什么是缓存穿透

缓存穿透是指查询一个缓存中和数据库中都不存在的数据,导致每次查询这条数据都会透过缓存,直接查库,最后返回空。当用户使用这条不存在的数据疯狂发起查询请求的时候,对数据库造成的压力就非常大,甚至可能直接挂掉。这种情况的流程就变成下图这样了:

image

1.2 解决方案

解决缓存穿透的方法一般有两种,第一种是缓存空对象,第二种是使用布隆过滤器。

1.2.1 缓存空对象

第一种方法比较好理解,就是当数据库中查不到数据的时候,我缓存一个空对象,然后给这个空对象的缓存设置一个过期时间,这样下次再查询该数据的时候,就可以直接从缓存中拿到,从而达到了减小数据库压力的目的。
但这种解决方式有两个缺点:
(1)需要缓存层提供更多的内存空间来缓存这些空对象,当这种空对象很多的时候,就会浪费更多的内存;
(2)会导致缓存层和存储层的数据不一致,即使在缓存空对象时给它设置了一个很短的过期时间,那也会导致这一段时间内的数据不一致问题。

1.2.2 布隆过滤器

使用布隆过滤器,这是比较推荐的方法。所谓布隆过滤器,就是一种数据结构,它是由一个长度为m bit的位数组与n个hash函数组成的数据结构,位数组中每个元素的初始值都是0。在初始化布隆过滤器时,会先将所有key进行n次hash运算,这样就可以得到n个位置,然后将这n个位置上的元素改为1。这样,就相当于把所有的key保存到了布隆过滤器中了。

举个例子,比如我们一共有3个key,我们对这3个key分别进行3次hash运算,key1经过三次hash运算后的结果分别为2/6/10,那么就把布隆过滤器中下标为2/6/10的元素值更新为1,然后再分别对key2和key3做同样操作,结果如下图:

image

这样,当客户端查询时,也对查询的key做3次hash运算得到3个位置,然后看布隆过滤器中对应位置元素的值是否为1,如果所有对应位置元素的值都为1,就证明key在库中存在,则继续向下查询;如果3个位置中有任意一个位置的值不为1,那么就证明key在库中不存在,直接返回客户端空即可。如下图:

image

当客户端查询key4时,key4的3次hash运算中,有一个位置8的值为0,就说明key4在库中不存在,直接返回客户端空即可。

所以,布隆过滤器就相当于一个位于客户端与缓存层中间的拦截器一样,负责判断key是否在集合中存在。如下图:

image

布隆过滤器的好处就是解决了第一种缓存空值的不足,但布隆过滤器也存在缺陷,
首先,它有误判的可能,比如在上面客户端查询key4的图中,假如key4经过3次hash运算得到的位置分别是2/4/6,由于这3个位置的值都是1,所以,布隆过滤器就认为key4在库中存在,进而继续向下查询了。所以,布隆过滤器判断存在的key实际上可能是不存在的,但布隆过滤器判断不存在的key是一定不存在的。
它的第二个缺点就是删除元素比较难,比如现在要删除key2这个元素,那么需要将2/7/11三个位置的元素值改为0,但这样就会影响到key1和key3的判断。

2.缓存击穿

2.1 什么是缓存击穿

缓存击穿是指当缓存中某个热点数据过期了,在该热点数据重新载入缓存之前,有大量的查询请求穿过缓存,直接查询数据库。这种情况会导致数据库压力瞬间骤增,造成大量请求阻塞,甚至直接挂掉。

image

2.2 解决方案

解决缓存击穿的方法也有两种,第一种是设置key永不过期;第二种是使用分布式锁,保证同一时刻只能有一个查询请求重新加载热点数据到缓存中,这样,其他的线程只需等待该线程运行完毕,即可重新从Redis中获取数据。

2.2.1 热点Key值永不过期

第一种方式比较简单,在设置热点key的时候,不给key设置过期时间即可。不过还有另外一种方式也可以达到key不过期的目的,就是正常给key设置过期时间,不过在后台同时启一个定时任务去定时地更新这个缓存。
image

2.2.2 分布式锁并发更新

第二种方式使用了加锁的方式,锁的对象就是key,这样,当大量查询同一个key的请求并发进来时,只能有一个请求获取到锁,然后获取到锁的线程查询数据库,然后将结果放入到缓存中,然后释放锁,此时,其他处于锁等待的请求即可继续执行,由于此时缓存中已经有了数据,所以直接从缓存中获取到数据返回,并不会查询数据库。

image

3.缓存雪崩

3.1 什么是缓存雪崩

缓存雪崩是指当缓存中有大量的key在同一时刻过期,或者Redis直接宕机了,导致大量的查询请求全部到达数据库,造成数据库查询压力骤增,甚至直接挂掉。

image

3.2 解决方案

针对第一种大量key同时过期的情况,解决起来比较简单,只需要将每个key的过期时间打散即可,使它们的失效点尽可能均匀分布。
针对第二种redis发生故障的情况,部署redis时可以使用redis的几种高可用方案部署
除了上面两种解决方式,还可以使用其他策略,比如设置key永不过期、加分布式锁等。

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

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

相关文章

接口中的成员特点、类和接口之间的各种关系--java进阶day02

1.接口的成员特点1.接口没有构造方法接口没有构造方法,但是实现类中有构造方法,super()又该访问谁呢? 类实现接口只是认干爹,类本身还是会有亲爹Object,super()会访问Object类2.接口中成员变量只能定义常量 接口会自动将public static final加到成员变量中系统识别到有…

跨平台桌面应用开发:解锁 Electron 与 shadcn/ui 的潜力

本文部分内容使用豆包AI进行撰写和润色在当今数字化转型加速推进的时代,桌面应用程序作为各行各业的关键支撑,持续发挥着不可替代的作用。从医疗领域专业精准的影像诊断软件,助力医生快速洞察病情、制定治疗方案;到建筑设计行业复杂且功能强大的建模工具,将设计师脑海中的…

最新扣子(Coze)实战案例:提效10倍的室内装修设计AI工作流打造流程,让AI帮你做室内风格设计,打造COZE装修应用

最近星球群里有做装修设计行业的同学,想用扣子开发一款室内装修设计的应用,希望使用扣子工作流搭建,并建立扣子应用发到小程序。咨询斜杠君能否分享一下装修行业的扣子应用搭建方法。 ️‍这位同学的需求是: 让用户上传一张尚未装修的室内毛坯图片,选择装修风格后,立即为…

通过LM Studio部署DeepSeek

下载LM Studio 下载地址:https://lmstudio.ai/download 配置软件 汉化点击右下角齿轮设置为中文并使用代理调整模型路径点击文件夹图标 设置模型路径到空间大的磁盘查找并下载模型点击"放大镜"图标,跳出模型查找界面选择合适模型即可下载非限制模型搜索区输入"…

接口介绍以及定义和使用--java进阶day02

1.接口介绍 日常生活中有很多接口,比如手机数据线的接口和手机充电器的接口我们转换视角,站在设计者的角度思考接口,接口体现出规则,手机的接口大小和数据线的接口大小必须一致,各种接口的大小都要一致,都具有规则 所以,接口的本质就是设定规则代码当中又该如何设定规则…

软件开发与创新作业1-逆向-学生选课系统

来源:https://github.com/CurtainXT/Student_Management_System 运行环境:Visual Studio 2022 运行结果:主要代码:点击查看代码 #include"StuManage.h"/*-------------------------------学生工具组--------------------------------*/ // 查看备选课程信息 void…

JEXL 入门实战

JEXL 是一个在 Java 中实现动态表达式和脚本功能的库,本文主要介绍其基本概率和使用。 1、背景 在软件开发中,动态执行表达式是一项非常重要的能力。特别是在动态规则处理、配置文件解析以及灵活的业务逻辑实现等场景下,使用一种能够在运行时解析和执行表达式的工具显得尤为…

Octopus游戏服务器框架

Octopus一个跨平台的lua游戏服务器开发框架,该框架代码采用C++编写,开发者只需要调用SDK提供的接口函数和绑定对应的回调函数即可。框架在逻辑层表现为单线程的开发模式,使开发者更加易使用,易调试,易维护,易扩展,同时确保有快速的响应能力。 框架使用面向对象的开发模式…

【蓝牙小程序】实现简易table表格

Demo效果图 正文 由于需要开发小程序,前端又是自己弄,类似table的标签也没有,后来看到小程序文档中推荐使用flex布局,就把css中的flex布局学了一遍,效果还行,大家将就看一下table.wxml <view class="table"><view class="tr bg-w"><…

工程管理(二)

工程模板介绍 DevEco Studio支持多种品类的应用/元服务开发,预置丰富的工程模板,可以根据工程向导轻松创建适应于各类设备的工程,并自动生成对应的代码和资源模板。同时,DevEco Studio还提供了多种编程语言供开发者进行应用/元服务开发,包括ArkTS、JS和C/C++。工程模板支持…

工程管理(一)

APP包结构 在进行应用/元服务开发前,开发者应该掌握应用/元服务的逻辑结构。 应用/元服务发布形态为APP Pack(Application Package),它是由一个或多个HAP(Harmony Ability Package)包以及描述APP Pack属性的pack.info文件组成。 一个HAP在工程目录中对应一个Module,它是…

包和抽象类介绍--java进阶day02

1.package包导包第二点需要注意 a包和b包都存有Student类,c包存有测试类,我们在c中创建Student对象,系统会询问你要哪个包的Student类,并自动帮你导包.在导完a包的学生类后,想要再次导入b包的学生类就不能再像之前那样导了全类名导包 通过带包名将b包重复的学生类导入2.抽…