缓存的思考与总结

news2024/11/15 4:26:59

缓存的思考与总结

    • 什么是缓存
    • 缓存命中率
    • 数据一致性
      • 旁路模式 Cache aside
      • 双写模式
        • 直写模式 write through
        • 异步写 Write Behind
      • 旁路和双写
    • 案例

新技术或中间的引入,一定是解决了亟待解决的问题或是显著提升了系统性能,并且这种改变所带来的增幅,可以让我们忽略引入新技术所带来的系统复杂性等负面影响。好比是CAP理论中对C和A的权衡。

什么是缓存

从内存中读取数据,从文件系统通过IO读取磁盘数据,两者在时间上存在较大差异,毫无疑问,从内存中读取数据相较于磁盘会更快,于是便有了缓存,很典型的以空间换时间的运用。
如果数据都放在内存中自然是最好不过,也就没有缓存这么一说了。但目前来看,内存依旧属于紧张资源,需要有选择的将数据(读多写少)放入内存作为缓存来使用。
在缓存方面,大多数问题都可以归结到以下两个方面去讨论:

  • 缓存命中率
  • 数据一致性

缓存命中率

读取数据时,从缓存中是否读取到了数据。系统在设计添加缓存层时,一方面提升系统响应速度,另一方面也能拦截部分查询请求从而分担数据库压力。对于一些我们希望在缓存层被拦截的请求,如果缓存没有命中,那么缓存层将失去意义。比如常说的几个概念:

  • 缓存穿透:查询缓存中不存在的键(非法的key),请求到达DB层
  • 缓存击穿:查询缓存中不存在的键(尚未构建缓存),请求到达DB层
  • 缓存雪崩:缓存大面积失效,请求到达DB层

你会发现,上述都是在描述一个概念:缓存命中率。只不过是不同场景下缓存未命中的情况:
我们希望请求在缓存层被拦截,但由于未命中缓存导致请求到达DB层。所以上述场景的解决方案也都是围绕着:如何提高缓存命中率 来展开的。
缓存击穿还涉及并发场景下缓存重建问题,需要通过加锁来避免。

数据一致性

有了缓存,就意味着有了两份数据,DB层一份,内存一份,那就必然会涉及数据一致性的问题,并且由于是两份数据,数据同步期间必然会存在不一致情况,除非将数据的修改和缓存的修改作为一个原子操作(单体应用)。所以,不能仅仅要设计数据如何读取提高命中率,还要设计数据更新时的策略。也就是说,加入缓存层后,要从读写两方面进行约束,形成闭环,这样才能保证缓存和DB层的数据一致性。
常见的场景必然有成熟的解决方案,对于缓存的数据一致性问题,常见的设计有以下几种:

  • 旁路模式
  • 直写模式
  • 异步写模式

旁路模式 Cache aside

读取时先从缓存中读取数据。如果缓存中没有数据,则从数据库中读取,并将数据写入缓存。更新数据时,先更新数据库,然后再将缓存中的数据失效。

旁路模式中,并发场景下,先更新数据后再删除缓存先删除缓存再更新数据两者有所不同,即使双删策略保证第二次删除后读取到的都是新数据。
推荐使用先更新数据库再删除缓存的做法,优点是不存在使用旧数据重建缓存的情况,且数据不一致的窗口期不依赖于第二次删除,也就是说:更新数据后删除缓存前,并发读会读到旧缓存,但更新数据且删除缓存后,不一致窗口期便结束了。假如设定的第二次删除的延时是1小时,先更新数据库再删除缓存这种方式会在删除缓存后结束数据不一致;但先删除缓存再更新数据的方式则强依赖与第二次删除,会在1小时后才结束数据不一致。

双写模式

顾名思义,既写数据库,又写缓存。包括直写和异步写(严格的双写是指一份数据同时写入两种存储介质,这里的异步写归结到双写模式下便于记忆)

直写模式 write through

读取时先从缓存中读取数据,在写入数据时,数据同时写入缓存和数据库

异步写 Write Behind

写入数据时,数据只更新缓存,并异步批量刷新到数据库中

旁路和双写

为了方便理解和区分旁路和双写模式,最简单的区分就是:
旁路模式中,缓存更新(失效重建)是被动的,由后续的读操作进行缓存重建;而双写模式则是主动更新缓存

旁路模式和双写模式是保证缓存和DB数据一致性的常用做法。分布式系统中也存在一些在旁路和双写基础上进行改进增强的设计,比如旁路模式+TTL过期时间,双写+补偿机制等,用来处理缓存操作失败时的场景,感兴趣的可以继续研究。

案例

写这篇偏总结性的文章,起因是之前写的一个IDEA插件 ,在第一版设计的时候,考虑到之后插件记录的数据增多,于是通过代理模式预留了扩展。
在这里插入图片描述
这里通过代理模式添加缓存层,在代理对象中统一进行缓存的处理。
在这里插入图片描述
由于插件开发是单体应用且不考虑多线程场景(多编辑器同时操作一个源文件时,会提示并拒绝),所以这里我们使用旁路模式实现最简单的LRU缓存。具体怎么做呢?

  1. 读操作优先读缓存,缓存没有再读DB(这里是持久化文件)
  2. 数据一旦发生修改,例如修改了高亮记录中的笔记内容,则失效缓存,等待下一次读取时重新构建缓存即可。
    但是有个问题:这里使用的缓存key和value,key是源码文件名称,value是该文件所有的高亮笔记。这里缓存的粒度很大,如果每次修改一条高亮笔记就重建整个源码文件的数据,不是很合理。所以还是双写模式更适合,避免牵一发动全身。每次更新笔记,只更新缓存中笔记列表里面相同ID的缓存记录即可。

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

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

相关文章

Mysql删库跑路,如何恢复数据?

问题 删库跑路,数据还能恢复吗? 我们经常听说某某被领导训斥了,对领导心生痛恨,然后登录 Mysql 删库跑路。对于闲聊中经常听说过的一个段子,在现实生活中是否真的发生过,如果发生了,我们该如何解…

基于单片机的智能小车的开发与设计

摘要:本文论述了基于 STC89C52 单片机的智能小车的开发与设计过程。该设计采用单片机、电机驱动及光电循迹等技术,保证小车在无人管理状态下,能按照预先设定的线路实现自动循迹功能。在电路结构设计中力求方便,可操作,…

go webapi上传文件

一、导入依赖 import "net/http" 我这里用到了Guid所以安装依赖 go get github.com/google/uuid 二、main.go package mainimport ("fmt""github.com/jmoiron/sqlx""github.com/tealeg/xlsx""log""path/filepath&q…

七彩云南文化旅游网站设计与实现

摘 要 传统办法管理信息首先需要花费的时间比较多,其次数据出错率比较高,而且对错误的数据进行更改也比较困难,最后,检索数据费事费力。因此,在计算机上安装七彩云南文化旅游网站软件来发挥其高效地信息处理的作用&am…

解决RabbitMQ设置x-max-length队列最大长度后不进入死信队列

解决RabbitMQ设置x-max-length队列最大长度后不进入死信队列 问题发现问题解决方法一:只监听死信队列,在死信队列里面处理业务逻辑方法二:修改预取值 问题发现 最近再学习RabbitMQ过程中,看到关于死信队列内容: 来自队…

计算机组成原理——存储系统

计算机组成原理——存储系统 存储器层次结构 存储器层次结构如下: 寄存器(CPU)Cache(高速缓冲存储器)主存磁盘磁带、光盘等 按照上述层次结构,自下而上速度依次增快、容量相对依次渐小、造价越来越高昂…

OpenHarmony(鸿蒙南向开发)——小型系统内核(LiteOS-A)【文件系统】上

往期知识点记录: 鸿蒙(HarmonyOS)应用层开发(北向)知识点汇总 鸿蒙(OpenHarmony)南向开发保姆级知识点汇总~ 子系统开发内核 轻量系统内核(LiteOS-M) 轻量系统内核&#…

锂电池基础知识

1. 电池的发展史 电池是将化学能转变为电能的装置,通过电池内部的化学反应向外部提供直流电能 1800年Vote伏打电堆 1835年英国Daniel丹尼尔电池 1859年法国Plante铅酸蓄电池 1866年法国Leclanche锌锰电池 1899年瑞典Jungner镍镉电池 1950年Urry碱性电池 1990年索尼…

鸿蒙OpenHarmony【轻量系统内核扩展组件(C++支持)】子系统开发

C支持 基本概念 C作为目前使用最广泛的编程语言之一,支持类、封装、重载等特性,是在C语言基础上开发的一种面向对象的编程语言。 运行机制 C代码的识别主要由编译器支持,系统主要对全局对象进行构造函数调用,进行初始化操作。…

【漏洞复现】用友 NC-Cloud queryStaffByName Sql注入漏洞

免责声明: 本文内容旨在提供有关特定漏洞或安全漏洞的信息,以帮助用户更好地了解可能存在的风险。公布此类信息的目的在于促进网络安全意识和技术进步,并非出于任何恶意目的。阅读者应该明白,在利用本文提到的漏洞信息或进行相关测…

智能农业系统——作物生长模型

橙蜂智能公司致力于提供先进的人工智能和物联网解决方案,帮助企业优化运营并实现技术潜能。公司主要服务包括AI数字人、AI翻译、AI知识库、大模型服务等。其核心价值观为创新、客户至上、质量、合作和可持续发展。 橙蜂智农的智慧农业产品涵盖了多方面的功能&#x…

windows 驱动实例分析系列-COM驱动案例讲解

COM也被称之为串口,这是一种非常简单的通讯接口,这种结构简单的接口被广泛的应用在开发中,几乎所有系统都能支持这种通讯接口,它有RS232和RS485等分支,但一般我们都会使用RS232作为常见的串口,因为它足够简单和高效。 几乎所有的开发板,都会提供用于烧录、调试、日志的…

《Pyramid Vision Transformer》论文笔记

原文笔记 What 为了解决VIT在视觉任务上的局限性并且探究Transformer模型在视觉任务上的应用,这项工作提出了一种纯 Transformer 主干,称为 Pyramid Vision Transformer (PVT),它可以作为 CNN 主干在许多下游任务中的替代方案,包…

【人工智能】Linux系统Mamba安装流程

在编译安装 mamba 之前,你需要确保已安装正常的PyTorch环境。 # 安装必要的系统依赖 sudo apt update sudo apt install build-essential # 安装mamba依赖 pip install packaging wheel # 克隆仓库 git clone https://github.com/Dao-AILab/causal-conv1d.git git …

【二等奖论文】2024年华为杯研赛D题成品论文(后续会更新)

您的点赞收藏是我继续更新的最大动力! 一定要点击如下的卡片,那是获取资料的入口! 点击链接获取【2024华为杯研赛资料汇总】: https://qm.qq.com/q/jTIeGzwkSchttps://qm.qq.com/q/jTIeGzwkSc 题 目: 大数据驱动的…

fastadmin 根据选择数据来传参给selectpage输入框

文章目录 js代码php代码:完结 js代码 $(document).on(change,#table .bs-checkbox [type"checkbox"],function(){let url$(#chuancan).attr(data-url)urlurl.split(?)[0]let idsTable.api.selectedids(table)if(ids.length){let u_id[]ids.forEach(eleme…

torch.embedding 报错 IndexError: index out of range in self

文章目录 1. 报错2. 原因3. 解决方法 1. 报错 torch.embedding 报错: IndexError: index out of range in self2. 原因 首先看下正常情况: import torch import torch.nn.functional as Finputs torch.tensor([[1, 2, 4, 5], [4, 3, 2, 9]]) embedd…

【C++ Primer Plus习题】17.3

大家好,这里是国中之林! ❥前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。有兴趣的可以点点进去看看← 问题: 解答: #include <iostream> #include <fstream> using namesp…

PHP、Java等其他语言转Go时选择GoFly快速快速开发框架指南

概要 经过一年多的发展GoFly快速开发框架已被一千多家科技企业或开发者用于项目开发&#xff0c;它的简单易学得到其他语言转Go首选框架。且企业版的发展为GoFly社区提供资金&#xff0c;这使得GoFly快速框架得到良好的发展&#xff0c;GoFly技术团队加大投入反哺科技企业和开…

数据结构之搜索二叉树

目录 一、什么是搜索二叉树 基本概念 特点 注意事项 二、搜索二叉树的C实现 2.0 构造与析构 2.1 插入 2.2 查找 2.3 删除 2.3.1 无牵无挂型 2.3.2 独生子女型 2.3.3 儿女双全型 三、搜索二叉树的应用 3.1 key搜索 3.2 key/value搜索 一、什么是搜索二叉树 搜索二…