什么是缓存、为什么要用缓存、缓存分类、缓存测试、缓存更新、缓存设计考虑点、缓存测试点

一、缓存

缓存是一种将数据存储在高速缓存中的技术,它可以提高应用程序的性能和响应速度。

二、 为什么要用缓存

1. 高性能(主要目的)
查询耗时,但变化少,又有很多读请求情况下,可以将查询结果放到缓存中。减少对数据库的压力,提升响应速度。

在这里插入图片描述

2. 高并发
Mysql对高并发支持不好,单机撑到2kQPS容易告警,所以对于1s上万个请求,会让mysql宕机。缓存功能简单,说白了就是 key-value 式操作,单机支撑的并发量一秒可达几万十几万,单机承载并发量是 mysql 单机的几十倍。
在这里插入图片描述

三、缓存分类

本地缓存
定义:直接运行在应用程序本地的缓存组件
优点:应用程序和cache是在同一个进程内部,请求缓存非常快速,没有过多的网络开销等,在单应用不需要集群支持或者集群情况下各节点无需互相通知的场景下使用本地缓存较合适。
缺点:缓存跟应用程序耦合,多个应用程序无法直接的共享缓存,各应用或集群的各节点都需要维护自己的单独缓存,对内存是一种浪费。
在这里插入图片描述
分布式缓存
定义:分布式缓存是指独立的缓存服务,不和任何一个具体的应用耦合,可以独立运行并搭建缓存集群。类似数据库,所有的应用程序都可以连接同一个缓存服务以获取相同的缓存数据。
优点:自身就是一个独立的应用,与本地应用隔离,多个应用可直接的共享缓存。
缺点:优点也就是缺点,因为自身是一个独立的应用,本地节点都需要与其进行通信,导致依赖网络,同时如果缓存服务崩溃可能会影响所有依赖节点(缓存雪崩)。
在这里插入图片描述

四、缓存异常&测试方法

1.缓存雪崩
定义:大量缓存数据在同一时间过期(失效)或者 Redis 故障宕机。调用时这些接口查询缓存时无数据,去查询数据库,这些请求都指向数据库,数据库压力增大,耗时增加。
解决方案:

  • 均匀设置过期时间:避免同一时间失效
  • 读数据库加互斥锁:如果发现访问的数据不在 Redis 里,就加个互斥锁,保证同一时间内只有一个请求来构建缓存(从数据库读取数据,再将数据更新到 Redis 里),当缓存构建完成后,再释放锁。未能获取互斥锁的请求,要么等待锁释放后重新读取缓存,要么就返回空值或者默认值。
    实现互斥锁的时候,最好设置超时时间,不然第一个请求拿到了锁,然后这个请求发生了某种意外而一直阻塞,一直不释放锁,这时其他请求也一直拿不到锁,整个系统就会出现无响应的现象。
    后台更新缓存:不设置过期时间

模拟测试方法:对多个使用到缓存的接口进行并发调用,设置这些缓存时间已过期(即删除缓存),调用时这些接口查询缓存时无数据,去查询数据库,这些请求都指向数据库,数据库压力增大,耗时增加。

测试通过标准:每个缓存失效的数据都只执行了一次数据库查询并设置缓存,之后请求都命中了缓存。

2.缓存击穿
定义:热点数据过期,此时大量的请求访问了该热点数据,就无法从缓存中读取,直接访问数据库,数据库很容易就被高并发的请求冲垮。
解决方案

  • 设置热点数据永远不过期。
  • 读数据库时加互斥锁,写入缓存,其他等待线程就可以从缓存读取

模拟测试方法:对某个 Key 有大量的并发请求,这时从缓存中删除这个 key,再并发访问。
测试通过标准:并发调用接口,缓存失效的那个数据只有一个请求执行了数据库查询并设置缓存,其他查询则命中缓存。其他请求都命中了缓存。

3.缓存穿透
定义:不断发起查询缓存和数据库中都没有的数据,导致压力全部落在数据库,导致数据库压力过大。
解决方案:当数据库查询为空时,将缓存赋值默认值,后续查询都走缓存,减少数据库压力。
模拟测试方法:查询一个根本不存在的数据,缓存层和存储层都不会命中。
测试通过标准:每个不存在的数据都只执行了一次数据库查询并设置缓存,之后请求都命中了缓存,有效防止了缓存穿透问题。

五、 缓存更新方式

有三种更新方式:

  • 惰性加载(Lazy Loading/Expiration):这是最懒的更新方式。通过设置缓存有效期,让缓存失效后通过新的请求自动创建新的缓存。
    **优点:**实现简单,数据总是最新的,只有在数据被请求时才会更新,节省资源。
    缺点:在缓存失效后的第一个请求可能会遇到延迟,因为需要重新从数据源加载数据。此外,如果缓存中存储的是热点数据,可能会导致缓存击穿问题。
  • 缓存失效(Cache Invalidation):在更新db数据后,直接删除缓存,通过新的请求自动创建新的缓存。
    优点:简单直接,保证了下一次请求一定会得到最新数据。
    缺点:可能导致数据在缓存被删除和新缓存被创建之间的短暂时间内不一致。同时,如果删除操作和数据库更新操作之间有任何延迟,也会导致缓存和数据库之间的数据不一致。
  • 重新设置缓存(Write-Through/Update Cache):在更新db数据后,直接重新设置缓存。
    优点:缓存始终保持最新状态,避免了因缓存失效而导致的延迟,也减少了数据不一致的风险。
    缺点:每次数据库更新时都需要更新缓存,这可能会导致额外的开销,特别是在写操作频繁的场景下。

六、 缓存更新策略

1. 先删除缓存后更新数据库(会造成数据不一致)
在删除缓存未更新数据库前,有读请求更新缓存,从而导致数据库和缓存不一致。
在这里插入图片描述

2. Cache Aside(更新数据库后缓存失效)旁路换存储策略
最常用策略,应用程序直接与「数据库、缓存」交互,并负责对缓存的维护

  • 失效:应用程序先从cache取数据,没有得到,则从数据库中取数据,成功后,放到缓存中。
  • 命中:应用程序从cache中取数据,取到后返回。
  • 更新:先把数据存到数据库中,成功后,再让缓存失效。
    在这里插入图片描述

也会发生数据不一致问题,但出现概率不高,原因是缓存的写入通常远快于比数据库写入。实际很难出现B更新完数据库删了缓存,A才更新完缓存清空。
在这里插入图片描述

如果业务对缓存命中率有严格的要求,那么可以考虑两种解决方案:

  • 一种做法是在更新数据时也更新缓存,只是在更新缓存前先加一个分布式锁,因为这样在同一时间只允许一个线程更新缓存,就不会产生并发问题了。当然这么做对于写入的性能会有一些影响;
  • 另一种做法同样也是在更新数据时更新缓存,只是给缓存加一个较短的过期时间,这样即使出现缓存不一致的情况,缓存的数据也会很快过期,对业务的影响也是可以接受。

3. Read/Write Through(读穿 / 写穿)策略
该模式把更新DB操作由Cache自己代理,对开发人员更简便。应用认为后端就是个单一存储,而存储自己维护自己的Cache。服务器只和 Cache 沟通,Cache 负责去沟通 DB,把数据持久化。
业界典型代表:Redis(可理解为 Redis 里包含了一个 Cache 和一个 DB)
在这里插入图片描述

Read Through 策略
先查询缓存中数据是否存在,如果存在则直接返回,如果不存在,则由缓存组件负责从数据库查询数据,并将结果写入到缓存组件,最后缓存组件将数据返回给应用。

Write Through 策略

  • 当有数据更新的时候,先查询要写入的数据在缓存中是否已经存在:如果缓存中数据已经存在,则更新缓存中的数据,并且由缓存组件同步更新到数据库中,然后缓存组件告知应用程序更新完成。
  • 如果缓存中数据不存在,直接更新数据库,然后返回;
    在这里插入图片描述

4. Write Behind Caching
Write Back(写回)策略在更新数据的时候,只更新缓存,同时将缓存数据设置为脏的,然后立马返回,并不会更新数据库。对于数据库的更新,会通过批量异步更新的方式进行。
优点

  • 让数据的I/O操作飞快(直接操作内存 )
  • 因为异步,write back还可合并对同一个数据的多次操作,对性能提高相当可观
    缺点
  • 数据非强一致性,可能丢失(Linux非正常关机会导致数据丢失)
  • 实现逻辑复杂,因为需track哪些数据是被更新的,待刷到DB
  • os的write back会在仅当该cache需失效时,才会被真正持久化,如内存不够或进程退出等情况,这又叫lazy write
    在这里插入图片描述

七、缓存设计考虑点

1.缓存时间设置合理性。
缓存时间设置,需要根据数据更新的频次合理设置;缓存时间太长会导致用户访问到的数据一直是老的,缓存设置时间太短对数据库访问会比较频繁。所以最好调研清楚实际数据更新的频次,再去设置缓存时间
2.存储逻辑合理性。
①服务端或数据库返回数据正确性。返回异常,不应该缓存;返回数据正常,才需要缓存;
②在缓存数据时,需要考虑查询条件的选择,这通常取决于业务需求和数据访问模式。例如,如果一个系统允许通过歌名或歌手来检索歌曲信息,那么可能需要为每种查询类型分别缓存数据。
3. 缓存读取逻辑合理性。以下是比较合理的逻辑:
有缓存,优先读取缓存;
无缓存,请求接口或查数据库获取数据;并存储缓存;
注意:缓存不命中也需要结合具体业务,比如上面的例子中,如果三位查不到缓存,大多数情况就是没有数据,在我们看来是一种正常的情况,会直接返回空结果,而不会去查数据库,避免造成缓存穿透。
4.缓存更新逻辑
缓存失效后是否会更新缓存的内容
注意:关注过期时间和更新时间的临界点,会不会出现异常情况,比如
5.缓存内容
redis缓存具体内容是否正确、格式(list、string)是否合理、实际每次缓存的数据数是否与需求一致
6.缓存数据重复
同样的数据触发保存缓存逻辑之后,应该只有一条在redis缓存中可以查到,重复缓存会浪费资源

八、缓存测试点

基本功能:

  1. 缓存增加:缓存与数据库的数据一致性检测。
  2. 缓存读取:缓存和数据库中均存在;缓存无,数据库有数据情况; 缓存和数据库中均不存在
  3. 缓存过期:验证数据在缓存中的过期机制是否按预期工作,包括时间过期和条件过期。再次请求,缓存是否正确写入。
  4. 缓存更新:当后端数据更新时,缓存应该相应地更新或失效。需要测试缓存更新机制是否正确执行。
  5. DB事务性导致回滚,缓存是否回滚,有没有产生脏数据。(可通过延迟写入解决)
  6. 缓存预热:验证缓存预热策略是否能够有效地将热点数据加载到缓存中,以避免系统启动初期的高延迟。

特殊场景

  1. 缓存读取时超时:校验缓存查询达到超时时间后,未返回指定的数据,对系统的影响。
    (可退化为查库)
  2. 缓存存储时超时:注意处理方式(比如重试)
  3. 特殊场景:缓存穿透、缓存雪崩、缓存击穿场景的解决方案
  4. 缓存上限:校验缓存淘汰参数配置与预期一致:增加缓存至达到 maxmemory 限制时(可修改 redis.conf 配置文件中配置的最大可用内存值),再次请求查询,数据返回正确,同时,检查被淘汰的数据确实是依照所配置的淘汰策略被移除的。
    监控线上的稳定性
  5. 监控缓存的命中率:评估缓存的设计是否达到预期;
  6. 监控中间件:CPU、内存是否异常;
  7. 监控是否有某个 key 过大;
  8. 监控是否存在缓存的频繁更新。

参考:https://mp.weixin.qq.com/s/9YXstvCin7pkmWlk4JI-fA
https://blog.csdn.net/qq_40685200/article/details/124861245

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

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

相关文章

Java位运算及移位运算

java中能表示整数数据类型的有byte、short、char、int、long,在计算机中占用的空间使用字节描述,1个字节使用8位二进制表示。 数据类型字节数二进制位数表示范围默认值byte18-27 – 27-10char2160 – 216-1\u0000 (代表字符为空 转成int就是0)short216-…

Word 将页面方向更改为横向或纵向

文章目录 更改整个文档的方向更改部分页面的方向方法1:方法2: 参考链接 更改整个文档的方向 选择“布局”>“方向”,选择“纵向”或“横向”。 更改部分页面的方向 需要达到下图结果: 方法1: 选:中你要在横向页面…

帆软报表中定时调度中的最后一步如何增加新的处理方式

在定时调度中,到调度执行完之后,我们可能想做一些别的事情,当自带的处理方式不满足时,可以自定义自己的处理方式。 产品的处理方式一共有如下这些类型: 我们想在除了上面的处理方式之外增加自己的处理方式应该怎么做呢? 先看下效果: 涉及到两方面的改造,前端与后端。…

C++日期类的实现

前言:在类和对象比较熟悉的情况下,我们我们就可以开始制作日期表了,实现日期类所包含的知识点有构造函数,析构函数,函数重载,拷贝构造函数,运算符重载,const成员函数 1.日期类的加减…

【产品设计】信息建设三驾马车:PLM系统拆解

本篇文章将介绍PLM的基础信息、发展及模块功能等内容,让大家对PLM有一个全面、完整地了解,方便在后期的工作中能快速地使用其解决方案,希望本篇文章能对你有所帮助。 PLM系统主要实现产品模块业务,既包含产品的创意设计、样品打样…

【源码】-MyBatis-如何系统地看源码

写在前面 前段时间做过一个项目,期间用到了动态数据源dynamic-datasource,经历了dbcp2的数据库连接池没有生效到排查定位、MyBatis多种数据库产品兼容、手写MyBatis拦截器等事情。 花费了好久,一直在打磨这篇文章(不知道花费这么长…

thinkphp6.0升级到8.0

目录 一:升级过程 二:报错处理 最近写的项目需要使用thinkphp8.0,之前的老项目需要从php6.0升级到8.0,特此记录下升级过程。 一:升级过程 查看版本: php think version,我目前的版本是6.1.4 生成thin…

WPF+Halcon 培训项目实战(8-9):WPF+Halcon初次开发

文章目录 前言相关链接项目专栏运行环境匹配图片WPF Halcon组件HSmartWindowControlWPF绑定读取图片运行代码运行结果 抖动问题解决运行结果 绘制矩形绘制图像会消失 绘制对象绑定事件拖动事件 前言 为了更好地去学习WPFHalcon,我决定去报个班学一下。原因无非是想…

C/C++面向对象(OOP)编程-回调函数详解(回调函数、C/C++异步回调、函数指针)

本文主要介绍回调函数的使用,包括函数指针、异步回调编程、主要通过详细的例子来指导在异步编程和事件编程中如何使用回调函数来实现。 🎬个人简介:一个全栈工程师的升级之路! 📋个人专栏:C/C精进之路 &…

Spark魔力:招聘网站数据深度分析系统

Spark魔力:招聘网站数据深度分析系统 简介数据集技术栈功能特点创新点 简介 在本文中,我们将介绍一款基于Spark的招聘网站数据分析系统,该系统使用爬取的前程无忧招聘数据。通过结合Flask、Pandas、PySpark、以及MySQL等技术,实现…

【汇编笔记】初识汇编-内存读写

汇编语言的由来: CPU是计算机的核心,由于计算机只认识二进制,所以CPU执行的指令是二进制。 我们要想让CPU工作,就得给他提供它认识的指令,这一系列的指令的集合,称之为指令集。 指令集: 不同的体…

单片机键盘程序设计举例

1、键盘与的连接 图3键盘连接 图4单片机与键盘接口图 2、通过1/0口连接。将每个按钮的一端接到单片机的I/O口,另一端接地,这是最简单的办法,如图3所示是实验板上按钮的接法,四个按钮分别接到P3.2 、P3.3、P3.4和P3.5。对于这种键…

css 设置鼠标覆盖显示菜单

鼠标覆盖到“全部分类”效果如下 鼠标放到“精品推荐”效果如下 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"&g…

【CF比赛记录】—— Good Bye 2023(A、B、C)

&#x1f30f;博客主页&#xff1a;PH_modest的博客主页 &#x1f6a9;当前专栏&#xff1a;CF比赛记录 &#x1f48c;其他专栏&#xff1a; &#x1f534;每日一题 &#x1f7e1; cf闯关练习 &#x1f7e2; C语言跬步积累 &#x1f308;座右铭&#xff1a;广积粮&#xff0c;缓…

mysql基础-表操作

环境&#xff1a; 管理工具&#xff1a;Navicat 数据库版本&#xff1a;5.7.37 mysql的版本&#xff0c;我们可以通过函数&#xff0c;version()进行查看&#xff0c;本次使用的版本如下&#xff1a; 目录 1.管理工具 1.1创建表 1.2.修改表名 1.3.复制表 1.4.删除表 2…

C#上位机与欧姆龙PLC的通信08----开发自己的通讯库读写数据

1、介绍 前面已经完成了7项工作&#xff1a; C#上位机与欧姆龙PLC的通信01----项目背景-CSDN博客 C#上位机与欧姆龙PLC的通信02----搭建仿真环境-CSDN博客 C#上位机与欧姆龙PLC的通信03----创建项目工程-CSDN博客 C#上位机与欧姆龙PLC的通信04---- 欧姆龙plc的存储区 C#上…

Linux常用命令大全总结及讲解(超详细版)

前言&#xff1a; Linux 是一个基于Linux 内核的开源类Unix 操作系统&#xff0c;Linus Torvalds于 1991 年 9 月 17 日首次发布的操作系统内核。Linux 通常打包为Linux 发行版。 Linux 最初是为基于Intel x86架构的个人计算机开发的&#xff0c;但此后被移植到的平台比任何其…

前端实现websocket类封装

随着Web应用程序的发展&#xff0c;越来越多的人开始利用Websocket技术来构建实时应用程序。Websocket是一种在客户端和服务器之间建立持久连接的协议。这种协议可以在一个单独的连接上实现双向通信。与HTTP请求-响应模型不同&#xff0c;Websocket允许服务器自主地向客户端发送…

OpenCV-Python(21):OpenCV中的轮廓性质

3.轮廓的性质 本文我们将主要学习基于轮廓来提取一些经常使用的对象特征。 3.1 长宽比 边界矩形的宽高比&#xff1a; x,y,w,h cv2.boundingRect(cnt) aspect_ratio float(w)/h 3.2 Extent 轮廓面积与边界矩形面积的比。 area cv2.contourArea(cnt) x,y,w,h cv2.bounding…

基于JavaWeb实验室预约管理系统(源码+数据库+文档)

一、项目简介 本项目是一套基于JavaWeb实验室预约管理系统&#xff0c;主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的Java学习者。 包含&#xff1a;项目源码、数据库脚本等&#xff0c;该项目附带全部源码可作为毕设使用。 项目都经过严格调试&#xff0c;e…