【Redis】如何保证缓存和数据库的一致性

news2024/11/15 23:47:51

目录

  • 背景
    • 问题
    • 思路
  • 三个经典的缓存模式
    • Cache-Aside
      • 读缓存
      • 写缓存
        • 为什么是删除旧缓存而不是更新旧缓存?
        • 为什么不先删除旧的缓存,然后再更新数据库?
      • 延迟双删
      • 如何确保原子性
    • Read-Through/Write-Through
      • Read-Through
      • Write-Through
    • Write Behind
  • 方案抉择

背景

  • 我们在日常开发中,为了提高数据响应速度,可能会将一些热点数据保存在缓存中,这样就不用每次都去数据库中查询了,可以有效提高服务端的响应速度,那么目前我们最常使用的缓存就是 Redis 了。

  • 以电商项目为例,主要有三个主要环节:

    1. 订单数据和支付流水数据:这两块数据对实时性和精确性要求很高,所以一般是不需要添加缓存的,直接操作数据库即可。
    2. 用户相关数据:这些数据和用户相关,具有读多写少的特征,所以我们使用 redis 进行缓存。
    3. 支付配置信息:这些数据和用户无关,具有数据量小,频繁读,几乎不修改的特征,所以我们使用本地内存进行缓存。
  • 选中合适的数据存入 Redis 之后,接下来,每当要读取数据的时候,就先去 Redis 中看看有没有,

    • 如果有就直接返回;
    • 如果没有,则去数据库中读取,并且将从数据库中读取到的数据缓存到 Redis 中,

问题

大致上就是上面这样一个流程,读取数据的这个流程实际上是比较清晰也比较简单的,然而,当数据存入缓存之后,如果需要更新的话,往往会来带另外的问题:

  1. 当有数据需要更新的时候,先更新缓存还是先更新数据库?
  2. 如何确保更新缓存和更新数据库这两个操作的原子性?
  3. 更新缓存的时候该怎么更新?修改还是删除?

思路

正常来说,我们有四种方案:

  1. 先更新缓存,再更新数据库。
  2. 先更新数据库,再更新缓存。
  3. 先淘汰缓存,再更新数据库。
  4. 先更新数据库,再淘汰缓存。

三个经典的缓存模式

  1. Cache-Aside
  2. Read-Through/Write through
  3. Write Behind

Cache-Aside

  • Cache-Aside,中文也叫旁路缓存模式,如果我们能够在项目中采用 Cache-Aside,那么就能够尽可能的解决缓存与数据库数据不一致的问题,注意是尽可能的解决,并无法做到绝对解决。
  • Cache-Aside 又分为读缓存和写缓存两种情况,我们分别来看。

读缓存

在这里插入图片描述

  • 其实对于读缓存的流程而言,一般没什么数据影响,有影响的主要是写流程

写缓存

  • 流程:写缓存——更新数据——删除旧缓存
  • 两个问题:
    • 为什么是删除旧缓存而不是更新旧缓存?
    • 为什么不先删除旧的缓存,然后再更新数据库?
为什么是删除旧缓存而不是更新旧缓存?
  • 更新缓存,说着容易做起来并不容易。很多时候我们更新缓存并不是简简单单更新一个 Bean。很多时候,我们缓存的都是一些复杂操作或者计算(例如大量联表操作、一些分组计算)的结果,如果不加缓存,不但无法满足高并发量,同时也会给 MySQL 数据库带来巨大的负担。那么对于这样的缓存,更新起来实际上并不容易,此时选择删除缓存效果会更好一些。
  • 对于一些写频繁的应用,如果按照更新缓存->更新数据库的模式来,比较浪费性能,因为首先写缓存很麻烦,其次每次都要写缓存,但是可能写了十次,只读了一次,读的时候读到的缓存数据是第十次的,前面九次写缓存都是无效的,对于这种情况不如采取先写数据库再删除缓存的策略。
  • 在多线程环境下,这样的更新策略还有可能会导致数据逻辑错误,来看如下一张流程图:
    在这里插入图片描述

当有两个并发的线程 A 和 B:

  1. 首先 A 线程更新了数据库。
  2. 接下来 B 线程更新了数据库。
  3. 由于网络等原因,B 线程先更新了缓存。
  4. A 线程更新了缓存。

那么此时,缓存中保存的数据就是不正确的,而如果采用了删除缓存的方式,就不会发生这种问题了。

为什么不先删除旧的缓存,然后再更新数据库?
  • 同样考虑到并发请求,假设我们先删除旧的缓存,然后再更新数据库,那么就有可能出现如下这种情况:
    在这里插入图片描述

线程A 和 B,其中 A 写数据,B 读数据,具体流程如下:

  1. A 线程首先删除缓存。
  2. B 线程读取缓存,发现缓存中没有数据。
  3. B 线程读取数据库。
  4. B 线程将从数据库中读取到的数据写入缓存。
  5. A 线程更新数据库。

一套操作下来,我们发现数据库和缓存中的数据不一致了!所以,在 Cache-Aside 中是先更新数据库,再删除缓存。

延迟双删

  • 其实无论是先更新数据库再删除缓存,还是先删除缓存再更新数据库,在并发环境下都有可能存在问题:

    • 假设有 A、B 两个并发请求:
      • 先更新数据库再删除缓存:当请求 A 更新数据库之后,还未来得及进行缓存清除,此时请求 B 查询到并使用了 Cache 中的旧数据。
      • 先删除缓存再更新数据库:当请求 A 执行清除缓存后,还未进行数据库更新,此时请求 B 进行查询,查到了旧数据并写入了 Cache。
  • 前面已经分析过了,尽量先操作数据库再操作缓存,但是即使这样也还是有可能存在问题,解决问题的办法就是延迟双删。

  • 延迟双删的处理流程:先执行缓存清除操作,再执行数据库更新操作,延迟 N 秒之后再执行一次缓存清除操作,这样就不用担心缓存中的数据和数据库中的数据不一致了。

  • 那么这个延迟 N 秒,N 是多大比较合适呢?一般来说,N 要大于一次写操作的时间,如果延迟时间小于写入缓存的时间,会导致请求 A 已经延迟清除了缓存,但是此时请求 B 缓存还未写入,具体是多少,就要结合自己的业务来统计这个数值了。

如何确保原子性

  • 其实说到底更新数据库和删除缓存毕竟不是一个原子操作,要是数据库更新完毕后,删除缓存失败了咋办?
  • 对于这种情况,一种常见的解决方案就是使用消息中间件来实现删除的重试。众所周知,MQ 一般都自带消费失败重试的机制,当我们要删除缓存的时候,就往 MQ 中扔一条消息,缓存服务读取该消息并尝试删除缓存,删除失败了就会自动重试。

Read-Through/Write-Through

  • Read-Through/Write-Through(读写全程)是一种计算机缓存策略,用于管理内存和磁盘之间的数据传输。

  • 在这种策略中,当计算机需要从磁盘读取数据时,它会首先检查缓存中是否存在该数据。

    • 如果缓存中有数据,就直接从缓存读取,这称为“读取全程”。
    • 如果缓存中没有数据,计算机会从磁盘读取数据,并将数据复制到缓存中,这称为“写入全程”。
  • 在写入全程过程中,当计算机更新缓存中的数据时,它会同时将数据写入磁盘,以保持缓存和磁盘中数据的一致性。这样可以确保在缓存中的数据在发生故障时,仍然能够从磁盘中恢复。

  • Read-Through/Write-Through策略的优点是可以确保数据的实时一致性,并且在发生故障时能够快速恢复。

  • 然而,由于每次读取操作都要检查缓存,读取性能可能会受到一定影响。

Read-Through

在这里插入图片描述

  • Read-Through 是一种类似于 Cache-Aside 的缓存方法,区别在于
    • 在 Cache-Aside 中,由应用程序决定去读取缓存还是读取数据库,这样就会导致应用程序中出现了很多业务无关的代码;
    • 而在 Read-Through 中,相当于多出来了一个中间层 Cache Middleware,由它去读取缓存或者数据库,应用层的代码得到了简化,
  • 和 Cache-Aside 相比,其实就相当于是多了一个缓存中间件(处理判断缓存并设置缓存的操作),这样我们在应用程序中就只需要正常的读写数据就行了,并不用管底层的具体逻辑,相当于把缓存相关的代码从应用程序中剥离出来了,应用程序只需要专注于业务就行了。

Write-Through

  • Write-Through 其实也是差不多,所有的操作都交给缓存中间件来完成,应用程序中就是一句简单的更新就行了
    在这里插入图片描述

  • 在 Write-Through 策略中,所有的写操作都经过 缓存中间件,每次写入时,Cache Middleware 会将数据存储在 DB 和 Cache 中,这两个操作发生在一个事务中,因此,只有两个都写入成功,一切才会成功。

  • 这种写数据的优势在于,应用程序只与 缓存中间件 对话,所以它的代码更加干净和简单。

Write Behind

  • Write-Behind 缓存策略类似于 Write-Through 缓存,应用程序仅与 缓存中间件 通信,缓存中间件 会预留一个与应用程序通信的接口。
  • Write-Behind 与 Write-Through 最大的区别在于,前者是数据首先写入缓存,一段时间后(或通过其他触发器)再将数据写入 Database,并且这里涉及到的写入是一个异步操作。
    • 这种方式下,Cache 和 DB 数据的一致性不强,对一致性要求高的系统要谨慎使用
    • 如果有人在数据尚未写入数据源的情况下直接从数据源获取数据,则可能导致获取过期数据
    • 不过对于频繁写入的场景,这个其实非常适用。
  • 将数据写入 DB 可以通过多种方式完成:
    • 一种是收集所有写入操作,然后在某个时间点(例如,当 DB 负载较低时)对数据源进行批量写入。
    • 另一种方法是将写入合并成更小的批次,例如每次收集五个写入操作,然后对数据源进行批量写入。

流程图如下
在这里插入图片描述

方案抉择

在选择具体方式来保证缓存和数据库的一致性时,可以考虑以下几个因素:

  1. 数据一致性要求:首先,明确应用对数据一致性的要求。如果数据一致性是绝对必要且不可容忍任何差异,那么使用事务是最可靠的选择。如果数据一致性要求较低,可以考虑使用缓存更新策略或消息队列。

  2. 系统性能需求:考虑应用的性能需求。事务可能会对性能产生较大的影响,因为它需要加锁、提交和回滚等操作。如果应用对性能有较高的要求,可以选择使用缓存更新策略或消息队列,并对缓存的更新进行优化。缓存更新策略可以在写入数据库之前更新缓存,减少数据库访问次数。

  3. 并发控制:在多线程或分布式环境下,需要考虑并发控制的问题。事务提供了强大的并发控制机制,但也会带来性能开销。如果并发操作较少或可以容忍一定程度的冲突,可以使用缓存更新策略或消息队列。

  4. 可靠性和容错性:考虑可靠性和容错性。事务通常提供较高的可靠性和容错性,因为它们可以回滚操作以确保数据一致性。缓存更新策略和消息队列需要额外的措施来处理故障或消息丢失的情况,例如使用缓存失效机制或消息重试机制等。

  5. 开发和维护复杂性:最后,考虑实现和维护所需的复杂性。事务管理着复杂的并发控制和回滚机制,可能需要更多的代码和配置。缓存更新策略和消息队列可能需要额外的逻辑和配置来确保一致性。

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

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

相关文章

LINUX桌面运维----第一天

一、Linux的特点: (1)与UNIX兼容 (2)自由软件,源码公开 (3)性能高,安全性强 (4)便于定制和再开发 (5)相互之间操作性…

某同盾验证码

⚠️前言⚠️ 本文仅用于学术交流。 学习探讨逆向知识,欢迎私信共享学习心得。 如有侵权,联系博主删除。 请勿商用,否则后果自负。 网址 aHR0cHM6Ly9zZWMueGlhb2R1bi5jb20vb25saW5lRXhwZXJpZW5jZS9zbGlkaW5nUHV6emxl 1. 先整体分析一下接…

地级市绿色创新及碳排放与环境规划数据(2000-2021年)

数据简介:分享各个城市对于碳排放的降低做出了哪些共享。该数据是地级市2000-2021年间由绿色创新、碳排放与环境规制数据构成的能源与环境研究数据大合集,并对其进行可视化处理,供大家研究使用。当今我国大力推进生态文明建设、美丽中国建设等…

【Python系列】FastAPI 中的路径参数和非路径参数解析问题

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

PDF秒变翻页式电子画册

​在当今数字化时代,将PDF文档转换成翻页式电子画册是一种提升作品展示效果和传播效率的有效方式。以下是将PDF秒变翻页式电子画册的攻略,帮助您轻松掌握数字创作技巧。 首先,选择一个合适的制作工具是关键。目前市场上有多种在线平台和软件可…

元素旋转?一个vue指令搞定

说在前面 🎈鼠标控制元素旋转功能大家应该都不陌生了吧,今天我们一起来看看怎么编写一个vue指令来实现元素旋转功能吧! 效果展示 体验地址 http://jyeontu.xyz/jvuewheel/#/JRotateView 实现思路 1、自定义指令对象 export default {inse…

选择门店收银系统要考虑哪些方面?美业系统Java源码分享私

开店前的一个重要事件就是选择门店收银软件/系统,尤其是针对美容、医美等美业门店,一个优秀专业的系统十分重要,它必须贴合门店的经营需求,提供更全面、便捷、高效的管理功能,帮助提升门店的服务质量和经营效益。 以下…

品牌策划背后的秘密:我为何对此工作情有独钟?

你是否曾有过一个梦想,一份热爱,让你毫不犹豫地投身于一个行业? 我就是这样一个对品牌策划充满热情的人。 从选择职业到现在,我一直在广告行业里“混迹”,一路走来,也见证了许多对品牌策划一知半解的求职…

CPsyCoun:心理咨询多轮对话自动构建及评估方法

CPsyCoun: A Report-based Multi-turn Dialogue Reconstruction and Evaluation Framework for Chinese Psychological Counseling 在大模型应用于心理咨询领域,目前开源的项目有: https://github.com/SmartFlowAI/EmoLLM (集合,…

mp4转换成mp3怎么转?教你几种值得收藏的转换方法!

mp4转换成mp3怎么转?MP4,这一深入人心的数字多媒体容器格式,无疑在当今数字世界中占据了一席之地,那么,它究竟有何过人之处呢?首先,MP4的跨平台兼容性是其一大亮点,不论是在Windows的…

(一)、配置服务器的多个网卡路由,访问多个不同网络段

一、现场网络关系说明 有这么一个需要,服务器有三个网口,网口一需要访问外网,网口二需要访问内网1,网口2需要访问内网2。需要配置路由来满足该网络访问需要。 图1 现场网络关系 二、配置教程 步骤1: a、命令行输入…

A股羊群效应CSSD CSAD数据与Stata代码数据(2000-2023)

数据来源 参考马丽老师(2016)的做法,股价数据来源于东方财富网,采用上证180指数及构成上证180指数样本股日收盘价数据作为样本。上证180指数自2002年7月1日起正式发布,其样本股是在所有 A 股股票中抽取最具市场代表性…

react-native在IOS上集成百度地图详解

export default class BaiDuMapTest extends Component { render() { return ( ); } } const styles StyleSheet.create({ container: { flex: 1, justifyContent: ‘center’, alignItems: ‘center’, backgroundColor: ‘#F5FCFF’, }, welcome: { fontSize:…

若依-前后端分离项目学习

第一天(6.24) 具体参考视频 b站 楠哥教你学Java 【【开源项目学习】若依前后端分离版,通俗易懂,快速上手】 https://www.bilibili.com/video/BV1HT4y1d7oA/?share_sourcecopy_web&vd_sourcecd9334b72b49da3614a4257…

公司logo设计大全怎么找?直接帮你设计logo

公司logo设计大全怎么找?在品牌塑造的过程中,Logo无疑是至关重要的一环。一个优秀的Logo不仅能够有效传达公司的核心理念和品牌形象,还能在消费者心中留下深刻的印象。然而,对于许多初创公司或小型企业来说,制作出适合…

【稀疏三维重建】Flash3D:单张图像重建场景的GaussianSplitting

项目主页:https://www.robots.ox.ac.uk/~vgg/research/flash3d/ 来源:牛津、澳大利亚国立 文章目录 摘要1.引言2.相关工作3.方法3.1 背景:从单个图像中重建场景3.2 单目前向的多个高斯 4.实验4.14.2 跨域新视角合成4.3 域内新视图合成 摘要 F…

OpenBayes 教程上新 | 5 秒完成高考作文,Llama 3-Chinese-Chat Demo 上线!

Llama 3 自发布以来备受关注,并被誉为「迄今为止最好的开源大模型」,但 Llama 3 在支持中文方面仍然存在一些问题,比如在使用中文提问时,经常发生英文回复或者中英混合回复的情况,非常不方便。 使用中文向 Llama 3-8B-…

web应用-Nginx学习笔记01-应用的组成结构,配置项的分类和理解

参考来源: 在线文档:Nginx开发从入门到精通,https://docs.pythontab.com/nginx/nginx-book/ 极客专栏:nginx核心100讲,作者:陶辉 书籍:《深入理解Nginx:模块开发与架构解析》第二章 参考来源&a…

ONLYOFFICE 桌面编辑器 8.1

ONLYOFFICE 桌面编辑器 8.1 ONLYOFFICE 简介一、轻松编辑器 PDF 文件二、用幻灯片版式快速修改幻灯片三、无缝切换文档编辑、审阅和查看模式四、**改进从右至左语言的支持 & 新的本地化选项**五、隐藏“连接到云”板块六、在演示文稿中播放视频和音频文件七、版本 8.1&…

AI视频改字系统+五端兼容+卡密兑换+内置素材,系统搭建部署

目录 前言: 一、AI视频改字系统是什么 二、AI视频改字系统的功能 三、总结 前言: AI视频改字是利用套模板的原理,对短视频的模板进行更改,从而生成新的短视频。当然这个AI短视频改字系统都是有素材的,不用自己上传…