03_缓存双写一致性

03——缓存双写一致性

一、缓存双写一致性

  1. 如果redis中有数据,需要和数据库中的值相同
  2. 如果redis中无数据,数据库中的值要是最新值,且准备回写redis

缓存按照操作来分,可以分为两种:

  1. 只读缓存

  2. 读写缓存

    1. 同步直写操作(及时生效)

      写数据库后,也同步写redis缓存,缓存和数据库中的数据一致

      对于读写缓存来说,要想保证缓存和数据库中的数据一致,就要采用同步直写策略

    2. 异步缓写策略

      正常业务中,mysql数据变动了,但是可以在业务上允许出现一定时间后才作用与redis(仓库、物流)

      异常情况出现了,不得不将失败的动作重新修补,有可能需要借助kafka或者其他MQ等消息中间件,实现重试重写

双检加锁策略:当多个线程同时去查询数据库的某一条数据时,可以在第一个查询数据的请求上使用一个互斥锁。其他线程获取锁失败,就会阻塞。第一个线程查询完毕,并将数据回写redis后,其他线程直接从redis中获取数据。以此来减轻数据库的压力。

二、数据库和缓存一致性的几种更新策略

目标:数据最终一致性

给缓存设置过期时间,定期清理缓存并回写,是保证最终一致性的解决方案。

我们可以对存入缓存的数据设置过期时间,所有的写操作以数据库为准,对缓存操作只是尽最大努力即可。也就是说如果数据库写成功,缓存更新失败,那么只要到达过期时间,则后面的读请求自然会从数据库中读取新值然后回填缓存,达到一致性,切记,要以mysql的数据库写入库为准。

上述方案和后续落地案例是调研后的主流+成熟的做法,但是考虑到各个公司业务系统的差距,不是100%绝对正确,不保证绝对适配全部情况,请同学们自行酌情选择打法,合适自己的最好。

可以停机的情况:

挂牌报错,凌晨升级,温馨提示,服务降级
单线程,这样重量级的数据操作最好不要多线程

四种更新策略:

  1. 先更新数据库,再更新缓存

    案例一:

    更新mysql的某商品的库存,当前商品的库存是100,更新为99个。
    1、先更新mysql修改为99成功,然后更新redis。
    2、此时假设异常出现,更新redis失败了,这导致mysql里面的库存是99而redis里面的还是100。

    上述发生,会让数据库里面和缓存redis里面数据不一致,读到redis脏数据

    案例二:

    image-20230306230929143

  2. 先更新缓存,再更新数据库

    业务上一般把mysql作为底单数据库,保证最后解释

    案例一:

    image-20230306231156598

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

    案例:

    两个并发操作,一个是更新操作,另一个是查询操作,
    A删除缓存后,B查询操作没有命中缓存,B先把老数据读出来后放到缓存中,然后A更新操作更新了数据库。
    于是,在缓存中的数据还是老的数据,导致缓存中的数据是脏的,而且还一直这样脏下去了。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eSCPx6nt-1692427619711)(https://you-blog.oss-accelerate.aliyuncs.com/2023/202303062316864.png)]

    image-20230306231625485

    image-20230306231701491

    解决方案: 延时双删策略

    image-20230306232004783

    加上sleep的这段时间,就是为了让线程B能够先从数据库读取数据,再把缺失的数据写入缓存,然后,线程A再进行删除。所以,线程A sleep的时间,就需要大于线程B读取数据再写入缓存的时间。这样一来,其它线程读取数据时,会发现缓存缺失,所以会从数据库中读取最新值。因为这个方案会在第一次删除缓存值后,延迟一段时间再次进行删除,所以我们也把它叫做“延迟双删”。

    延迟双删问题:

    1. 这个删除该休眠多久呢

      线程A sleep的时间,需要大于线程B读取数据再写入缓存的时间

      确认时间的方法:

      1. 第一种方法:

        在业务程序运行的时候,统计下线程读数据和写缓存的操作时间,自行评估自己的项目的读数据业务逻辑的耗时,以此为基础来进行估算。然后写数据的休眠时间则在读数据业务逻辑的耗时基础上加百毫秒即可。这么做的目的,就是确保读请求结束,写请求可以删除读请求造成的缓存脏数据。

      2. 第二种方法:

        新启动一个后台监控程序,比如后面要讲解的VatchDog监控程序,会加时

    2. 这种同步淘汰策略,吞吐量降低怎么办

      使用异步线程,避免阻塞

      image-20230308213815830

    3. 看门狗WatchDog分析

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

    1. 异常问题:

      image-20230308214041872

    2. 业务指导思想

      1. 微软云

        https://learn.microsoft.com/en-us/azure/architecture/patterns/cache-aside

      2. 阿里canal

    3. 解决方案

      image-20230308214650661

      流程如下图所示:

      1. 更新数据库数据

      2. 数据库会将操作信息写入binlog日志当中

      3. 订阅程序提取出所需要的数据以及key

      4. 另起一段非业务代码,获得该信息

      5. 尝试删除缓存操作,发现删除失败

      6. 将这些信息发送至消息队列

      7. 重新从消息队列中获得该数据,重试操作。

      8. 可以把要删除的缓存值或者是要更新的数据库值暂存到消息队列中(例如使用Kafka/RabbitMQ等)

      9. 当程序没有能够成功地删除缓存值或者是更新数据库值时,可以从消息队列中重新读取这些值,然后再次进行删除或更新。

      10. 如果能够成功地删除或更新,我们就要把这些值从消息队列中去除,以免重复操作,此时,我们也可以保证数据库和缓存的数据一致了,否则还需要再次进行重试

      11. 如果重试超过的一定次数后还是没有成功,我们就需要向业务层发送报错信息了,通知运维人员。

    4. 类似经典的分布式事务问题

      只能保证最终一致性

三、总结

  1. 如何选择方案?利弊如何

    在大多数业务场景下,优先使用先更新数据库,再删除缓存的方案(先更库→后删缓存)。

    理由如下:

    1. 先删除缓存值再更新数据库,有可能导致请求因缓存缺失而访问数据库,给数据库带来压力导致打满nysql。.

    2. 如果业务应用中读取数据库和写缓存的时间不好估算,那么,延迟双删中的等待时间就不好设置。

    如果使用先更新数据库,再删除缓存的方案: 如果业务层要求必须读取一致性的数据,那么我们就需要在更新数据库时,先在Rdis缓存客户端暂停并发读请求,等数据库更新完、缓存值删除后,再读取数据,从而保证数据一致性,这是理论可以达到的效果,但实际,不推荐,因为真实生产环境中,分布式下很难做到实时一致性,一般都是最终一致性。

  2. 总结

    image-20230308215415472

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

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

相关文章

解决:(error) ERR unknown command shutdow,with args beginning with

目录 一、遇到问题 二、出现问题的原因 三、解决办法 一、遇到问题 要解决连接redis闪退的问题,按照许多的方式去进行都没有成功,在尝试使用了以下的命名去尝试时候,发现了这个问题。 二、出现问题的原因 这是一个粗心大意导致的错误&am…

Azure静态网站托管

什么是静态网站托管 Azure Blob的静态网站托管是一项功能,它允许开发人员在Azure Blob存储中托管和发布静态网站。通过这个功能,您可以轻松地将静态网页、图像、视频和其他网站资源存储在Azure Blob中,并直接通过提供的URL访问这些资源。 官…

什么是变量提升(hoisting)?它在JavaScript中是如何工作的?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 变量提升(Hoisting)⭐ 变量提升的示例:⭐ 写在最后 ⭐ 专栏简介 前端入门之旅:探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅&…

Android 场景Scene的使用

Scene 翻译过来是场景,开发者提供起始布局和结束布局,就可以实现布局之间的过渡动画。 具体可参考 使用过渡为布局变化添加动画效果 大白话,在 Activity 的各个页面之间切换,会带有过渡动画。 打个比方,使用起来类似…

回归预测 | MATLAB实现IPSO-SVM改进粒子群优化算法优化支持向量机多输入单输出回归预测(多指标,多图)

回归预测 | MATLAB实现IPSO-SVM改进粒子群优化算法优化支持向量机多输入单输出回归预测(多指标,多图) 目录 回归预测 | MATLAB实现IPSO-SVM改进粒子群优化算法优化支持向量机多输入单输出回归预测(多指标,多图&#xf…

保险龙头科技进化论:太保的六年

如果从2013年中国首家互联网保险公司——众安在线的成立算起,保险科技在我国的发展已走进第十个年头。十年以来,在政策指引、技术发展和金融机构数字化转型的大背景下,科技赋能保险业高质量发展转型已成为行业共识。 大数据、云计算、人工智…

unity 之Transform组件(汇总)

文章目录 理论指导结合例子 理论指导 当在Unity中处理3D场景中的游戏对象时,Transform 组件是至关重要的组件之一。它管理了游戏对象的位置、旋转和缩放,并提供了许多方法来操纵和操作这些属性。以下是关于Transform 组件的详细介绍: 位置&a…

初步认识OSI/TCP/IP一(第三十八课)

1 初始OSI模型 OSI参考模型(Open Systems Interconnection Reference Model)是一个由国际标准化组织(ISO)和国际电报电话咨询委员会(CCITT)联合制定的网络通信协议规范,它将网络通信分为七个不同的层次,每个层次负责不同的功能和任务。 2 网络功能 数据通信、资源共…

网络安全---webshell实践

一、首先环境配置 1.上传文件并解压 2.进入目录下 为了方便解释,我们只用两个节点,启动之后,大家可以看到有 3 个容器(可想像成有 3 台服务器就成)。 二、使用蚁剑去连接 因为两台节点都在相同的位置存在 ant.jsp&…

ansible(1)-- 部署ansible连接被控端

目录 一、部署ansible 1.1 安装 1.2 测试连接 192.168.136.55 ansible 192.168.136.56被控端 一、部署ansible 1.1 安装 zabbix-s只是主机名,不用在意,更好该主机也安装了zabbix,不好更改。 下载阿里云epel源 #安装阿里云的epel源&#…

算法之排序总结

排序算法 最近,一直在学习业务上的知识,对基础没有怎么重视,因此,这篇文章想对于排序算法进行一个大致的总结🤓🤓🤓。 首先来说一下,关于排序一些相关的基础知识。 排序概述 原地…

操作系统的体系结构、内核、虚拟机

🐌个人主页: 🐌 叶落闲庭 💨我的专栏:💨 c语言 数据结构 javaweb 石可破也,而不可夺坚;丹可磨也,而不可夺赤。 操作系统结构 一、操作系统体系结构1.1操作系统的内核1.1.…

GO学习之 数据库(mysql)

GO系列 1、GO学习之Hello World 2、GO学习之入门语法 3、GO学习之切片操作 4、GO学习之 Map 操作 5、GO学习之 结构体 操作 6、GO学习之 通道(Channel) 7、GO学习之 多线程(goroutine) 8、GO学习之 函数(Function) 9、GO学习之 接口(Interface) 10、GO学习之 网络通信(Net/Htt…

VS2019生成的DLL,给QT(MinGW版本)使用的小结

VS2019端: a 基于生成一个DLL的工程(要注意生成是x86,还是x64的,需要和后面的QT的App工程对应),这里不多解释了,网上多的是; b 在cpp实现文件里,假如要导出一个这样的…

React Native文本添加下划线

import { StyleSheet } from react-nativeconst styles StyleSheet.create({mExchangeCopyText: {fontWeight: bold, color: #1677ff, textDecorationLine: underline} })export default styles

kafka-- kafka集群 架构模型职责分派讲解

一、 kafka集群 架构模型职责分派讲解 生产者将消息发送到相应的Topic,而消费者通过从Topic拉取消息来消费 Kafka奇数个节点消费者consumer会将消息拉去过来生产者producer会将消息发送出去数据管理 放在zookeeper

actuator/prometheus使用pushgateway上传jvm监控数据

场景 准备 prometheus已经部署pushgateway服务&#xff0c;访问{pushgateway.server:9091}可以看到面板 实现 基于springboot引入支持组件&#xff0c;版本可以 <!--监控检查--><dependency><groupId>org.springframework.boot</groupId><artifa…

java Spring Boot yml多环境拆分文件管理优化

上文 java Spring Boot yml多环境配置 我们讲了多环境开发 但这种东西都放在一起 还是非常容易暴露信息的 并且对维护来讲 也不是非常的友好 这里 我们在resources下创建三个文件 分别叫 application-pro.yml application-dev.yml application-test.yml 我们直接将三个环境 转…

Seaborn数据可视化(一)

目录 1.seaborn简介 2.Seaborn绘图风格设置 21.参数说明&#xff1a; 2.2 示例&#xff1a; 1.seaborn简介 Seaborn是一个用于数据可视化的Python库&#xff0c;它是建立在Matplotlib之上的高级绘图库。Seaborn的目标是使绘图任务变得简单&#xff0c;同时产生美观且具有信…

图像处理常见的两种拉流方式

传统算法或者深度学习在进行图像处理之前&#xff0c;总是会首先进行图像的采集&#xff0c;也就是所谓的拉流。解决拉流的方式有两种&#xff0c;一个是直接使用opencv进行取流&#xff0c;另一个是使用ffmpeg进行取流&#xff0c;如下分别介绍这两种方式进行拉流处理。 1、o…