当前位置: 首页 > news >正文

Redis:原理速成+项目实战——Redis实战4(解决Redis缓存穿透、雪崩、击穿)

👨‍🎓作者简介:一位大四、研0学生,正在努力准备大四暑假的实习
🌌上期文章:Redis:原理+项目实战——Redis实战3(Redis缓存最佳实践(问题解析+高级实现))
📚订阅专栏:Redis速成
希望文章对你们有所帮助

上次已经讲解了企业级用Redis进行缓存更新的基础用法,并且进行了最佳实践。但是其实Redis在使用的过程中还是会出现各种问题:缓存穿透、缓存雪崩、缓存击穿。
其中缓存穿透比较好解决,在这里会进行解决。
缓存雪崩提一下解决方案就好了,真正的解决在Redis学到比较高级的时候,或者说在肝微服务架构的时候去具体解决。
缓存击穿的解决方法在这里也提一下,具体编码的解决在下一节进行

缓存穿透、雪崩、击穿及解决方案

  • 缓存穿透
    • 缓存穿透解决思路
    • 编码解决商铺查询的缓存穿透问题
  • 缓存雪崩及解决思路
  • 缓存击穿及解决思路
    • 解决思路——互斥锁
    • 解决思路——逻辑过期
    • 解决思路总结

缓存穿透

缓存穿透是指客户端请求的数据在缓存和数据库中都不存在,这样缓存永远不会生效,这些请求都会打到数据库。过程即:
(1)客户端访问Redis,未命中
(2)接着访问数据库,未命中
这样的话,如果有人恶意多线程地访问不存在的内容,可能就把我们的系统弄垮了。

缓存穿透解决思路

常见的解决方案如下:

1、缓存空对象:
(1)客户端请求Redis,未命中
(2)接着访问数据库,未命中
(3)数据库将空值null缓存到Redis里
这样如果继续访问的话,就会访问Redis了,不会一直去对数据库造成攻击,尽管访问Redis以后返回的内容是NULL。
优点:实现简单,维护方便
缺点:额外内存消耗(每次进行不同的访问,都创建null,不过设置TTL可以解决);可能造成短期的不一致(设置为NULL之后,数据库真的新增了这个数据,不过设置TTL可以有效缓解这种情况的出现概率)

2、布隆过滤:
这其实是一种算法,它在客户端与Redis交互之间加了一个布隆过滤器
(1)用户请求布隆过滤器,不存在就直接拒绝
(2)存在的话就放行,让客户端去访问Redis,有就返回,没有就访问数据库
布隆过滤器存储的一系列的二进制位,这种二进制数是先对数据库数据进行某种哈希运算以后再转成二进制存储到布隆过滤器的,具体原理可以自行查询,这种算法实现方式决定了过滤器存在概率性:

如果过滤器返回不存在,那就是不存在;如果返回存在,那就不一定了。

优点:内存占用较少,没有多余key
缺点:实现复杂(不过Redis里面存在,可以简化开发);存在误判可能。

因为布隆过滤器存在误判,所以我们的开发过程中,会选择缓存空对象的方式来解决缓存穿透。

编码解决商铺查询的缓存穿透问题

1、我们需要在之前业务流程环节中增加缓存空对象的环节,即可解决,也就是根据id查询数据库的时候,判断商铺不存在之后,不再直接结束,而是将空值写入Redis。
2、那么我们之后的查询,可以在缓存中查询出null值,因此我们的查询就需要对查询出来的值进行判断,不是空值的话才能返回商铺信息到前端。
代码如下:

    @Overridepublic Result queryById(Long id) {String key = CACHE_SHOP_KEY + id;//从Redis中查询商铺缓存,存储对象可以用String或者Hash,这里用StringString shopJson = stringRedisTemplate.opsForValue().get(key);//判断是否存在if (StrUtil.isNotBlank(shopJson)) {//存在,直接返回Shop shop = JSONUtil.toBean(shopJson, Shop.class);return Result.ok(shop);}//判断命中的是否是nullif (shopJson != null){//返回错误信息return Result.fail("点评信息不存在");}//不存在,根据id查询数据库Shop shop = getById(id);//不存在,返回错误if (shop == null){//存一个null到Redis中//这种没用的信息,TTL没必要设置太长了,这里我设置成了2minstringRedisTemplate.opsForValue().set(key, "", CACHE_NULL_TTL, TimeUnit.MINUTES);return Result.fail("店铺不存在");}//存在,写入RedisstringRedisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(shop), CACHE_SHOP_TTL, TimeUnit.MINUTES);//返回return Result.ok(shop);}

当我们网页的id设置成0去查询店铺:
在这里插入图片描述
打开Redis,0号的商铺确实存入了Redis,且值为空:
在这里插入图片描述
到此,我们成功用代码解决了这个问题。

缓存雪崩及解决思路

缓存雪崩是指同一时段有大量的缓存key失效,或者Redis服务宕机,导致大量请求到达数据库,带来的巨大压力。
正常情况下,大量请求会到达Redis,少数请求到达数据库。而Redis一旦宕机,或者Redis中的大量key都因为TTL到期而失效了,这时候的很多请求都会指向数据库。
针对这个问题,我们可以提出一些解决方案:
1、给不同的key的TTL添加随机值,避免大量的key在同一个小时段内失效
2、利用Redis集群提高服务的可用性(Redis哨兵机制可以实现服务的监控,发现宕机的主Redis,就可以立刻将从Redis替代上去),这个内容相对比较高级,在之后讲。
3、给缓存业务添加降级限流策略(如果整个集群的Redis全部都宕机了,我们可以提前做容错处理,当这些Redis都失效的时候,我们要及时的拒绝请求,防止大量请求到达数据库)
4、给业务添加多级缓存

缓存击穿及解决思路

缓存击穿也叫作热点key问题,就是一个被高并发访问并且缓存重建业务较复杂的key突然失效了,无数的请求访问会在瞬间给数据库带来巨大的冲击。

我们可以这么理解,网站中有一些内容是非常的重要的,很可能在同一时段被多个用户给同时访问,也就是高并发访问,而这个被高并发访问的key失效了,这时候访问就会到达数据库,大量请求到达数据库是很危险的,很容易造成缓存雪崩。
即便数据库比较坚强,也有可能用户进行访问的内容是很复杂的,可能涉及到了多表查询,也可能其转换到Redis中进行存储的时候需要进行一系列的业务。当缓存重建业务复杂的时候,如此大的请求在那一瞬间给数据库带来的冲击是非常巨大的。

缓存击穿问题,有两种比较主流的解决方法:
1、互斥锁
2、逻辑过期

解决思路——互斥锁

互斥锁还是比较好理解的:
1、当第一个线程未命中缓存的时候,获取互斥锁,直到这个线程查询数据库完,并且重建了缓存数据并存入Redis,才能释放互斥锁;
2、后面的线程在缓存数据存入Redis的过程中,同样会发生查询Redis未命中的情况,那么这些线程无法获得互斥锁,只能进行休眠,休眠一段时间后再重试,直到锁被解开(Redis中已经有数据了)。
在这里插入图片描述
学过操作系统的同学应该知道,这个问题可能会出现的问题就是,线程之间很可能会出现相互等待的情况,当然操作系统中针对这些情况都还是有对应的一些解决方法的。

解决思路——逻辑过期

缓存击穿会出现的原因,其实无非就是TTL到期,Redis失效了,因此我们可以不给其设置TTL。但是我们该如何知道key过期了呢?我们要给这个key设置一个逻辑过期,类似:

KEYVALUE
wxj:user:1{name:“Jack”, age:21, expire:151467}

这里的expire不是TTL,而是我们添加到Redis之前设定的,用代码逻辑来进行维护。
那么这个key一旦存储到了Redis里面,没有任何干预的情况下是永不过期的。
也就是说有一个线程在查询缓存的时候,代码逻辑里发现逻辑时间过期了,我们也直接把旧数据返还给客户端,毕竟已经是高并发,一时的旧数据在很多时候也能接受,在我看来这是一种牺牲策略,客户端无须等待新数据到来,当然了,旧数据迟早要进行修改,但数据的更新操作完全可以交给其他线程,这样可以提高效率:
在这里插入图片描述

解决思路总结

解决方案优点缺点
互斥锁没有额外内存消耗;保持一致性;实现简单线程要等待,性能受影响;可能死锁
逻辑过期线程无需等待,性能较好不保证一致性;有额外内存消耗;实现复杂

其实我感觉两种思路完全是可以结合在一起的,当然具体还是要看业务的应用场景和需求。

在下面的文章将会进行缓存击穿的解决思路的编码实现。

相关文章:

Redis:原理速成+项目实战——Redis实战4(解决Redis缓存穿透、雪崩、击穿)

👨‍🎓作者简介:一位大四、研0学生,正在努力准备大四暑假的实习 🌌上期文章:Redis:原理项目实战——Redis实战3(Redis缓存最佳实践(问题解析高级实现)&#x…...

后端开发——jdbc的学习(一)

上篇结束了Mysql数据库的基本使用,本篇开始对JDBC进行学习总结,开始先简单介绍jdbc的基本使用,以及简单的练习;后续会继续更新!以下代码可以直接复制到idea中运行,便于理解和练习。 JDBC的概念 JDBC&#…...

阿里云免费SSL证书时长只有3个月,应对方法来了

阿里云免费SSL证书签发有效期从12个月缩短至3个月:尊敬的用户,根据供应商变更要求,免费证书(默认证书)的签发有效期将由12个月缩短至3个月。 免费证书(升级证书)的有效期不会改变。 没错&#…...

Flutter 中使用 ICON

Flutter Icon URL : https://fonts.google.com/icons: 在Flutter中使用 Icon 步骤如下: 导入图标库 在Dart 文件中导入 material.dart 包,该包包含了 Flutter 的图标库。 import package:flutter/material.dart;使用图标组件 …...

百度编辑器常用设置

1、创建编辑器 UE.getEditor(editor, { initialFrameWidth:"100%" //初始化选项 }) 精简版 UE.getEditor(editor) 2、删除编辑器 UE.getEditor(editor).destroy(); 3、使编辑器获得焦点 UE.getEditor(editor).focus(); 4、获取编辑器内容 UE.getEditor(editor).getCo…...

Java ORM 框架 Mybatis详解

📖 内容 Mybatis 的前身就是 iBatis ,是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。本文以一个 Mybatis 完整示例为切入点,结合 Mybatis 底层源码分析,图文并茂的讲解 Mybatis 的核心工作机制。 …...

前端:html+css+js实现CSDN首页

提前说一下,只实现了部分片段哈!如下: 前端:htmlcssjs实现CSDN首页 1. 实现效果2. 需要了解的前端知识3. 固定定位的使用4. js 监听的使用4. 参考代码和运行结果 1. 实现效果 我的实现效果为: 原界面如下,网址为&…...

三种 SqlSession

三种 SqlSession ​SqlSession​ 是一个接口,并且里面包含了许多 CRUD 操作数据库等方法。 ​SqlSession​​ 它有三个实现类,分别是 SqlSessionManager​​ 、DefaultSqlSession​​ 和 SqlSessionTemplate​​,其中 DefaultSqlSession​​…...

Mybatis SQL构建器类 - 问题答案

问题 Java开发人员可能会碰到的最棘手的事情之一就是在Java代码中嵌入SQL语句。通常情况下,这是因为需要动态生成SQL语句 - 否则可以将其外部化到文件或存储过程中。正如你已经了解到的,MyBatis在其XML映射功能中有一个强大的解决方案来生成动态SQL。然…...

React 是什么?有什么特性?有哪些优势?

一、是什么 React,用于构建用户界面的 JavaScript 库,只提供了 UI 层面的解决方案 这句话的意思是,React 是一个专注于构建用户界面的 JavaScript 库,它主要关注于解决 UI 层面的问题。它并不是一个全功能的框架,而是…...

瑞吉外卖项目详细总结

文章目录 瑞吉外卖1.技术栈2.项目文件架构3.业务功能模块(例子)3.1管理员登录接口层(Controller)3.2管理员登录实现层(ServiceImpl)3.3管理员登录服务层(Service)3.4管理员登录Mapper层 4.公共模块4.1 BaseContext(保存…...

Cytoscape 3.10安装包下载及安装教程

Cytoscape3.10下载链接:https://docs.qq.com/doc/DUkpuR0RVU0JVWkFP 1、选中下载好的安装包,右键选择解压到“Cytoscape 3.10”文件夹 2、双击打开“Cytoscape_3_10_0_windows_64bit.exe” 3.点击“Download”,请耐心等待“Java”完成 4、点击…...

data.TensorDataset解析

data.TensorDataset 是 PyTorch 中的一个类,用于创建一个包含多个张量的数据集。这个类的主要作用是将输入的张量组合成一个数据集,使得在训练过程中可以方便地进行数据加载和迭代。 具体来说,TensorDataset 接受一系列的张量作为输入参数&a…...

贝锐花生壳全新功能:浏览器一键远程访问SSHRDP远程桌面

为了满足特定场景的远程访问需求,如:远程群晖NAS设备、远程SQL Server数据库/MySQL数据库、3389远程桌面(RDP远程桌面)、远程SSH、我的世界游戏联机…… 贝锐花生壳推出了场景映射服务,不仅提供满足相应场景的网络带宽…...

2024 年度 AAAI Fellows 揭晓!清华大学朱军教授入选!

今日,国际人工智能领域最权威的学术组织 AAAI 揭晓 2024 年度 Fellows 评选结果,新增 12 位 Fellow。 其中,清华大学计算机系教授朱军因「在机器学习理论与实践方面做出的重大贡献」而成功入选,成为本年度入选的唯一华人学者&…...

Linux(openssl):用CA证书签名具有SAN的CSR

Linux(openssl):创建CA证书,并用其对CSR进行签名_生成ca证书签名请求文件csr-CSDN博客 提供了方法为CSR进行签名。 对于有SAN的CSR如何签名呢? 1.创建CA证书,与下面的帖子一样...

从零开始了解大数据(七):总结

系列文章目录 从零开始了解大数据(一):数据分析入门篇-CSDN博客 从零开始了解大数据(二):Hadoop篇-CSDN博客 从零开始了解大数据(三):HDFS分布式文件系统篇-CSDN博客 从零开始了解大数据(四):MapReduce篇-CSDN博客 从零开始了解大…...

增量预训练经验积累(3)

站在巨人的肩膀上才能走的更远~本文主要是针对《千亿参数开源大模型 BLOOM 背后的技术》进行学习和提取关键经验。 1、BLOOM与Megatron-DeepSpeed 1.1 BLOOM训练细节 BLOOM 的模型架构与 GPT3 非常相似,只是增加了一些改进,176B BLOOM 模型的训练于 2022 年 3 月至 7 月期…...

R语言【CoordinateCleaner】——cc_dupl():根据物种名称和坐标以及用户定义的附加列删除或标记重复的记录

Package CoordinateCleaner version 2.0-20 Parameters cc_dupl(x,lon "decimallongitude",lat "decimallatitude",species "species",additions NULL,value "clean",verbose TRUE ) 参数【x】:data.frame。包含地…...

Hadoop安装笔记1单机/伪分布式配置_Hadoop3.1.3——备赛笔记——2024全国职业院校技能大赛“大数据应用开发”赛项——任务2:离线数据处理

将下发的ds_db01.sql数据库文件放置mysql中 12、编写Scala代码,使用Spark将MySQL的ds_db01库中表user_info的全量数据抽取到Hive的ods库中表user_info。字段名称、类型不变,同时添加静态分区,分区字段为etl_date,类型为String&am…...

python数据分析之交叉验证

python数据分析之交叉验证 1、常用的分类算法 有监督:SVM向量机、梯度提升、决策树(随机森林)、朴素贝叶斯、逻辑斯蒂回归、神经网络(cnn、rnn) 无监督:k-means、隐马尔可夫 2、数据分析过程 1、采集数据 2、数据预处理 3、特征选择 4、模型训练、评估、保存 5、模型…...

机器人技能学习--数据集剖析

文章目录 前言数据总览数据介绍actionsrobot0_eef_poserobot0_eef_quatstatesobject 参考资料 前言 一切为了能自己构建属于自己的数据集,所以,从现有数据集剖析入手。    目前,基于 MimicGen 官方提供的数据集,初始数据集有11组…...

Jenkins的Transfers路径怎么配置,解决Transfers配置不生效的问题

Transfers配置: 1.配置Source files: 要填写jar包的相对路径,从当前项目工作空间的根目录开始,看看我的工作空间你就懂了 !如图 我填的是 parent/build/libs/parent-1.0.0.jar,即不要 fdw1/ 的前缀 2.配置Remote directory: 远程目标文件夹,也就是你jar包要放到远程…...

php安装扩展event 提示 No package ‘openssl‘ found 解决方法

在使用pecl编译安装最新版event模块的时候提示 No package openssl found , 可是本机是安装了openssl的, 编译时找不到, 大概率就是环境配置的问题了, 增加 OPENSSL_CFLAGS OPENSSL_LIBS环境变量即可解决. 异常提示信息: checking for openssl > 1.0.2... no configure: …...

基于SpringBoot的动物领养平台的设计与实现

文章目录 项目介绍主要功能截图:部分代码展示设计总结项目获取方式🍅 作者主页:超级无敌暴龙战士塔塔开 🍅 简介:Java领域优质创作者🏆、 简历模板、学习资料、面试题库【关注我,都给你】 🍅文末获取源码联系🍅 项目介绍 基于SpringBoot的动物领养平台的设计与实…...

计算机网络期末复习——计算大题(一)

个人名片: 🦁作者简介:一名喜欢分享和记录学习的在校大学生 🐯个人主页:妄北y 🐧个人QQ:2061314755 🐻个人邮箱:2061314755qq.com 🦉个人WeChat:V…...

2024年深度学习、计算机视觉与大模型面试题综述,六大专题数百道题目

DeepLearning-Interview-Awesome-2024 本项目涵盖了大模型(LLMs)专题、计算机视觉与感知算法专题、深度学习基础与框架专题、自动驾驶、智慧医疗等行业垂域专题、手撕项目代码专题、优异开源资源推荐专题共计6大专题模块。我们将持续整理汇总最新的面试题并详细解析这些题目&a…...

解读 $mash 通证 “Fair Launch” 规则,将公平发挥极致

Solmash 是 Solana 生态中由社区主导的铭文资产 LaunchPad 平台,该平台旨在为 Solana 原生铭文项目,以及通过其合作伙伴 SoBit 跨链桥桥接到 Solana 的 Bitcoin 生态铭文项目提供更广泛的启动机会。有了 Solmash,将会有更多的 Solana 生态的铭…...

06、docker 安装mysql8

Docker 安装 MySQL8 下载mysql8的镜像 docker pull mysql:8.0.32启动镜像 docker run -p 3307:3306 --name mysql8 -e MYSQL_ROOT_PASSWORD123456 -d mysql:8.0.32配置挂载 创建挂载目录 mkdir -p /docker/mysql8.0.32/copy配置文件到创建的目录下 docker cp mysql:/etc/mysql…...

魔改Stable Diffusion,开源创新“单目深度估计”模型

单目深度估计一直是计算机视觉领域的难点。仅凭一张 RGB 图像,想要还原出场景的三维结构,在几何结构上非常不确定,必须依赖复杂的场景理解能力。 即便使用更强大的深度学习模型来实现,也面临算力需求高、图像数据注释量大、泛化能力弱等缺点。 为了解决这些难题&a…...

天津平台网站建设设计/seo网站营销推广公司

[传送门] 问题: 树状数组: 单点修改,区间查询 感觉 还是挺简单的嘛 就一个lowbit CODE #include <bits/stdc.h> using namespace std; const int N 5e510; typedef long long ll; ll a[N],c[N]; ll n,m;ll lowbit(ll x) {return x&(-x); } void updata(ll i,…...

做网站推广的方法有哪些/java培训班

案例介绍&#xff1a; 我们在日常生活中&#xff0c;经常与朋友们玩猜数字的游戏&#xff0c;非常的有趣。现在我们通过java把这个猜数字游戏编写出来。 猜数字案例是要完成什么样的功能呢&#xff1f;顾名思义&#xff0c;这个游戏就是你出个数字、我来猜。 游戏操作如下&…...

用织梦系统做网站/百度首页官网

"检查点"是 Windows Server 2012 R2 中对 Windows Server 2012 及以前版本的 Hyper-V"快照"功能的新称呼。之所以改成这个名称&#xff0c;其实和私有云有一定的关系。在私有云组件 System Center 2012 SP1 Virtual Machine Manager 中&#xff0c;它的&qu…...

网站制作教程一般地建网络/百度账号管理中心

2019独角兽企业重金招聘Python工程师标准>>> FileAudit允许用户从审计访问事件中排除掉某些特定事件&#xff0c;用户可以把对于自身来说不敏感的文件审计访问事件设定在这些派出范围之类&#xff0c;这样一来就FileAudit就会自动过滤掉这些不明感时间&#xff0c;以…...

wordpress 公众号 采集器/太原网站建设制作

本节书摘来异步社区《贝叶斯方法&#xff1a;概率编程与贝叶斯推断》一书中的第1章&#xff0c;第1.7节&#xff0c;作者&#xff1a;【加】Cameron Davidson-Pilon&#xff08;卡梅隆 戴维森-皮隆&#xff09;&#xff0c;更多章节内容可以访问云栖社区“异步社区”公众号查看…...

phpcms可以做网站吗/搜索引擎查询

解析 H.264 NAL Unit 帧类型的代码&#xff1a; 1 // 2 // 功能: 从 Nal Unit 数据中获取帧类型 3 // 读取字节结构体 4 typedef struct bs_t_T 5 { 6 unsigned char *pucStart; // 缓冲区首地址 7 unsigned char *pucCurrent; // 缓冲区当…...