【MySQL】如何处理DB读写分离数据不一致问题?

news2025/1/12 15:55:13

文章内容

    • 1、前言
    • 读写库数据不一致问题我们如何解决?
      • 方案一:利用数据库自身特性
      • 方案二:不解决
      • 方案三:客户端保存法
      • 方案四:缓存标记法
      • 方案五:本地缓存标记
    • 那DB读写分离情况下,如何解决缓存和数据库不一致性问题呢?
      • 方案一:延迟消息
      • 方案二:更新用户再次发起读请求

1、前言

在互联网中大型项目中,读写分离应该是我们小伙伴经常听说的,这个主要解决大流量请求时,提高系统的吞吐量。因为绝大部分互联网产品都是读多写少,大部分都是读请求,很小部分是写请求。

在这里插入图片描述

1)一个主库负责写请求,更新数据
 
2)两个从库负责读请求,可以提高系统吞吐量
 
3)主库和从库之间同步数据

为什么产生数据不一致

在这里插入图片描述
上图中业务流程

1)写请求A进行数据更新,但写库还没有来得及把更新的数据更新到读库
 
2)读请求B进行数据查询,请求B是访问的读库,获取的是旧值
 
3)因为写库和读库之间存在同步延迟,导致数据在不同库中不一致

读写库数据不一致问题我们如何解决?

方案一:利用数据库自身特性

我们一般用的数据库是mysql和oracle,mysql是我们互联网项目都会用到的,oracle一般大公司用的比较多(很贵啊)。

我们分析一下问题,原因就是在主库(写库)与从库(读库)之间数据同步延迟导致,mysql中有全同步复制机制、半同步复制、异步复制三种复制方案(小伙伴可以自行去了解)。

mysql全同步复制

在这里插入图片描述

全同步复制,当A提交更新请求主库事务之后,不是立即返回,而是等到所有的从库节点必须收到、APPLY并且提交这些事务,主库线程才返回请求A结果,才能做后续操作。这样就解决了数据同步延迟的问题。

问题:但这个同步方案严重的问题就是写请求耗时会很长,而且会随者从库数量增加,耗时也会增加。(不推荐)

oracle共享存储

在这里插入图片描述

上图采用了oracle RAC方案,DB服务其实就代表一个应用服务,所有的数据存储在同一个地方,所有就不存在数据同步这个问题。当然这个部署方案不是我们严格意义上面的读写分离,存储是独立的。

方案二:不解决

我们设计任何架构方案,都要围绕着业务,如果业务能够接受可以不解决;其实很多互联网产品都有短时间的数据不一致问题。如:58同城,美团,贴吧等。

但有些场景是不允许的。如
在这里插入图片描述
上图中:

1)用户写了一篇文章,点击保存按钮
 
2)系统执行保存方法,提示用户保存成功
 
3)保存成功后一般系统就会立即跳转到文章列表,按照时间倒序,最新的文章排在第一个,这个业务是很正常的,让用户可以看到自己的文章列表
 
4)这样就是调用获取文章列表的方法getArticleList,但这个方法是读请求,走的是从库。
 
5)如果出现主库和从库同步延迟,就出现了不一致。

方案三:客户端保存法

这个方案是:一些业务的操作是有前端页面的,不管是网页或App等。此方案的思路就是把之前保存的文章缓存到客户端,在用户到文章列表时,数据的组成就是(客户端缓存文章 + 后端读库返回的文章数据)。客户端要做的就是缓存要设置一个时间(这个缓存时间,可以预估主库同步到从库的时间延迟);以及要做文章去重,防止读库已经同步完成,客户端缓存没有过期。

问题:客户端逻辑复杂;客户端有缓存数据大小的限制,不能保存大数据。列表分页处理复杂。

方案四:缓存标记法


在这里插入图片描述
上图流程:

1)A发起写请求,更新了主库,但在缓存中设置一个标记,代表此数据已经更新,标记格式(业务代号:数据库:表:主键ID)根据自己业务场景。
 
2)设置此标记,要加上过期时间,可以为预估的主库和从库同步延迟的时间
 
3)B发起读请求的时候,先判断此请求的业务在缓存中有没有更新标记
 
4)如果存在标记,走主库;如果没有走从库。

这个方案就有效了解决了数据不一致的问题。

但这个方案会有个严重的问题,也就是每次的读请求都要到缓存中去判断是否存在缓存标记,如果是单机部署用的是jvm缓存,对性能还好;但如果是集群部署缓存肯定用redis,每次读都要和redis进行交互,这样肯定会影响系统吞吐量。

那怎么办?怎么办?继续往下看

方案五:本地缓存标记


在这里插入图片描述
上图流程:

1)用户A发起写请求,更新了主库,并在客户端设置标记,过期时间,如:cookies
 
2)用户A再发起读请求时,带上这个本地标记在后端
 
3)后端在处理请求时,获取请求传过来的数据,看有没有这个标记(如:cookies)
 
4)有这个业务标记,走主库;没有走从库。

这个方案就保证了用户A的读请求肯定是数据一致的,而且没有性能问题,因为标记是本地客户端传过去的。

但有写小伙伴就会问那其他用户在本地客户端是没有这个标记的,他们走的就是从库了。那其他用户不就看不到这个数据了吗?说的对,其他用户是看不到,但看不到的时间很短,过个1~10秒就能够看到。

但这个方案解决了当前用户的数据一致性的问题,如上面举的例子,写文章,然后到文章列表,本用户是能够看到的。其他用户暂时看不到是没有关系的。还是那句话,脱离业务的方案是耍流氓。(推荐)

那DB读写分离情况下,如何解决缓存和数据库不一致性问题呢?

方案一:延迟消息

其实在真实业务中,尤其互联网项目中,数据短时间的不一致时能够接受的。就像怎么解决DB读写分离,导致数据不一致问题?中提到的本地缓存标记法,保证了本用户数据一致,其他用户可暂时不一致,但最终是一致的这个思路。我们可以设置一个延迟消息,如下图
在这里插入图片描述
流程:

1)在订阅到binlog更新日志时,先不删除缓存,而是投递一个延迟消息(如:延迟10秒的消息,就是过10秒此消息才会被消费者监听到,从而被消费)

2)延迟消息的延迟时间,设置为主库与从库的数据同步延迟的时间,可自行预估

3)监听到延迟消息,在删除缓存。

这个方案的特点就是读请求会在延迟时间内读取到的是旧值,等到延迟时间一过,取到的就是新值。这个业务在互联网产品中是允许的。

如果要保证本用户(更新数据的用户)一定读到的是新值,这边可以采用本地缓存标记方案,直接从主数据库读取,读取到数据后,可以把新值设置到缓存中,这样就保证了数据一致性。

方案二:更新用户再次发起读请求

在方案一中,其他用户的读请求会有暂时间读取到的是旧值,如何缩短时间?其实是有一个方案,就是让更新用户再次发起读请求,也就是在方案一最后提到的

1)更新用户再次发起读请求,根据本地缓存标记,直接走主数据库,读取的肯定是新值,

2)再把这个新值设置到缓存中。这样就保证了缓存中的是新值,虽然从库还没有不同完成,但缓存中已经是新值了。

3)最后从库同步数据完成,值就达到了一致性

参考文章:

DB读写分离情况下,如何解决缓存和数据库不一致性问题?

如何更新缓存保证缓存和数据库双写一致性?

怎么解决DB读写分离,导致数据不一致问题?

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

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

相关文章

STM32F1X RS485使用DMA发送丢失数据的处理方法。

串口通过DMA发送一帧数据时总是缺少2个字节,且最后一个字节数据为0xff的原因及解决方法 本次记录为采用485串口发送数据,发送模式是循环检测串口数据寄存器为空(TXE)和发送完成标志位(TC)。DMA发送串口方式…

基于java,springboot和vue房屋租赁租房销售平台设计

摘要 在现代城市生活中,房屋租赁市场一直是一个活跃且复杂的领域。随着互联网技术的不断发展,基于Spring Boot和Vue的房屋租赁系统应运而生,旨在提供一个高效、方便、可靠的在线服务平台。该系统利用了前后端分离架构的优势,后端…

【嵌入式学习】QT-Day1-Qt基础

笔记 https://lingjun.life/wiki/EmbeddedNote/20QT 毛玻璃登录界面实现:

模式匹配这么好,Java语法里有吗?

这篇文章我们借助新版Java来理解模式匹配,Rust版的模式匹配稍后就端上来,各位先尝尝Java这杯老咖啡还香不香😄。 什么是模式匹配? 下图直观的表达了模式匹配的概念。 所谓模式类似上图中木盒的各种形状的洞洞,我们…

UG NX二次开发(C#)-PMI-获取PMI尺寸数据

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 1、前言2、在UG NX的三维模型中添加PMI尺寸信息3、采用二次开发获取尺寸数据4、测试结果1、前言 PMI(Product and Manufacturing Information)是产品和制造信息的简称,主要用于将产品部件设计的…

工具分享:在线键盘测试工具

在数字化时代,键盘作为我们与计算机交互的重要媒介之一,其性能和稳定性直接影响到我们的工作效率和使用体验。为了确保键盘的每个按键都能正常工作,并帮助用户检测潜在的延迟、连点等问题,一款优质的在线键盘测试工具显得尤为重要…

智能运维乱象有哪些?智能运维业务包括哪些

在实施智能运维过程中可能遇到的乱象及其原因,系统地阐述智能运维业务所涵盖的各个方面,包括但不限于预防性维护、故障检测与诊断、自动化修复以及持续的性能优化等关键组成部分。 实施智能运维过程中可能遇到的乱象及原因包括: 数据不一致或…

Qt|大小端数据转换(补充)

Qt|大小端数据转换-CSDN博客 之前这篇文章大小端数据转换如果是小数就会有问题。 第一个方法&#xff1a; template <typename T> static QByteArray toData(const T &value, bool isLittle) {QByteArray data;for (int i 0; i < sizeof(T); i) {int bitOffset…

小米14 ULTRA:重新定义手机摄影的新篇章

引言 随着科技的飞速发展&#xff0c;智能手机已经不仅仅是一个通讯工具&#xff0c;它更是我们生活中的一位全能伙伴。作为科技领域的佼佼者&#xff0c;小米公司再次引领潮流&#xff0c;推出了全新旗舰手机——小米14 ULTRA。这款手机不仅在性能上进行了全面升级&am…

电脑文件msvcr110.dll缺失的多种解决方法,msvcr110.dll文件修复手段

遭遇"程序无法启动&#xff0c;因为电脑中缺失msvcr110.dll"这样的错误提示&#xff0c;是Windows操作系统用户可能会遇到的一种情况。尽管这种现象在一些用户中较为常见&#xff0c;但解决这一问题并非复杂的过程。本文将深入剖析此问题&#xff0c;并分享一些实用的…

2.16日学习打卡----初学Dubbo(一)

2.16日学习打卡 目录: 2.16日学习打卡一. 什么是分布式&#xff1f;二. 什么是RPC?三. Dubbo概念_简介四. Dubbo核心组件五.Dubbo配置开发环境六. Dubbo配置开发环境_管理控制台 一. 什么是分布式&#xff1f; 可以看我的这篇文章–2.14日学习打卡----初学Zookeeper(一) 二.…

【设计模式】23种设计模式笔记

设计模式分类 模板方法模式 核心就是设计一个部分抽象类。 这个类具有少量具体的方法&#xff0c;和大量抽象的方法&#xff0c;具体的方法是为外界提供服务的点&#xff0c;具体方法中定义了抽象方法的执行序列 装饰器模式 现在有一个对象A&#xff0c;希望A的a方法被修饰 …

Android挖取原图中心区域RectF(并框线标记)放大到ImageView宽高,Kotlin

Android挖取原图中心区域RectF(并框线标记)放大到ImageView宽高&#xff0c;Kotlin 红色线框区域即为选中的原图中心区域&#xff0c;放大后放到等宽高的ImageView里面。 import android.content.Context import android.graphics.Bitmap import android.graphics.BitmapFactor…

Mybatis | 初识Mybatis

初识Mybatis 目录: 初识Mybatis什么是Mybatis&#xff1f;Hibernate 和 MyBatis的区别&#xff1f;Mybatis的下载和使用Mybatis的工作原理 作者简介 &#xff1a;一只大皮卡丘&#xff0c;计算机专业学生&#xff0c;正在努力学习、努力敲代码中! 让我们一起继续努力学习&#…

牛客网 OR141 密码检查

答案&#xff1a; #include <stdio.h> #include <string.h> #include <ctype.h> int main() {int n 0;int count1 0, count2 0, count3 0;scanf("%d", &n);while (n--){char ch[100];scanf("%s", ch);int len strlen(ch);if (…

UE5 C++ UENUM 和 USTRUCT

一.首先在APawn里声明 UENUM 和 USTRUCT。UENUM 有两种定义方式 一种是使用命名空间&#xff1a; 还有是继承uint8&#xff1a; 通过申明class类 别名来替代 USTRUCT的定义 上面的第二种有类似但仍然有很多的差异&#xff1a; 首先要有GENERATED_USTRUCT_BODY()这个函数 并且…

element-ui 自定义表头label(利用 :slot=“header“ slot-scope=“slot“)

<el-table :data"Gbtable" border style"width: 100%"><el-table-column prop" date" label"责任方" align"center" ></el-table-column><el-table-column prop"name" label"柜名"…

图片文字编辑软件app分享5个!

在数字化时代&#xff0c;图片和文字的结合已经成为信息传播的重要形式之一。无论是制作精美的海报、设计独特的社交媒体封面&#xff0c;还是简单地为图片添加一些说明性文字&#xff0c;都离不开专业的图片文字编辑软件。今天&#xff0c;就让我们一起探索那些不可错过的图片…

ai自动证件照片制作的软件?分享3款先进工具!

随着科技的发展&#xff0c;我们的生活变得越来越便捷。尤其在图像处理领域&#xff0c;AI技术的应用更是让许多传统行业焕发出新的活力。其中&#xff0c;AI证件照制作工具就是近年来备受瞩目的创新产品。这些工具利用先进的AI技术&#xff0c;帮助用户在家中就能轻松制作出专…

【git 使用】使用 git rebase -i 修改任意的提交信息/合并多个提交

修改最近一次的提交信息的方法有很多&#xff0c;可以参考这篇文章&#xff0c;但是对于之前的提交信息进行修改只能使用 rebase。 修改提交信息 假设我们想修改下面这个提交信息&#xff0c;想把【登录】改成【退出登录】步骤如下 运行 git rebase -i head~3 打开了一个文本…