【数据库与缓存保持一致性】

news2024/11/18 2:53:29

文章目录

  • 1. 方案1
    • 先更新数据库,再更新缓存
    • 先更新缓存,在更新数据库
  • 2. 方案2
    • 先更新数据库,在删缓存
    • 先删缓存,在更新数据库
  • 3. 方案3—如何保证两个操作都能执行成功?
    • 重试机制
    • 订阅 MySQL binlog

1. 方案1

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

在这里插入图片描述

先更新缓存,在更新数据库

在这里插入图片描述

总结:无论是「先更新数据库,再更新缓存」,还是「先更新缓存,再更新数据库」,这两个方案都存在并发问题,当两个请求并发更新同一条数据的时候,可能会出现缓存和数据库中的数据不一致的现象。

  • 我们的业务对缓存命中率有很高的要求,我们可以采用「更新数据库 + 更新缓存」的方案,因为更新缓存并不会出现缓存未命中的情况。

问题

  • 在两个更新请求并发执行的时候,会出现数据不一致的问题,因为更新数据库和更新缓存这两个操作是独立的,而我们>又没有对操作做任何并发控制,那么当两个线程并发更新它们的话,就会因为写入顺序的不同造成数据的不一致。

解决办法

  1. 在更新缓存前先加个分布式锁,保证同一时间只运行一个请求更新缓存,就会不会产生并发问题了,当然引入了锁后,对于写入的性能就>会带来影响。
  2. 在更新完缓存时,给缓存加上较短的过期时间,这样即时出现缓存不一致的情况,缓存的数据也会很快过期,对业务还是能接受的。

2. 方案2

  • 先更新数据库,还是先删除缓存,叫Cache Aside 策略,中文是叫旁路缓存策略

  • 该策略又可以细分为「读策略」「写策略」

  • 写策略的步骤

    1. 更新数据库中的数据;
    2. 删除缓存中的数据。
  • 读策略的步骤

    1. 如果读取的数据命中了缓存,则直接返回数据;
    2. 如果读取的数据没有命中缓存,则从数据库中读取数据,然后将数据写入到缓存,并且返回给用户。

先更新数据库,在删缓存

在这里插入图片描述

  • 因为缓存的写入通常要远远快于数据库的写入,所以在实际中很难出现请求 B 已经更新了数据库并且删除了缓存,请求 A 才更新完缓存的情况。
  • 而一旦请求 A 早于请求 B 删除缓存之前更新了缓存,那么接下来的请求就会因为缓存不命中而从数据库中重新读取数据,所以不会出现这种不一致的情况。
  • 缓存数据加上了「过期时间」,就算在这期间存在缓存数据不一致,有过期时间来兜底,这样也能达到最终一致。

所以,「先更新数据库 + 再删除缓存」的方案,是可以保证数据一致性的。

问题

  • 明明更新了数据,但是数据要过一段时间才生效。(原因:「先更新数据库, 再删除缓存」其实是两个操作,前面的所有分析都是建立在这两个操作都能同时执行成功,而这次客户投诉的问题就在于,在删除缓存(第二个操作)的时候失败了,导致缓存中的数据是旧值。给缓存加上了过期时间,所以才会出现客户说的过一段时间才更新生效的现象。)

先删缓存,在更新数据库

在这里插入图片描述

解决办法

  • 延迟双删
#删除缓存
redis.delKey(X)
#更新数据库
db.update(X)
#睡眠
Thread.sleep(N)
#再删除缓存
redis.delKey(X)
  • 加个睡眠时间,主要是为了确保请求 A 在睡眠的时候,请求 B 能够在这这一段时间完成「从数据库读取数据,再把缺失的缓存写入缓存」的操作,然后请求 A 睡眠完,再删除缓存。
    所以,请求 A 的睡眠时间就需要大于请求 B 「从数据库读取数据 + 写入缓存」的时间。

建议使用「先更新数据库,再删除缓存」的方案。

3. 方案3—如何保证两个操作都能执行成功?

  • 「先更新数据库 + 再删除缓存」的方案,是可以保证数据一致性的。但是在删除缓存(第二个操作)的时候失败了,导致缓存还是旧值,而数据库是最新值,虽然加了过期时间,但是也需要过一会才生效,所以还会造成数据库和缓存数据不一致的问题。
  • 不管是先操作数据库,还是先操作缓存,只要第二个操作失败都会出现数据一致的问题。
    在这里插入图片描述
    解决办法
  • 重试机制。
  • 订阅 MySQL binlog,再操作缓存。

重试机制

  • 引入消息队列,将第二个操作(删除缓存)要操作的数据加入到消息队列,由消费者来操作数据。
    • 如果应用删除缓存失败,可以从消息队列中重新读取数据,然后再次删除缓存,这个就是重试机制。当然,如果重试超过的一定次数,还是没有成功,我们就需要向业务层发送报错信息了。
    • 如果删除缓存成功,就要把数据从消息队列中移除,避免重复操作,否则就继续重试。

在这里插入图片描述

订阅 MySQL binlog

  • 「先更新数据库,再删缓存」的策略的第一步是更新数据库,那么更新数据库成功,就会产生一条变更日志,记录在 binlog 里。
  • 通过订阅 binlog 日志,拿到具体要操作的数据,然后再执行缓存删除,Canal 中间件就是基于这个实现的。

Canal 原理

  • Canal 模拟 MySQL 主从复制的交互协议,把自己伪装成一个 MySQL 的从节点,向 MySQL 主节点发送 dump 请求,MySQL 收到请求后,就会开始推送 Binlog 给 Canal,Canal 解析 Binlog 字节流之后,转换为便于读取的结构化数据,供下游程序订阅使用。
    在这里插入图片描述
    文章:https://www.xiaolincoding.com/

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

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

相关文章

S7-1200PLC与组态王进行TCP通信的基本方法和步骤

S7-1200PLC与组态王进行TCP通信的基本方法和步骤 如下图所示,打开博途软件,新建一个项目,设置该PLC的IP地址为:192.168.1.102, 如下图所示,在OB1中编写一段简单的启保停程序, 如下图所示,打开Kingview组态王软件,点击文件—新建工程, 新建一个项目,如下图所示…

化工企业安全风险管控数字化解决方案

当前我国化工行业的基础能力缺失问题非常严重。由于一些共性技术的缺失,给以化工行业为代表的关键基础工业的产业安全带来诸多隐患。粗放式发展 带来的环保安全问题,不仅造成了巨大的资源浪费和社会成本的增加,同 时也使整个产业的发展环境恶…

SpringBoot+Vue前后端分离项目搭建

好久没写文章了!!! 企业级项目,开袋即食。扩展、修改起来非常方便 系统基本功能 用户管理:提供用户的相关配置,新增用户后,默认密码为:Pass_123角色管理:对权限与菜单…

基于注解的AOP之切入点表达式的语法和获取连接点的信息以及切入点表达式的重用

基于注解的AOP之切入点表达式的语法和获取连接点的信息以及切入点表达式的重用 1.切入点表达式的语法 ①作用 ②语法细节 用*号代替“权限修饰符”和“返回值”部分表示“权限修饰符”和“返回值”不限 在包名的部分,一个“*”号只能代表包的层次结构中的一层&…

Vue3+TS+Vant3——增删改input和通过双页面进行增删改操作

Vue3TSVant3——增删改input和通过双页面进行增删改操作 两种方案: 第一种点击添加按钮添加一项,缺点:页面过于臃肿,用户体验较差 第二种:分成两种页面进行添加等操作 先说一下第一种,我这里用到了va…

Linux下Qt程序用qBreakpad定位崩溃位置

目录1. 使用qBreakpad1.1. 下载1.2. 编译1.3. 使用2. 使用dump文件2.1. 编译breakpad2.2. 解析dmp文件生成sym文件2.3. 解析dmp可能遇到的问题问题一Qt程序的release版本交付给用户或者测试后,如果出现崩溃,很多时候都比较难重现,如果程序能自…

赛卓电子冲刺科创板上市:计划募资11亿元,股东包括尚颀资本等

12月28日,赛卓电子科技(上海)股份有限公司(下称“赛卓电子”)在上海证券交易所递交招股书,准备在科创板上市。本次冲刺上市,赛卓电子计划募资11亿元,将用于车规级芯片研发及产业化项…

高级网络复习——防火墙,OSPF协议,rip协议,三层,DHCP中继知识题解(带答案)

作者简介:一名在校云计算网络运维学生、每天分享网络运维的学习经验、和学习笔记。 座右铭:低头赶路,敬事如仪 个人主页:网络豆的主页​​​​​​ 目录 前言 简答题 二.选择题 前言 本章讲解讲解防火墙,OSPF协…

java多线程(9):线程状态

1 五大状态 2 线程方法 3 停止线程 不推荐使用JDK提供的 stop()、 destroy()方法。【已废弃】推荐线程自己停止下来建议使用一个标志位进行终止变量 ,当flagfalse,则终止线程运行。package xiong.demo3;public class TestStop implements Runnable{//1.…

从DTCC2022盘点各大厂商如何看待数据库发展趋势

DTCC 2022 已落下帷幕有些时日,回顾大会上的一些分享,尤其是头一天上午几大数据库厂商均在演讲一开始纷纷表达了对数据库发展趋势的看法。从各个厂商的观点来看,对数据库发展趋势基本属于是不谋而合,未来数据库的样子离不开以下这…

MATLAB形态学的基本运算膨胀和腐蚀(开、闭运算)

形态学中两种基本的操作是膨胀和腐蚀,膨胀是指在图像中为其边界添加像素点,而腐蚀是其逆过程。对应的添加和移除像素点数依赖于处理图像结构元素矩阵的大小和形式。 一.膨胀处理 膨胀的运算符为⊕, A用B来膨胀写作A⊕B,MATLAB中提供了预定义…

小程序-小程序框架

目录 一,框架简介 响应的数据绑定 二,视图层 View WXML (html) WXSS 样式 JS 逻辑交互 三,事件 什么是事件 事件的使用方式 四,逻辑层 APP service 1,生命周期 生命周期演示 页面路…

快速排序(Java分治法)

快速排序(Java分治法) 文章目录快速排序(Java分治法)0、 分治策略1、思路步骤2、代码3、复杂度分析3.1 最好情况3.2 最坏情况3.3 平均情况3.4 性能影响因素4、合并排序VS快速排序5、参考0、 分治策略 快速排序是对气泡排序的一种改…

minio下载、安装、Java集成应用

1.下载MinIO 下载链接:https://dl.min.io/server/minio/release/windows-amd64/minio.exe 网盘:https://pan.baidu.com/s/1uS2ii958tTjnb0KTpsKpCg 提取码:3nr9 2.安装启动 下载好的文件不要双击,自己定义一个文件夹放下载好的文件,本文指定的位置D:\minio,同时创建一…

淮北绿金通过港交所上市聆讯:净利润再度下滑,收入依赖股东

12月27日,港交所披露的信息显示,淮北绿金产业投资股份有限公司(下称“淮北绿金”)通过港交所上市聆讯并递交了聆讯后招股书,光大证券国际为其独家保荐人。据了解,淮北绿金曾于2021年12月递表,20…

【答学员问】网站换ip后遇到的问题排查思路

文章目录遇到问题先进行基本的问题排查1. 查看IP2. 是否能通网3. 关闭防火墙和selinux4. 使用windows的浏览器访问问题复现1. 安装好wordpress ,确保能够访问2. 修改IP,进行测试3. 访问测试:问题排查问题解决方案遇到问题 学员反馈在家访问网…

C++类和对象1:类是什么?对象是什么?

目录 类的引入 类的定义 类的定义规则 类域问题: 类的访问限定符及封装 访问限定符 封装 类的实例化 类对象的大小问题 this指针 This指针的一些特性: 类的引入 在学习C语言的时候,C语言是面向过程的,关注的是过程&#xff…

2023年5月北京老博会,医养家具展,护理床展,老年护理展

2023中国国际养老服务业博览会CISSE介绍: 2023中国国际养老服务业博览会(CISSE)将于5月5-7日在北京国家会议中心举行。大会以养老产业为主题,通过展贸平台为涉老企业抢占市场先机,对企业营销策略、宣传影响力、定位产品…

apt-fast 使用

apt-fast 使用1. 安装2. 使用默认的apt-get install,有时下载会非常的慢,尤其是安装的一些ppa包的时候。apt-fast 通过使用多线程来给apt提速,极大地提高了效率。 1. 安装 添加ppa仓库 sudo add-apt-repository ppa:apt-fast/stable 更新软…

CAPL学习之路-测试功能集函数(约束和条件)

在test module和test unit中,可以添加事件对象或事件文本作为条件或约束。当事件发生时,条件或约束受损,测试报告中输出“Fail”条目,同时测试用例判定为“Fail” 此类函数有: TestAddCondition/TestAddConstraint,添加事件对象或事件文本作为条件或约束。不管是作为条件…