高并发下的分布式缓存 | Cache-Aside缓存模式

news2024/11/15 18:06:52

Cache-aside 模式的缓存操作

Cache-aside 模式,也叫旁路缓存模式,是一种常见的缓存使用方式。在这个模式下,应用程序可能同时需要同缓存和数据库进行数据交互,而缓存和数据库之间是没有直接联系的。这意味着,应用程序代码要负责处理数据的获取和存储,

一些应用程序使用“Read-Through”或“Write-Through”的缓存策略,其中缓存系统定义了更新或缓存失效的逻辑,并作为应用程序的透明接口。

如果缓存系统不提供这些功能,则应用程序代码需要负责管理缓存查找、在写操作时更新缓存,以及在缓存未命中时查询数据库。这就是 cache-aside 策略的作用所在:应用程序与缓存和数据库交互,而缓存与数据库完全没有交互。

Cache-aside 模式的读操作流程

在读取数据时,应用程序首先会去缓存中查看这个数据是否已经存在,如果数据存在于缓存中,这叫做缓存命中,则直接将缓存的数据返回给用户。

如果缓存中没有需要的数据,这叫做缓存未命中,这种情况下,应用程序需要从数据库中获取这个数据,从数据库中拿到数据后,应用程序还会将数据存入缓存,以便下次再需要这个数据时,可以直接从缓存里获取,而不需要再去查数据库。

Cache-aside 模式的写操作流程

现在,关键问题是:在 Cache-aside 模式中,我们如何执行写操作?

当你需要写入数据(添加、修改或删除)时,有两种常见的处理方式:

1. 写入数据库并使缓存失效

这种方法是先更新数据库然后将缓存中对应的数据删除(如果缓存中存在该数据)。因此,当后续需要再次读取相同的数据时,由于缓存里没有,应用程序将从数据库中查找数据并将其添加到缓存中。

可以看出:在更新数据库后,数据不会立即存储在缓存中,直到有下一次读取该数据的请求。这样,缓存总是按需更新,不用担心存放了无用的数据。

但这种方式也存在一些缺点:

  • 因为数据是在下一次读取时才更新到缓存中,所以第一次读取时可能会稍慢,导致一些延迟。如果读写比非常高,或者应用程序在数据库写入后频繁重新读取相同的数据,这种策略会很有用。

  • 存在增加数据库负载的可能性。例如,如果多个请求同时触发缓存未命中,可能导致数据库查询的激增。

这里有一个关键问题:我们在更新数据时是否可以先使缓存失效,然后再更新数据库?答案是尽量不要这么玩,特别是在高并发的场景下,下面看看这么做会有什么问题。

在高并发的场景下,如果我们在更新数据时采用先使缓存失效,再更新数据库,如果某个时刻,同时有一个读请求和一个更新请求操作同一条数据,更新请求刚好让这条数据在缓存失效,然后读请求读取时缓存未命中(因为数据已被更新请求从缓存中删除),就会从数据库中获取旧数据并添加到缓存中。更新请求继续将数据库中的这条数据更新,这导致缓存数据和数据库的数据不一致。

下面这张图很好的说明了这种现象。

2. 写入数据库并立即更新缓存

这种方式在更新数据库后,应用程序也会把最新的数据更新到缓存中。由于在数据库更新后缓存已更新为最新数据,因此后续的读取请求更有可能命中缓存,从而减少对数据库的访问。

然而,这种方式也会带来以下问题:增加写入延迟,因为数据需要同时写入缓存和数据库。不过,如果你的系统是读多写少(即大多数请求都是读取数据),这个额外的时间开销是可以接受的。

Cache-aside 模式的特点

Cache-aside 模式的优点

  1. 为应用程序代码提供了灵活性和控制力。开发人员可以自己根据业务场景决定哪些数据应该缓存,缓存多久,或者什么时候需要刷新缓存。

  2. Cache-aside模式能够抵御缓存层的故障。如果缓存系统出现故障,应用程序仍然可以从数据库中获取数据,不会因为缓存问题导致整个系统无法工作。

  3. 随着应用程序的增长以及处理更高流量所需资源的增加,可以添加更多的缓存服务器以分担负载。换句话说,在Cache-aside模式中,缓存层可以独立于数据库轻松扩展。

  4. 因为缓存和数据库是分离的,我们可以在缓存中使用与数据库不同的数据模型,例如据库中可能存储了完整的用户信息,但缓存中只存储了用户的ID和用户名,因为这些数据在前端展示中是最常用的。

  5. Cache-aside模式只会包含应用程序实际请求的数据,这样可以有效利用缓存空间,不会浪费存储。

  6. 使用混合策略(比如与 Write-Through 结合)可以确保缓存中数据和数据库中的数据是同步更新的,减少数据过时或不一致的风险。

Cache-aside 模式的缺点

  1. 由于应用程序需要自己管理缓存的操作,包括缓存失效、并发处理等,增加了开发的复杂性。如果处理不当,可能会出现错误或bug。

  2. 当数据更新后,缓存中的旧数据会被删除,这样下次读取时缓存会未命中(因为缓存中没有数据),从而需要从数据库中重新加载数据。如果频繁更新数据,会导致缓存未命中频繁发生,影响性能。

  3. 当使用Cache-aside与Write-Through结合时,写操作的延迟会很高,因为数据将同时更新到缓存和数据库中。因此,对于写密集型的工作负载来说,这种策略效率不高。另一方面,这样做可能导致缓存中存储了许多不必要的数据,或者缓存中的数据未必是最常用的。这会导致缓存效率低下,增加缓存未命中率。如何处理这种情况?需要深入思考和探索。

  4. 在实际操作中,由于缓存和数据库是分离的,缓存中的数据可能不会及时反映数据库中的变化,导致数据不一致的情况。因此,应用程序开发人员应使用适当的缓存淘汰策略来处理数据不一致问题。举一个例子:假设你成功更新了缓存,但数据库更新失败。因此,代码需要实现重试机制。在最坏的情况下,在重试失败期间,缓存中可能包含数据库中不存在的值。

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

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

相关文章

Java数据结构 | 二叉树基础及基本操作

二叉树 一、树型结构1.1 树的概念1.2 关于树的一些常用概念(很重要!!!)1.3 树的表示形式1.4 树的应用 二、二叉树2.1 二叉树的概念2.2 两种特殊的二叉树2.3 二叉树的性质2.4 二叉树的存储2.5 二叉树的基本操作2.5.1 代…

【前端可视化】 大屏可视化项目二 scale适配方案 g6流程图 更复杂的图表

项目介绍 第二个大屏可视化,整个项目利用scale进行按比例适配。 图表更加复杂,涉及到图表的叠加,mark,地图,g6流程图的能等 始终保持比例适配(本项目方案),始终满屏适配(项目一). echarts绘制较为复杂图表&#xff0…

C++:string类(auto+范围for,typeid)

目录 前言 auto typeid 范围for 使用方法 string类的模拟实现 默认构造函数 拷贝构造函数 swap 赋值重载 析构函数 迭代器iterator begin和end c_str clear size capacity []运算符重载 push_back reserve append 运算符重载 insert erase find npos…

postgresql 宝塔 连接不上,prisma

不太熟悉pgsql; 配置搞了半天; 一直连不上远程数据库; 后台经过探索发现需要以下配置 1. 端口放行; 5422 (pgsql的端口) 2.编辑 pg_hba.conf 文件最后新增一条,这样可以外部使用postgres超级管理员账号 host all all 0.0.0.0/0 md5 3. pris…

数据结构复杂度

文章目录 一. 数据结构前言1.1 数据结构1.2 算法 二. 算法效率2.1 时间复杂度2.1.1 T(N)函数式2.1.2 大O的渐进表示法 一. 数据结构前言 1.1 数据结构 什么是数据结构呢?打开一个人的主页,有很多视频,这是数据(杂乱无章&#xf…

了解k8s架构,搭建k8s集群

kubernetes 概述 Kubernetes 集群图例 安装控制节点 安装网络插件 安装 calico 安装计算节点 2、node 安装 查看集群状态 kubectl get nodes # 验证容器工作状态 [rootmaster ~]# kubectl -n kube-system get pods

【学习笔记】:Maven初级

一、Maven简介 1、为什么需要maven Maven是一个依赖管理工具,解决如下问题: 项目依赖jar包多jar包来源、版本问题jar包导入问题jar包之间的依赖Maven是一个构建工具: 脱离IDE环境的项目构建操作,需要专门的工具2、Maven介绍 https://maven.apache.org/what-is-maven.htm…

代码随想录算法训练营第44天|LeetCode 1143.最长公共子序列、1035.不相交的线、53. 最大子序和、392.判断子序列

1. LeetCode 1143.最长公共子序列 题目链接:https://leetcode.cn/problems/longest-common-subsequence/description/ 文章链接:https://programmercarl.com/1143.最长公共子序列.html 视频链接:https://www.bilibili.com/video/BV1ye4y1L7CQ…

苹果离线打包机配置和打包

1、虚拟机安装 macOS虚拟机安装全过程(VMware)-腾讯云开发者社区-腾讯云 给 windows 虚拟机装个 mac 雪之梦 1、安装苹果镜像 去网上下载,打包机的镜像要和自己mac电脑上的保持一致。 同时打包机的用户名也需要和自己的mac保持一致。 2、…

云原生专题-k8s基础系列-k8s-namespaces详解

获取所有的pod实例: k8s中,命名空间(Namespace)提供一种机制,将同一集群中的资源划分为相互隔离的组。同一命名空间内的资源名称要唯一,命名空间是用来隔离资源的,不隔离网络。 https://kubern…

Kafka 实战使用、单机搭建、集群搭建、Kraft集群搭建

文章目录 实验环境单机服务启动停止服务简单收发消息其他消费模式理解Kakfa的消息传递机制 集群服务为什么要使用集群部署Zookeeper集群部署Kafka集群理解服务端的Topic、Partition和Broker总结 Kraft集群相关概念 实验环境 准备三台虚拟机 三台机器均预装CentOS7 操作系统。…

探索Transformer中的多头注意力机制:如何利用GPU并发

什么是多头注意力机制? 首先,什么是多头注意力机制?简单来说,它是Transformer模型的核心组件之一。它通过并行计算多个注意力头(attention heads),使模型能够从不同的表示子空间中捕捉不同的特…

Oracle服务器windows操作系统升级出现计算机名称改变导致数据库无法正常连接

1.数据库莫名奇妙无法正常连接,经排查是主机名称改变,导致oracle无法正常运行 如何查看ORACLE主机名称及路径:需要修改 listener 和 tnsnames的配置的主机名 2.修改tnsnames配置的主机名称,HOST主机名称 3.修改listener中的主机…

【案例36】Apache未指向新的openssl

客户发现apache报openssl相关漏洞,于是升级了操作系统的openssl组件。但再次漏扫发现相关版本依旧显示openssl的版本为:1.0.2k。怀疑升级的有问题。 问题分析 查看libssl.so.10指向的是/lib64.so.10 ldd mod_ssl.so libssl.so.10指向的是openssl1.0.2k…

【实际案例】服务器宕机情况分析及处理建议

了解银河麒麟操作系统更多全新产品,请点击访问麒麟软件产品专区:https://product.kylinos.cn 服务器环境以及配置 物理机/虚拟机/云/容器 物理机 外网/私有网络/无网络 私有网络 处理器: Kunpeng 920 内存: 4 TiB BIOS版…

【JVM基础18】——实践-Java内存泄漏排查思路?

目录 1- 引言:2- ⭐核心:2-1 排查思路2-2 步骤1:获取堆内存快照 dump2-3 步骤2、3:使用 VisualVM 打开 dump文件 3- 小结:3-1 Java内存泄漏排查思路? 1- 引言: 首先得明确哪里会产生内存泄漏的…

Solidworks API利用C# 实现物体的运动与碰撞检测

详情见github连接 SolidWorks-API-Collision-Detection Use SolidWorks API to MovePart and Collision Detection 利用solidworks的API来移动控件物体以及进行碰撞检测 visual studio 2022 利用Nuget 安装这些库 打开solidworks 可以看到有两个控件 部件运动 使用封装的函…

嵌入式初学-C语言-十七

#接嵌入式初学-C语言-十六# 函数的递归调用 含义: 在一个函数中直接或者间接调用了函数本身,称之为函数的递归调用 // 直接调用a()->a(); // 间接调用a()->b()->a();a()->b()->..->a();递归调用的本质: 本是是一种循环…

深入理解Spring的三级缓存机制

个人名片 🎓作者简介:java领域优质创作者 🌐个人主页:码农阿豪 📞工作室:新空间代码工作室(提供各种软件服务) 💌个人邮箱:[2435024119qq.com] &#x1f4f1…

Ubuntu(20.04 LTS)更换镜像源

此换镜像源方法只适用x86_64架构的系统,其他架构的系统参考ubuntu-ports的方法 1、备份文件 sudo mv /etc/apt/sources.list /etc/apt/sources.list.bk2、创建新文件 sudo vi /etc/apt/sources.list根据自己系统版本选择下面对应的镜像源添加到新文件中&#xf…