详解mysql和消息队列数据一致性问题

news2024/9/30 8:16:02

目录

前言

保持系统数据同步(双写问题)

消息队列消息丢失的问题

总结


前言

在当今互联网飞速发展的时代,随着业务复杂性的不断增加,消息队列作为一种重要的技术手段,越来越多地被应用于各种场景。它们不仅能有效解耦系统各部分之间的联系,还能够平衡流量峰值,提高系统的整体性能。

在本文中,我将重点分析一家医美公司的团队在使用消息队列时的奇葩做法。这家公司的技术团队选择了 Kafka 作为主要的消息队列,但在某些情况下却出现了数据未能成功消费的问题。为了应对这个挑战,他们又引入了 RocketMQ,并通过其延迟机制来弥补之前的不足。然而,这样的做法是否合理?这背后又隐藏着哪些技术思考与团队协作的缺陷?

接下来,我们将深入探讨这家公司的消息队列应用,以及其中的潜在问题与改进方案。

下面是我画的他们业务的一个架构图:

                                                                        <图一>

在这个架构图中,数据首先从MySQL数据库流入“业务1”,并通过Kafka进行消息传递。然后,数据被传递到“业务2”进行处理。处理完成后,系统会判断是否成功。如果成功,则数据继续存储到MySQL中;如果未成功处理,则会将消息发送到RocketMQ进行重新处理。

这个架构是非常简单,加入了 RocketMQ 就一个诉求就是消息不丢失,真的能做到吗?其实有几个问题,第一个问题系统同步也就是双重写入问题 第二个问题就是加入RocketMQ 和不合理,下面我们逐一讲解。

保持系统数据同步(双写问题)

我们业务系统有两个双写:业务1的1和2。业务2的5和6。图中这样的设计看起来很简单但是有一些严重的问题。

先用一个流程图来说明双写严重的问题:

                                                                <图二>

在这个例子中,两个客户同时想要更新项X:

客户端l 想要将值设置为A,客户端2 想要设置为B 。两个客户端首先将新值写入数据库,然后将其写入消息队列中。由于实机不凑巧,这些请求交叉了:数据库首先看到来自客户端1 的写入,将值设置为A,然后看到来自客户端2 的写入,将值设置为B ,因此数据库中的最终值为B 。而消息队列首先看到来自客户端2 的写人,然后才是客户端1 的写人,所以消息队列中的最终值是A。这两个系统将永远不一致,即使目前还没有发生错误。

除非有一些额外的并发监测机制,或者加入版本向量或者加入分布式锁。否则甚至不会注意到并发写入,一个值悄悄覆盖另一个值。

我们可以总结到双重写入的一个问题就是值会可能被覆盖。

还有一个很难发现的问题就是客户端1或者客户端2写入数据库成功了但是写入消息队列失败了,这不是一个并发问题,这是一个容错问题,也会造成两个系统相互不一致的结果,这是致命的。确保数据库和消息队列都成功或者失败是个原子提交问题,需要用到2pc 等分布式事务相关的技术。

这两个问题都是致命的,必须解决,数据库的主从复制给我了启发,不管如何并发,从库总是订阅主库的binglog,保证了数据的一致性。我们发现我们这个例子其实可以看成两个主库的双写问题,有没有一种技术把两个主库的双写问题转成主从机制呢?那么问题不就解决了吗?还真的是有这种方案,就是CDC 技术。于是我的架构就发生了一种变化。

                                                                <图三>

CDC 技术是对系统同步的里程碑,他借助了主从的思想,软件开发工程师开始认识到日志的重要性,再也不认为,数据库复制日志的问题被认为是数据库内部实现细节,他们开始尝试解析日志,捕获数据的变化,写入时立即将更改作为一种流来发布,那么业务只需要消费这些数据就可以了。现在很多数据库都提供了CDC解决方法。mysql 在国内用的最多的是canal。前面讲过就是canal作为一个从库似的获取主库的数据,并且她集成了快照技术也就是说会记录位置的偏移量,以便在快照处理完成后,知道哪一点开始应用修改。canal 具体问题,可以参考相关的文档。

消息队列消息丢失的问题

图一我们发现了该团队用了RocketMQ和kafka 就是解决业务2消息丢失的问题,RocketMQ在哪种情况下会用到,我们将详细分析下:

只有一种情况下,就是消费者出现error 或者异常,代码能捕获到这些问题,调用RocketMQ,用它的延迟队列。其实又有集中假设:

  1. 如果消费者出现了代码本身的bug ,应该在测试阶段就应该发现的,或者经过压测,这是代码问题,应该避免的

  2. 第二种情况就是业务二入库失败了,会把消息投递到RocketMQ,用它的延迟队列过段时间数据库可能就好了,就一定能捕获吗,成功写入到RocketMQ吗?

  3. 如果消费者在处理一半业务就突然挂掉了还能写入到RocketMQ吗,消息还是丢失了

经过分析发现只有第二种情况可能,为了一种可能的情况,引入RocketMQ当然是不合适的,是弊端大于利,而且系统更为复杂,不仅要监控kafka 而且也要监控RocketMQ。

那么我们就想kafka 能不能让消息不丢失呢。当然是可以的呀

在消息队列的处理中,常见的情况有以下几种:

零次处理(At-most-once):消息可能丢失,但不会被重复处理。

一次处理(At-least-once):消息一定会被处理,但可能会被处理多次。

精确一次(Exactly-once):确保每条消息只被处理一次。

消息不丢失我们可以用 At-least-once 消息设计模式

kafka 应该从生产者,消费者,还有服务端 去讨论消息不丢失:

生产者来说:

  1. 使用带回调方法的API。我们就知道消息有没有成功

  1. 设置参数 acks=1 (-1,0,1)。0生产者在发送消息后不等待任何确认,1 领导者(leader)在成功写入消息后发送确认。 -1 所有的副本(包括领导者和跟随者)都必须确认消息已被成功写入。

  1. 设置参数 retries=3。重试次数,如果次数到了还是失败,我们可以写入日志中

  1. 设置参数 retry.backoff.ms=300。每次重试间隔时间

服务端:

replication.factor>1。 (分区副本的个数),至少一个主分区,多个副本节点

Min.insync.replicas>1。 (isr 最少的副本数量)。

Unclean.leader.election.enable = false。 (是否能把非ISR集合中的副本选举为leader 副本)

定义:ISR 是指与当前主分区(Leader)保持同步的所有副本(Replica)。这些副本在数据写入主分区时,能够及时接收到并确认写入的数据。这是重要的,如果选择了非ISR 节点作为leader ,那么就会造成数据丢失。

消费者:

消费者是根据offset 来确定消息的消费位置,可以手动提交offset,就是业务结束的时候

Enable.auto.commit = false (手动提交偏移量)

具体的代码可以参考相关的文档。

得出了最终的架构是这样的。

总结

这篇文章我们详细介绍了cdc 技术,kafka 如何消息不丢失,同时也详细阐述了架构的不合理性以及合理性的架构是如何演变的。所以说选择一个好的团队特别重要。

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

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

相关文章

CRUD 开发工具 NocoBase 与 Refine 对比

引言 今天我们来聚焦两款非常优秀的开源 CRUD 开发工具&#xff1a;NocoBase 和 Refine&#xff0c;它们分别是无代码/低代码开发平台和低代码前端开发框架的典型代表。 特别值得一提的是&#xff0c;NocoBase 截止目前已经在GitHub 上获得了 12k 的 Star。Refine 作为 Retool…

「OC」多线程的学习——NSThread

「OC」多线程的学习——NSThread 文章目录 「OC」多线程的学习——NSThread线程(process) 和 进程(thread) 的区别多线程NSThreadNSThread的创建NSThread的方法常见API线程状态控制方法 NSThread线程的状态 NSThread的多线程隐患售票窗口例子 synchronize关键字NSThread的线程通…

【保姆级教程】UMLS工具——MetaMap安装及使用

专家词典 https://lhncbc.nlm.nih.gov/LSG/Projects/lexicon/current/web/index.html SPECIALIST 词典是一个大型的生物医学和通用英语句法词典&#xff0c;旨在提供 SPECIALIST 自然语言处理系统 (NLP) 所需的词汇信息&#xff0c;其中包括 MetaMap 和词汇工具等。它旨在成为…

docker快速安装ELK

一、创建elk目录 创建/elk/elasticsearch/data/目录 mkdir -p /usr/local/share/elk/elasticsearch/data/ 创建/elk/logstash/pipeline/目录 mkdir -p /usr/local/share/elk/logstash/pipeline/ 创建/elk/kibana/conf/目录 mkdir -p /usr/local/share/elk/kibana/conf/ 二、创建…

软考论文《论大数据处理架构及其应用》精选试读

论文真题 模型驱动架构设计是一种用于应用系统开发的软件设计方法&#xff0c;以模型构造、模型转换和精化为核心&#xff0c;提供了一套软件设计的指导规范。在模型驱动架构环境下&#xff0c;通过创建出机器可读和高度抽象的模型实现对不同问题域的描述&#xff0c;这些模型…

算法:按既定顺序创建目标数组

力扣1389 提示&#xff1a; 1 < nums.length, index.length < 100nums.length index.length0 < nums[i] < 1000 < index[i] < i 题解&#xff1a; class Solution {public int[] createTargetArray(int[] nums, int[] index) {int[] target new int[num…

The legacy JS API is deprecated and will be removed in Dart Sass 2.0

The legacy JS API is deprecated and will be removed in Dart Sass 2.0 更新了sass版本后&#xff0c;启动项目控制台一直在报错&#xff0c;影响开发效率&#xff0c;强迫症表示忍受不了。 字面意思是&#xff1a;Sass在2.0版本将会移除legacy JS API&#xff0c;所以现在使…

Python | Leetcode Python题解之第446题等差数列划分II-子序列

题目&#xff1a; 题解&#xff1a; class Solution:def numberOfArithmeticSlices(self, nums: List[int]) -> int:ans 0f [defaultdict(int) for _ in nums]for i, x in enumerate(nums):for j in range(i):d x - nums[j]cnt f[j][d]ans cntf[i][d] cnt 1return a…

Vue发送邮件攻略:从搭建到实现详细步骤?

vue发送邮件功能实现方法&#xff1f;Vue前端如何实现发送邮件&#xff1f; 随着应用功能的不断扩展&#xff0c;用户交互的复杂性也在增加。其中&#xff0c;发送邮件功能是许多Web应用中不可或缺的一部分。AokSend将详细介绍如何使用Vue.js实现发送邮件功能。 Vue发送邮件&…

fastadmin搜索刷新列表,怎么限制用户频繁点击?

文章目录 fastadmin搜索刷新列表&#xff0c;怎么限制用户频繁点击&#xff1f;解决方案fastadmin事件方法实现完结 fastadmin搜索刷新列表&#xff0c;怎么限制用户频繁点击&#xff1f; fastadmin目前有个很致命的问题&#xff0c;就是用户可以频繁的点击搜索等按钮&#xf…

基于SPRINTBOOT+VUE文献资料检索系统

文未可获取一份本项目的java源码和数据库参考。 1 选题背景 随着世界一体化和经济全球化席卷世界,越来越多的高校认识到&#xff0c;利用信息技术的发展来改变对文档、文献的运作方法和管理模式,提高高校的管理效益和生产效益&#xff0c;从而提高高校经济效益&#xff0c;增强…

大模型中的提示学习——情感预测示例项目

提示学习&#xff08;Prompting&#xff09;是一种自然语言处理&#xff08;NLP&#xff09;中的训练技术&#xff0c;它利用预训练的语言模型&#xff08;如BERT、GPT等&#xff09;来解决各种下游任务&#xff0c;如文本分类、命名实体识别、问答等。这种方法的关键思想是通过…

智能红外抄表系统的设计与实现(论文+源码)_kaic

摘 要 随着我国现代社会经济的快速发展&#xff0c;工厂居民用电量剧增。人工抄表&#xff0c;费时费力&#xff0c;效率低下。人工抄表会造成漏抄、误抄、估抄等数据不准确。抄表人员可能与用电户合伙作弊&#xff0c;给资产管理者带来损失。在很多智能仪表的应用中需要现场人…

麦克纳姆轮

一、B站: 一、运动原理 保留前进,平移和自转的车轮方向箭头,把反向变成红色 二、运动公式 如果已知需要的前后、左右、自转量。如何指示每个车轮旋转,用数学的方法表示反转,就是用负数,以平面直角坐标系为参照,向前是正,向后是负,向右是正,向左是负,自转…

云服务架构与华为云架构

目录 1.云服务架构是什么&#xff1f; 1.1 云服务模型 1.2 云部署模型 1.3 云服务架构的组件 1.4 云服务架构模式 1.5 关键设计考虑 1.6 优势 1.7 常见的云服务架构实践 2.华为云架构 2.1 华为云服务模型 2.2 华为云部署模型 2.3 华为云服务架构的核心组件 2.4 华…

【MySQL】视图、用户和权限管理

目录 视图创建视图数据修改影响删除视图视图优点 用户和权限管理查看当前的数据库拥有用户信息创建用户修改密码删除用户权限授权回收权限 视图 视图就是相当于创建一个表&#xff0c;将查询到的结果集给存储起来。像使用复杂的多表查询查询到的结果集就不可以对结果集操作。而…

Go语言中的深拷贝:概念、实现与局限

前不久&#xff0c;在“Gopher部落”知识星球[1]上回答了一个Gopher关于深拷贝(Deep Copy)的问题&#xff0c;让我感觉是时候探讨一下深拷贝技术了。 在日常开发工作中&#xff0c;深拷贝的使用频率相对较低&#xff0c;可能有80%的时间不需要使用深拷贝&#xff0c;只有在特定…

【PHP源码】匿名来信系统H5版本V1.0免费开源

你的匿名来信H5一封你的来信源码/表白祝福短信程序/往来信/传话短信源码支持邮件发信与手机短信发信“你的匿名来信”是最近某音上爆火的一个活动话题&#xff0c;可以通过H5网站&#xff0c;编辑自己想要对某人说的话或者祝福&#xff0c;网站会把您想说的发给您预留的号码&am…

免费语音转文字软件全览:开启高效记录新时代

在当今快节奏的信息时代&#xff0c;高效地处理和记录信息变得至关重要。语音转文字技术的出现&#xff0c;为我们带来了极大的便利&#xff0c;今天&#xff0c;就让我们一同探讨这些语音转文字免费的软件的使用方法。 1.365在线转文字 链接直达&#xff1a;https://www.pdf…

el-table添加fixed后错位问题

1 方案1 return {isShow:false, }mounted() {this.isShowtrue},watch: {$route(newRoute) {this.monitoredRoute newRoute; // 将新的路由信息保存到组件的monitoredRoute属性中// 执行其他操作或调用其他方法},//或$route(newRoute) {this.monitoredRoute newRoute; // 将新…