浅谈业务场景中缓存的使用

业务场景中缓存的使用

  • 一、背景
  • 二、缓存分类
    • 1.本地缓存
    • 2.分布式缓存
  • 三、缓存读写模式
    • 1.读请求
    • 2.写请求
  • 四、缓存穿透
    • 1.缓存空对象
    • 2.请求校验
    • 3.请求来源限制
    • 4.布隆过滤器
  • 五、缓存击穿
    • 1.改变过期时间
    • 2.串行访问数据库
  • 六、缓存雪崩
    • 1.避免集中过期
    • 2.提前更新缓存
  • 七、缓存与数据库一致性
    • 1.设置缓存过期时间
    • 2.更新缓存/更新数据库
      • 2.1 先更新数据库再更新缓存
      • 2.2 先更新缓存再更新数据库
    • 3.先删除缓存再更新数据库
      • 3.1 两个操作事务性操作情况如下:
      • 3.2 数据一致性问题
    • 4.先更新数据库再删除缓存
      • 4.1 两个操作事务性操作情况如下:
      • 4.2 补偿机制
      • 4.3 数据一致性问题
    • 5.延时双删
      • 5.1 延时双删操作流程:
      • 5.2 延迟双删优化
  • 总结


一、背景

互联网相关业务相对于传统场景普遍存在高并发高流量的情况,因此在实际业务场景中,都会通过在业务和存储中间添加缓存层来减轻数据库的压力。使用缓存主要是为了提升响应速度和并发量,并减轻数据库的访问压力。在实际使用过程中需要解决缓存穿透、缓存击穿和缓存雪崩的发生,并且需要考虑缓存与数据库数据一致性问题。

二、缓存分类

缓存根据保存的位置不同分为本地缓存和分布式缓存。本地缓存就是保存在服务所在机器上,占用jvm内存空间;分布式缓存就是保存在独立的服务上如Redis集群上。

1.本地缓存

将一些只读基础数据进行本地缓存减轻数据库访问压力加快程序访问速度。这类数据特点变更不频繁,对缓存与数据库中数据不一致容忍度较高。服务启动时进行本地缓存加载,可以采用定时刷新缓存或者监听消息的方式重新加载缓存来保证本地缓存数据的实时性。

  • 缺点:占用本地内存,数据量受限;每个服务都需要保存,副本较多;服务启动时需要加载,可能导致启动时间较长;
  • 优点:本地缓存访问速度更快,独立缓存不互相影响

2.分布式缓存

将非只读数据保存在分布式缓存集群中可以提高服务的灵活度,提升响应速度提高并发量,这些数据基本都是程序运行过程中加载到缓存并在一段时间后会从缓存卸载。

  • 缺点:需要部署额外缓存集群;需要提供多副本防止单点故障;业务集群共用,缓存污染容易导致整个业务不可用;
  • 优点:不占用本地内存,数据量不受限制;与业务集群结偶,缓存保存在缓存集群中;服务运行过程中加载和卸载,不影响服务启动耗时;

三、缓存读写模式

经典的缓存+数据库读取 Cache Aside Pattern模型。
在这里插入图片描述

1.读请求

  • 读的时候先从缓存读取
  • 如果缓存中不存在,则需要从数据库中读取
  • 数据取出后需要写入到缓存中

2.写请求

  • 更新时需要先更新数据库
  • 然后删除缓存

四、缓存穿透

缓存穿透是指查询了一个在数据库和缓存中都不存在的数据。由经典 Cache Aside Pattern模型可知,所有请求都会进行数据库查询,如果请求非常多会给数据库造成访问压力乃至奔溃。造成这种场景有可能是误删除数据或者恶意攻击导致的。
为了防止此问题,基本都是采用空间换时间,也就是对访问请求进行一定拦截和过滤。

1.缓存空对象

当查询数据库无结果时,将空对象保存到缓存中并设置一个过期时间。当在缓存过期时间内,相同的请求在缓存中都可以查询到结果而不会访问到数据库。过期时间内数据库即使新增了数据也不会加载到缓存,因此需要合理设置过期时间长度。

2.请求校验

对于请求进行数据合法性校验,将不合法校验直接拦截,不进行缓存和数据库的查询操作。

3.请求来源限制

可以通过设置黑白名单,对请求来源进行限制,保证没有恶意攻击行为和非法请求。

4.布隆过滤器

将数据库中数据保存到布隆过滤器中,当请求过来先经过布隆过滤器,如果不存在直接拒绝,如果存在则继续查询。

五、缓存击穿

缓存击穿是查询的数据在缓存中不存在,但是数据库中存在。当缓存中key过期,而此时有大量并发请求此key会导致数据库压力剧增。可以通过限制同时查询数据库的请求或者缓存的过期时间避免此问题。

1.改变过期时间

设置热点数据永不过期

2.串行访问数据库

缓存击穿是大量并发请求同时进行数据库查询导致的。可以在进行对应数据库查询之前进行加锁操作。
2.1 当查询key时,首先查询缓存,如果没有。需要先获取分布式锁才能进入数据库查询然后将查询结果保存到缓存,然后解锁。
2.2 如果发现查询锁被占用,则说明有线程正在获取。所以等待锁接触后可以直接访问缓存而不必进行数据库查询操作。

六、缓存雪崩

缓存雪崩是指缓存中大批量key同时过期,而此时又是流量高峰导致后端数据库压力暴增,甚至会导致数据库挂掉。缓存击穿是指单个key过期,缓存雪崩是指大量key同时过期。

1.避免集中过期

将缓存中的数据缓存时间在原有的失效时间基础上加一个随机值,这样可以避免集体失效引发雪崩。

2.提前更新缓存

可以在缓存中数据过期前,主动更新缓存中的数据,防止数据到达TTL。

七、缓存与数据库一致性

由于缓存和数据库是两个数据源,如果想要保证两个数据源的强一致性需要对读写操作进行加锁处理和事务处理,但是加锁之后会影响整个系统的响应速度,基本不会采用此方式进行处理。在实际场景中,在强一致性和系统性能上采取一个妥协,基本上都是要求缓存和数据库在短时间内一致即可,也就是最终一致性而不要求强一致性。

1.设置缓存过期时间

此方案针对数据要求一致性比较低或者读多写少的业务场景。读时缓存如果没有数据,从数据库读取后写入缓存并设置过期时间。写时直接写入数据库,不操作缓存。

2.更新缓存/更新数据库

由于更新数据库和更新缓存有可能有一定的延迟和间隔。在并发写请求的情况下,不论先更新缓存后更新数据库,还是先更新数据库后更新缓存,都可能存在数据库和缓存数据不一致的情况。由于数据库和缓存都更新成功都有很大概率出现数据不一致的情况,所以不讨论其中一个失败的情况。

2.1 先更新数据库再更新缓存

在这里插入图片描述

2.2 先更新缓存再更新数据库

在这里插入图片描述

3.先删除缓存再更新数据库

3.1 两个操作事务性操作情况如下:

1) 删除缓存成功,更新数据库成功
2 )删除缓存失败,程序异常,不会进行更新数据库操作
3 )删除缓存成功,更新数据库失败,由于数据库还是旧数据,缓存中为空,数据不会不一致

3.2 数据一致性问题

在删除缓存和更新数据库操作之间的读请求,会从数据库读取旧数据然后写入到缓存中导致数据不一致。

4.先更新数据库再删除缓存

4.1 两个操作事务性操作情况如下:

1) 更新数据库成功,删除缓存成功
2 )更新数据库失败,程序异常,不会进行删除缓存操作
3 )更新数据库成功,删除缓存失败,由于数据库是新数据,缓存是旧数据,数据出现不一致

4.2 补偿机制

  • 删除失败重试,如果删除缓存失败,需要把此信息发送到消息队列,进行异步删除
  • 监听数据库变更,建立一个服务监听binlog变化,然后删除缓存。

4.3 数据一致性问题

出现数据不一致的条件是否苛刻,基本不会出现

5.延时双删

先更新数据库再删除缓存已经很好的解决了缓存和数据库一致性问题。但是现在的数据库基本都是进行了主从配置,也就是主库负责数据写入,从库负责数据读取。这样在数据同步到从库之前,可能读取从库旧数据然后写入缓存导致数据不一致。

5.1 延时双删操作流程:

1) 先删除缓存,可以加快缓存与数据库数据同步速度(高并发时可能数据库不断有值写入)
2 )更新数据库
3 )延迟一段时间(大于主从同步时间)删除缓存(等待新数据同步到从库)

5.2 延迟双删优化

延迟双删数据库与缓存至少需要等待数据同步到从库才会数据一致。可以在更新数据库之后,将key进行标记,然后立刻删除缓存。当读数据时,如果缓存中没有数据,需要看key是否进行了标记,如果标记了需要从主库读取数据人然后保存到缓存,并删除此标记。
此方案相当于牺牲了主库的一部分性能,来尽可能保证数据一致性。

总结

缓存是提高系统响应和吞吐量的一个方法,但是使用过程中需要解决缓存穿透、缓存击穿、缓存雪崩等问题,并且需要考虑缓存和数据库的数据一致性问题。如果考虑到程序的可靠性,建议程序对缓存是弱依赖,也就是即使缓存系统完全不可用,也可以保证程序在响应速度和吞吐量降低的情况下,运行的正确性和数据的完整性。


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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

TMGM公司官网介绍

TMGM主要提供外汇、贵金属、原油、股指等CFD产品,客户可以根据个人的交易习惯选择其中一种或多种进行投资。具体来说,TMGM的金融产品包括但不限于货币对、黄金、原油、股票指数等。此外,TMGM还提供多种账户类型以满足不同客户的交易需求。 请…

error MSB8008: 指定的平台工具集(v143)未安装或无效。请确保选择受支持的 PlatformToolset 值解决办法

右击解决方案,选择属性 将工具集为143的修改为其他,如图 重新编译即可运行

DDC技术:AIGC网络的革命性解决方案

2023年,人工智能生成内容(AIGC)技术将蓬勃发展,其中ChatGPT作为一个典型案例,在文本生成、代码开发和诗歌创作等多个领域引起行业变革。DDC技术对改变网络格局具有创新和突破性意义,很大程度上提升了效率和…

Python 读取pdf文件

Python 实现读取pdf文件简单示例。 安装命令 需要安装操作pdf的三方类库,命令如下: pip install pdfminer3K 安装过程如下: 引入类库 需要引入很多的类库。 示例如下: import sys import importlib importlib.reload(sys)fr…

汽车零部件制造业MES系统解决方案

一、​汽车零部件行业现状 随着全球汽车产业不断升级,汽车零部件市场竞争日趋激烈,从上游的钢铁、塑料、橡胶等生产到下游的主机厂配套制造,均已成为全球各国汽车制造大佬战略目标调整的焦点,其意欲在汽车零部件行业快速开疆扩土&…

蓝牙BLE学习-GAP

1.概述 GAP层(Generic access profile-通用访问配置文件)。GAP是对LL层payload(有效数据包)如何进行解析的两种方式的一种,而且也是最简单的一种。GAP简单的对LL payload进行一些规范和定义,因此GAP能实现的…

Compose高级别API动画指南

前文讲了Compose中的低级别API动画,与之对应的,还有高级别API动画,同样也符合Material-Design规范。所有高级别动画 API 都是在低级别动画 API 的基础上构建而成,其对应关系如图: 接下来就对其高级别API逐个分析&…

【王道数据结构】【chapter5树与二叉树】【P159t12】

设一棵二叉树的结点结构为(LLINK,INFO,RLINK)&#xff0c;ROOT为指向该二叉树根结点的指针&#xff0c;p和q分别为指向该二叉树中任意两个节点的指针&#xff0c;试编写算法ANCESTOR(ROOT,p,q,r)&#xff0c;找到p和q的最近公共祖先结点r #include <iostream> #include &…

Linux第54步_根文件系统第1步_编译busybox并安装_然后添加“根文件系统”的库

学习编译busybox&#xff0c;并安装&#xff0c;然后添加“根文件系统”的库。有人说busybox构建根文件系统&#xff0c;只适合学习&#xff0c;不适合做项目。 1、了解ubuntu的根文件系统 根文件系统的目录名为“/”&#xff0c;就是一个斜杠。 1)、输入“cd /回车”&…

算法学习——LeetCode力扣二叉树篇7

算法学习——LeetCode力扣二叉树篇7 236. 二叉树的最近公共祖先 236. 二叉树的最近公共祖先 - 力扣&#xff08;LeetCode&#xff09; 描述 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。 百度百科中最近公共祖先的定义为&#xff1a;“对于有根树 T 的两个节点…

加速创新如何先从创意管理开始?

文章详细介绍了什么是创意管理以及它在组织中的重要性和最佳实践。创意管理是指在组织内捕捉、组织、评估和实施创意的过程。它通过建立一个结构化的系统&#xff0c;从员工、客户或其他利益相关者那里收集创意&#xff0c;并系统地审查和选择最有前景的创意进行进一步的开发或…

《区块链公链数据分析简易速速上手小册》第8章:实战案例研究(2024 最新版)

文章目录 8.1 案例分析&#xff1a;投资决策支持8.1.1 基础知识8.1.2 重点案例&#xff1a;股票市场趋势预测准备工作实现步骤步骤1: 加载和准备数据步骤2: 特征工程步骤3: 训练模型步骤4: 评估模型 结论 8.1.3 拓展案例 1&#xff1a;基于情感分析的投资策略准备工作实现步骤步…

【王道数据结构】【chapter5树与二叉树】【P159t14】

设有一棵满二叉树&#xff08;所有结点值均不同&#xff09;&#xff0c;已知其先序序列为pre&#xff0c;设计一个算法求其后序序列post #include <iostream> #include <stack> #include <queue> #include<string.h> typedef struct treenode{char da…

读十堂极简人工智能课笔记02_选对路径与犯错

1. 符号人工智能 1.1. 在符号处理中&#xff0c;单词被当成遵循一套规则、互相关联的符号 1.2. 符号人工智能让计算机能用单词来思考 1.3. 符号人工智能是最早、最成功的人工智能形式之一 1.4. 20世纪初的时候&#xff0c;伯特兰罗素、库尔特哥德尔和大卫希尔伯特等数学家就…

训练深度学习模型的过程

深度学习的训练过程是指通过大量的数据来调整神经网络的参数&#xff0c;以使其能够对输入数据进行准确的预测或分类. 训练神经网络的步骤 损失函数&#xff08;Loss Function&#xff09;是一个性能指标&#xff0c;反映神经网络生成接近期望值的值的程度。 损失函数直观上就…

书生浦语大模型实战营-课程笔记(1)

模型应用过程&#xff0c;大致还是了解的。和之前实习做CV项目的时候比起来&#xff0c;多了智能体这个环节。智能体是个啥&#xff1f; 类似上张图&#xff0c;智能体不太清楚。感觉是偏应用而不是模型的东西&#xff1f; 数据集类型很多&#xff0c;有文本/图片/视频。所以…

Vulnhub靶机:DC3

一、介绍 运行环境&#xff1a;Virtualbox 攻击机&#xff1a;kali&#xff08;10.0.2.15&#xff09; 靶机&#xff1a;DC3&#xff08;10.0.2.56&#xff09; 目标&#xff1a;获取靶机root权限和flag 靶机下载地址&#xff1a;https://www.vulnhub.com/entry/dc-32,312…

洛谷C++简单题小练习day11—字母转换,分可乐两个小程序

day11--字母转换--2.14 习题概述 题目描述 输入一个小写字母&#xff0c;输出其对应的大写字母。例如输入 q[回车] 时&#xff0c;会输出 Q。 代码部分 #include<bits/stdc.h> using namespace std; int main() { char n;cin>>n;cout<<char(n-32)<…

代码+视频基于R语言进行K折交叉验证

我们在建立数据模型后通常希望在外部数据验证模型的检验能力。然而当没有外部数据可以验证的时候&#xff0c;交叉验证也不失为一种方法。交叉验验证&#xff08;交叉验证&#xff0c;&#xff23;&#xff36;&#xff09;则是一种评估模型泛化能力的方法&#xff0c;广泛应用…

StarUML无法安装扩展的解决方案

StarUML无法安装扩展解决方案 版本&#xff1a;StarUML3.2.2 遇到问题 Unable to access the extension registry, Please try again later. 解决方案 第一步 https://docs.staruml.io/user-guide/managing-extensions#install-extension官网给了怎么手动安装扩展器的方法…