【Redis】redis缓存击穿,缓存雪崩,缓存穿透

一、什么是缓存?

        缓存就是与数据交互中的缓冲区,它一般存储在内存中且读写效率高,提高响应时间提高并发性能,如果访问数据的话可以先访问缓存,避免数据查询直接操作数据库,造成后端压力过大。

        但是可能会面临数据不一致问题,比如访问数据时拿到的是缓存中的数据,但是实际上数据库此时已经改变了,那么拿到的缓存中拿到数据与数据库中数据会有不一致的问题。解决数据一致性问题会要进行代码操作,增加代码维护成本,如果使用redis还会有运维成本。

二、怎么用redis实现缓存?

        实际上就是把redis作用在客户端与数据库中间,充当缓冲区作为缓存。我们一般把一些经常访问,但是变化不大的数据放入缓存区,因为访问量大对磁盘IO次数多性能消耗大,如果作用与缓存区那么存储效率会快,第二是对于变化不大的数据,对于读写不一致问题问题出现概率较小。 

         大概流程就是我们要获取数据的时候先操作缓存,如果在缓存redis中查不到数据就访问数据库,如果查到了就将数据写入缓存中,并且返回给客户端。

        在Java中可以使用RedisTemplate类进行操作redis数据库,里面封装了很多方法可供使用,但是它默认使用的jdk 的序列号工具,将数据序列话后是2进制,为了方便操作数据,我们可以手动将它的序列号工具用第三方例如jackson的将数据序列化为json格式。

三、缓存更新策略

        缓存更新策略有三种,内存淘汰、超时剔除、主动更新。

        内存淘汰它是指redis内存不足后它会自动清理一些内存,在清理掉这些内存后,如果再查询对应的数据它在redis中查不到就会去数据库中查返回给客户端,并且把数据写入Redis中,完成缓存更新策略。它是默认开启,一致性较差。

        超时淘汰指的是给数据设置超时时间,如果对应超过了对应的时间则将缓存清理,这种一般作为主动剔除的保底策略。主动更新是主动将数据从redis中剔除,这种方式面对与要求数据一致性较强的操作。

        主动更新策略

                1.cache aside pattern

                        由缓存调用者在更新数据库时同时更新缓存

        操作缓存和数据库中,我们应该删除操作,还是更新缓存?

        答:应该选择删除缓存,如果使用更新缓存,每次更新数据库都更新缓存,如果几乎不查询数据库,那么根本没必要使用缓存更新策略,使用缓存就是优化查询的速度。所以使用删除缓存模式,等下次进行查询数据库的时候再把缓存写入redis中,避免无用的写操作。

        如何保证缓存与数据库操作同时成功或失败?

        答:单体系统放在一个事务里,分布式服务理由TCC等分布式事务解决。

        先删除缓存,再操作数据库 还是先操作数据库再删除缓存?

        答:正常线程1删除缓存,然后更新数据库信息。但是由于多线程情况下,线程1更新数据库的过程中比较慢,突然中间插入了一个线程操作,线程2进行查询值,由于此时线程1已经将数据删除,所以缓存未命中于是查询数据库,查到了然后将数据写入缓存中。但是此时更新 数据库操作完成了,就造成缓存中的数据是10,但是数据库的值为20,缓存与数据库。

        先操作数据库再删除缓存

        答:正常情况是更新数据库,然后更新缓存。但是线程2之前有一个线程1进来查数据,并且此时缓存失效了,就会线程1进行查数据库发现数据是10。然后线程2要进行更新数据删除缓存操作,此时将数据库数据为20。然后线程一会将之前查出的数据10写入缓存中。这个概率比先删除再更新概率要低很多,首先是在缓存失效后有一个线程要进行查数据,然后紧接着有个线程要进行修改数据,并且写入的速度是比更新的速度快的,写入有几微秒,但是更新要比写入要慢一些,也就是说在几微妙下,线程2更新删除操作必须立刻完成,所以这种概率比较小。

                 2.read/write through pattern

                        缓存与数据库作为一种整体,由服务器管理数据一致性,无需调用者关系一直性问题。最大的问题是维护它是比较复杂的。调用者不知道操作的数据库还是缓存。

                3.write behind caching pattern

                        调用者也是无需关系数据一致性,但是它只读取缓存,由一个线程异步将缓存和数据库进行操作,一定时间将缓存数据写入数据库中。一致性和可靠性可能存在问题。

        对于数据库和缓存直接的数据一致性问题,可以使用canal,让他伪装成一个数据库的从节点,在主节点配置信息后,再从节点使用canal配置主节点的端口,ip等,然后再Java中引入canal的包,之后配置canal配置名字,ip,通过注解CanalTable监听表,如果改变了就将数据同步到redis中。 

四、缓存穿透

        缓存穿透指的是在数据库中和缓存中都没有的情况下进行查询操作。

                        1.缓存空对象解决缓存穿透,查询缓存如果为空查询数据库也为空,如果不断查询数据库会对数据库造成巨大的查询压力,所以可以设置一个缓存,key对应查询的对象,值为null。但是如果有可能此时数据库添加了该值,但是缓存还是之前的null值,此时可以设置个过期时间,或者插入数据库的时候查有没有缓存有的话删除就可以了,可能会造成短期数据不一致问题。

                        2.使用布隆过滤器解决缓存穿透

                 将数据库的数据根据hash算法,然后转换存2进制位存入布隆过滤器,然后如果有数据进来后,通过相同的算法进行与 布隆过滤器里的值进行比对,如果对应位有该数据说明该值有一定可能存在,如果布隆过滤器不存在说明值真不存在。内存占用特别小,实现复杂,存在误判的可能。

五、缓存雪崩

        缓存雪崩指的是同一时间大量数据同时失效或者redis宕机, 大量数据雪崩打入数据库中。

        解决方案:

                给缓存设置ttl设置随机值,防止缓存同时失效。

                确保redis高可用性,主从机制,当主宕机了从服务器可以挑选从节点作为主。

                限流降级sentinel,或者设置多级缓存

六、缓存击穿

         大量数据打进来,然后缓存数据失效需要重建的过程,再次过程中时间比较长,后面的数据继续访问需要先查缓存,此时缓存为建立,然后会查询数据库,不断的访问对数据库有巨大的冲击。

        结局方案 :1.互斥锁,2.逻辑过期

                1.互斥锁是如果缓存查询不到就操作数据库,在操作数据库操作重建缓存的过程完成后释放锁,其他线程在查不到缓存后会操作数据库前也需要获取锁。所以并发性能差,实现简单。

                2.逻辑过期指的是在查询缓存后发现逻辑过期也就是失效了,然后加互斥锁,此时开辟一个新的线程查询数据库更新缓存逻辑过期时间,然后返回旧缓存值。如果新的线程真的更新完毕了那么才会释放锁,在这期间如果其他线程进来查缓存失效了那么就会访问数据库发现互斥锁没释释放,说明此时新线程没有重建缓存完毕,那么会直接返回过期的旧缓存值。这样可以增加并发性,但是数据一致性较差,实现复杂,性能消耗大。

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

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

相关文章

全面解析:HTML页面的加载全过程(一)--输入URL地址,与服务器建立连接

用户输入URL地址,与服务器建立连接 用户在浏览器地址栏输入一个URL 浏览器开始执行以下三步操作操作:url解析、DNS查询、TCP连接 第一步:URL解析 什么是URL? URL(Uniform Resource Locator,统一资源定位符)是互联网…

uni-ui自动化导入

2024年8月6日 https://uniapp.dcloud.net.cn/component/uniui/uni-ui.html 安装 https://www.npmjs.com/package/dcloudio/uni-ui npm i dcloudio/uni-ui配置自动导入功能 在pages.json文件里添加easycom节点: "easycom": {"autoscan": true,"custom…

实验三:构建园区网(静态路由)

目录 一、实验简介 二、实验目的 三、实验需求 四、实验拓扑 五、实验任务及要求 1、任务 1:完成网络部署 2、任务 2:设计全网 IP 地址 3、任务 3:实现全网各主机之间的互访 六、实验步骤 1、在 eNSP 中部署网络 2、配置各主机 IP …

电脑超频是什么意思?超频的好处和坏处

嗨,亲爱的小伙伴!你是否曾经听说过电脑超频?在电脑爱好者的圈子里,这个词似乎非常熟悉,但对很多普通用户来说,它可能还是一个神秘而陌生的存在。 今天,我将带你揭开超频的神秘面纱,…

android 如何获取当前 Activity 的类名和包名

其一:getClass().getSimpleName() public static String getTopActivity(Context context){ ActivityManager am (ActivityManager) context.getSystemService(context.ACTIVITY_SERVICE); ComponentName cn am.getRunningTasks(1).get(0).topAct…

【YOLOv8】安卓端部署-2-项目实战

文章目录 1 准备Android项目文件1.1 解压文件1.2 放置ncnn模型文件1.3 放置ncnn和opencv的android文件1.4 修改CMakeLists.txt文件 2 手机连接电脑并编译软件2.1 编译软件2.2 更新配置及布局2.3 编译2.4 连接手机 3 自己数据集训练模型的部署4 参考 1 准备Android项目文件 1.1…

三十九、Python(pytest框架-中)

一、执行用例的方式 1.工具执行 2.在终端使用命令行运行 命令:pytest -s 用例代码文件 -s 的作用是输出显示代码中的 print。 3.在主函数main中执行 if __name__ "__main__": # 主函数pytest.main([-s, 用例代码文件]) import pytestclass TestDemo…

mybatis的动态sql用法之排序

概括 在最近的开发任务中,涉及到了一些页面的排序,其中最为常见的就是时间的降序和升序。这个有的前端控件就可以完成,但是对于一些无法用前端控件的,只能通过后端来进行解决。 后端的解决方法就是使用mybatis的动态sql拼接。 …

在AndroidStudio中新建项目时遇到的Gradle下载慢问题,配置错的按我的来,镜像地址不知道哪个网页找的,最主要下载要快

android-studio-2024.2.1.11-windows Android 移动应用开发者工具 – Android 开发者 | Android Developers https://r4---sn-j5o76n7z.gvt1-cn.com/edgedl/android/studio/install/2024.2.1.11/android-studio-2024.2.1.11-windows.exe?cms_redirectyes&met1731775…

项目配置文件选择(Json,xml,Yaml, INI)

选择使用哪种类型的配置文件(如 JSON、XML 或其他格式)取决于多个因素,包括项目的需求、团队的熟悉程度、数据结构的复杂性以及可读性和可维护性等。以下是对常见配置文件格式的比较,以及在不同情况下的推荐: 1. JSON&…

Vue学习记录07

列表渲染 v-for 可以使用v-for指令基于一个数组来渲染一个列表。v-for指令的值需要使用 item in items 形式的特殊语法,其中 items 是源数据的数组, 而 item 是迭代项的别名: const items ref([{ message: Foo }, { message: Bar }]) &l…

Android开发实战班 - 应用架构 - LiveData/Flow 数据流

在 MVVM 架构中,数据流是连接 ViewModel 和 View 的重要桥梁,用于实现数据的观察和响应。Jetpack 提供了两种主要的数据流机制:LiveData 和 Flow。本章节将深入讲解 LiveData 和 Flow 的概念、使用方法、区别以及在实际开发中的应用场景&…

rk3399开发环境使用Android 10初体验蓝牙功能

版本 日期 作者 变更表述 1.0 2024/11/10 于忠军 文档创建 零. 前言 由于Bluedroid的介绍文档有限,以及对Android的一些基本的知识需要了(Android 四大组件/AIDL/Framework/Binder机制/JNI/HIDL等),加上需要掌握的语言包括Java/C/C等&#xff0…

python脚本实现csv中百度经纬度转84经纬度

数据准备 csv文件,带百度经纬度字段:bd09_x,bd09_y 目的 将百度经纬度转换为84经纬度,并在csv文件中添加两个字段:84_x,84_y python脚本 from ChangeCoordinate import ChangeCoordimport pandas as pd import numpy as npcoord = ChangeCoord()def bd09_to_wgs84

前端反向代理的配置和實現

反向代理是位於客戶端和服務器之間的一個中間層,它代表客戶端向伺服器發起請求,然後將伺服器的回應返回給客戶端。與傳統的正向代理不同,反向代理是由伺服器端配置的,客戶端通常不知道它的存在。在前端開發中,反向代理…

微调Helsinki-NLP-en-zh模型

Helsinki-NLP 是一个广泛使用的开源机器翻译(Machine Translation,MT)模型系列,基于 Marian NMT 框架 Hugggingface地址:https://huggingface.co/Helsinki-NLP/opus-mt-en-zh 原本的模型对于国内外公司的名称支持度很…

C++中的初始化列表

初始化参数列表 用于在构造函数中初始化类的数据成员。 语法:构造函数():属性1(值1),属性2(值2)......{ } 性质: 1.只能在构造函数中使用 2.引用 或 常量…

QT基本绘图

QT绘图 1.概述 这篇文章介绍如何绘图 2.绘图基本操作 创建一个普通的widget类型的项目 在widget.h 文件中重写绘图事件 #ifndef WIDGET_H #define WIDGET_H#include <QWidget>QT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACEclass Widget : p…

【IEEE独立出版 |往届均已成功检索】第八届大数据与应用统计国际学术研讨会(ISBDAS 2025)

重要信息 时间地点&#xff1a;2025年2月28日-3月2日 中国 广州 会议检索&#xff1a;EI Compendex, Scopus →点此投稿/参会/了解会议详情 组织单位 主办单位&#xff1a;广东省高等教育学会人工智能与高等教育研究分会 协办单位&#xff1a;北京师范大学人工智能与未…

C# 中的 LINQ:轻松处理集合和数据

C#中的LINQ&#xff08;Language Integrated Query&#xff09;&#xff0c;这是一个非常强大且实用的功能&#xff0c;可以简化集合操作和数据查询。以下是一篇关于C#中LINQ使用的文章。 引言 LINQ&#xff08;Language Integrated Query&#xff09;是C#语言的一个重要特性…