消息队列(基础篇)-4 如何利用事务消息实现分布式事务?

电商项目-分布式事务(四)基于消息队列实现分布式事务 分布式事务,用户下单增加积分 阅读详情
AI摘要

本文探讨了消息队列在实现分布式事务中的作用,重点介绍了RocketMQ如何通过事务消息和事务反查机制来保证数据一致性。

很多场景下,我们“发消息”这个过程,目的往往是通知另外一个系统或者模块去更新数据,消息队列中的“事务”,主要解决的是消息生产者和消息消费者的数据一致性问题。

依然拿我们熟悉的电商来举个例子。一般来说,用户在电商 APP 上购物时,先把商品加到购物车里,然后几件商品一起下单,最后支付,完成购物流程,就可以愉快地等待收货了。

这个过程中有一个需要用到消息队列的步骤,订单系统创建订单后,发消息给购物车系统,将已下单的商品从购物车中删除。因为从购物车删除已下单商品这个步骤,并不是用户下单支付这个主要流程中必需的步骤,使用消息队列来异步清理购物车是更加合理的设计。

 

对于订单系统来说,它创建订单的过程中实际上执行了 2 个步骤的操作:

  1. 在订单库中插入一条订单数据,创建订单;
  2. 发消息给消息队列,消息的内容就是刚刚创建的订单。

购物车系统订阅相应的主题,接收订单创建的消息,然后清理购物车,在购物车中删除订单中的商品。

在分布式系统中,上面提到的这些步骤,任何一个步骤都有可能失败,如果不做任何处理,那就有可能出现订单数据与购物车数据不一致的情况,比如说:

  • 创建了订单,没有清理购物车;
  • 订单没创建成功,购物车里面的商品却被清掉了。

那我们需要解决的问题可以总结为:在上述任意步骤都有可能失败的情况下,还要保证订单库和购物车库这两个库的数据一致性。

对于购物车系统收到订单创建成功消息清理购物车这个操作来说,失败的处理比较简单,只要成功执行购物车清理后再提交消费确认即可,如果失败,由于没有提交消费确认,消息队列会自动重试。

问题的关键点集中在订单系统,创建订单和发送消息这两个步骤要么都操作成功,要么都操作失败,不允许一个成功而另一个失败的情况出现。

这就是事务需要解决的问题。

什么是分布式事务?

那什么是事务呢?如果我们需要对若干数据进行更新操作,为了保证这些数据的完整性和一致性,我们希望这些更新操作要么都成功,要么都失败。至于更新的数据,不只局限于数据库中的数据,可以是磁盘上的一个文件,也可以是远端的一个服务,或者以其他形式存储的数据。

这就是通常我们理解的事务。其实这段对事务的描述不是太准确也不完整,但是,它更易于理解,大体上也是正确的。所以我还是倾向于这样来讲“事务”这个比较抽象的概念。

一个严格意义的事务实现,应该具有 4 个属性:原子性、一致性、隔离性、持久性。这四个属性通常称为 ACID 特性。

原子性,是指一个事务操作不可分割,要么成功,要么失败,不能有一半成功一半失败的情况。

一致性,是指这些数据在事务执行完成这个时间点之前,读到的一定是更新前的数据,之后读到的一定是更新后的数据,不应该存在一个时刻,让用户读到更新过程中的数据。

隔离性,是指一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对正在进行的其他事务是隔离的,并发执行的各个事务之间不能互相干扰,这个有点儿像我们打网游中的副本,我们在副本中打的怪和掉的装备,与其他副本没有任何关联也不会互相影响。

持久性,是指一个事务一旦完成提交,后续的其他操作和故障都不会对事务的结果产生任何影响。

大部分传统的单体关系型数据库都完整的实现了 ACID,但是,对于分布式系统来说,严格的实现 ACID 这四个特性几乎是不可能的,或者说实现的代价太大,大到我们无法接受。

分布式事务就是要在分布式系统中的实现事务。在分布式系统中,在保证可用性和不严重牺牲性能的前提下,光是要实现数据的一致性就已经非常困难了,所以出现了很多“残血版”的一致性,比如顺序一致性、最终一致性等等。

显然实现严格的分布式事务是更加不可能完成的任务。所以,目前大家所说的分布式事务,更多情况下,是在分布式系统中事务的不完整实现。在不同的应用场景中,有不同的实现,目的都是通过一些妥协来解决实际问题。

在实际应用中,比较常见的分布式事务实现有 2PC(Two-phase Commit,也叫二阶段提交)、TCC(Try-Confirm-Cancel) 和事务消息。每一种实现都有其特定的使用场景,也有各自的问题,都不是完美的解决方案。

事务消息适用的场景主要是那些需要异步更新数据,并且对数据实时性要求不太高的场景。比如我们在开始时提到的那个例子,在创建订单后,如果出现短暂的几秒,购物车里的商品没有被及时清空,也不是完全不可接受的,只要最终购物车的数据和订单数据保持一致就可以了。

2PC 和 TCC 不是这次讨论的内容,就不展开讲了,感兴趣的同学可以自行学习。

消息队列是如何实现分布式事务的?

事务消息需要消息队列提供相应的功能才能实现,Kafka 和 RocketMQ 都提供了事务相关功能。

回到订单和购物车这个例子,我们一起来看下如何用消息队列来实现分布式事务。

首先,订单系统在消息队列上开启一个事务。然后订单系统给消息服务器发送一个“半消息”,这个半消息不是说消息内容不完整,它包含的内容就是完整的消息内容,半消息和普通消息的唯一区别是,在事务提交之前,对于消费者来说,这个消息是不可见的。

半消息发送成功后,订单系统就可以执行本地事务了,在订单库中创建一条订单记录,并提交订单库的数据库事务。然后根据本地事务的执行结果决定提交或者回滚事务消息。如果订单创建成功,那就提交事务消息,购物车系统就可以消费到这条消息继续后续的流程。如果订单创建失败,那就回滚事务消息,购物车系统就不会收到这条消息。这样就基本实现了“要么都成功,要么都失败”的一致性要求。

如果你足够细心,可能已经发现了,这个实现过程中,有一个问题是没有解决的。如果在第四步提交事务消息时失败了怎么办?对于这个问题,Kafka 和 RocketMQ 给出了 2 种不同的解决方案。

Kafka 的解决方案比较简单粗暴,直接抛出异常,让用户自行处理。我们可以在业务代码中反复重试提交,直到提交成功,或者删除之前创建的订单进行补偿。RocketMQ 则给出了另外一种解决方案。

RocketMQ 中的分布式事务实现

在 RocketMQ 中的事务实现中,增加了事务反查的机制来解决事务消息提交失败的问题。如果 Producer 也就是订单系统,在提交或者回滚事务消息时发生网络异常,RocketMQ 的 Broker 没有收到提交或者回滚的请求,Broker 会定期去 Producer 上反查这个事务对应的本地事务的状态,然后根据反查结果决定提交或者回滚这个事务。

为了支撑这个事务反查机制,我们的业务代码需要实现一个反查本地事务状态的接口,告知 RocketMQ 本地事务是成功还是失败。

在我们这个例子中,反查本地事务的逻辑也很简单,我们只要根据消息中的订单 ID,在订单库中查询这个订单是否存在即可,如果订单存在则返回成功,否则返回失败。RocketMQ 会自动根据事务反查的结果提交或者回滚事务消息。

这个反查本地事务的实现,并不依赖消息的发送方,也就是订单服务的某个实例节点上的任何数据。这种情况下,即使是发送事务消息的那个订单服务节点宕机了,RocketMQ 依然可以通过其他订单服务的节点来执行反查,确保事务的完整性。

综合上面讲的通用事务消息的实现和 RocketMQ 的事务反查机制,使用 RocketMQ 事务消息功能实现分布式事务的流程如下图:

小结

我们通过一个订单购物车的例子,学习了事务的 ACID 四个特性,以及如何使用消息队列来实现分布式事务。

然后我们给出了现有的几种分布式事务的解决方案,包括事务消息,但是这几种方案都不能解决分布式系统中的所有问题,每一种方案都有局限性和特定的适用场景。

最后,我们一起学习了 RocketMQ 的事务反查机制,这种机制通过定期反查事务状态,来补偿提交事务消息可能出现的通信失败。在 Kafka 的事务功能中,并没有类似的反查机制,需要用户自行去解决这个问题。

但是,这不代表 RocketMQ 的事务功能比 Kafka 更好,只能说在我们这个例子的场景下,更适合使用 RocketMQ。Kafka 对于事务的定义、实现和适用场景,和 RocketMQ 有比较大的差异,后面的课程中,我们会专门讲到 Kafka 的事务的实现原理。

【基础篇-消息队列】——如何利用事务消息实现分布式事务 本文探讨了消息队列如何实现分布式事务,以订单系统与购物车系统的数据一致性为例进行分析。传统事务的ACID特性在分布式系统中难以完全实现,因此出现了分布式事务的多种解决方案,包括2PC、TCC和事务消息。文章详细介绍了事务消息的实现机制,重点解析了RocketMQ通过"半消息"和事务反查机制来确保"要么都成功,要么都失败"的一致性要求。与Kafka相比,RocketMQ的事务反查功能能够自动处理提交失败的情况,但强调不同消息队列的事务实现各有适用场景。文章最后指出,分布 阅读详情

相关推荐

借助消息队列实现分布式事务解决方案

在后端开发中,分布式事务是一个常见的挑战。当系统的各个组件分布在不同的节点上时,保持数据的一致性和可靠性变得更加困难。然而,通过借助消息队列,我们可以实现一种有效的解决方案,用于处理分布式事务。消息队列是一种在不同组件之间传递消息的中间件。它提供了一种异步通信的方式,允许发送者将消息发送到队列中,然后接收者从队列中获取消息进行处理。这种异步通信的特性使得消息队列成为处理分布式事务的理想选择。下面我们将介绍如何使用消息队列来实现分布式事务,并提供相应的源代码。首先,我们需要选择一个合适的消息队列系统。

YOLOv7895的博客 315

分布式事务解决方案

分布式事务解决方案 1.分布式事务解决方案-面试 ​ 刚才编写的扣减库存与保存订单是在两个服务中存在的,如果扣减库存后订单保存失败了是不会回滚的,这样就会造成数据不一致的情况,这其实就是我们所说的分布式事务的问题,接下来我们来学习分布式事务的解决方案。 1.1 本地事务与分布式事务 1.1.1 事务 数据库事务(简称:事务,Transaction)是指数据库执行过程中的一个逻辑单位,由一个有限的数据库操作序列构成。 事务拥有以下四个特性,习惯上被称为ACID特性: 原子性(Atomicity):事务

1663988740 732

基于消息队列的分布式事务实现

1.背景介绍 在现代的互联网应用中,分布式系统已经成为了一种常见的架构模式。然而,分布式系统带来的高可用性和可扩展性的同时,也带来了一些新的挑战,其中之一就是如何处理分布式事务。传统的数据库事务模型在分布式环境中往往无法很好地工作,因此我们需要寻找新的解决方案。本文将介绍一种基于消息队列的分布式事务实现方法。

AI天才研究院 471

分布式事务完美解决方案:消息中间件(kafka)+ 本地事物 + 消息校对

采用消息队列技术实现分布式事务,旨在确保数据的最终一致性,即柔性事务。本次实践通过融合MQ、本地事务与消息校验机制来达成分布式事务处理目标。

ZYNORL的博客 2932

分布式事务的消息代理与消息队列

1.背景介绍 分布式事务是一种在多个独立系统之间进行协同工作的事务处理方式。在现代互联网应用中,分布式事务已经成为了常见的应用场景,例如微信支付、支付宝支付等。分布式事务的主要目标是确保多个独立系统之间的事务处理的一致性。 在分布式事务中,消息代理和消息队列是两个非常重要的技术手段。消息代理负责接收来自不同系统的消息,并将消息发送到相应的

AI天才研究院 1014

Amos实战:如何用Bootstrap法检验中介效应?附完整操作步骤

本文详细介绍了如何使用Amos软件通过Bootstrap法检验中介效应,包括模型设定、参数配置和结果解读。Bootstrap方法因其不依赖正态分布假设、统计功效高等优势,成为中介效应分析的首选方法。文章提供了完整的操作步骤和实用建议,帮助研究者准确评估变量间的中介作用机制。

zz67890的博客 1440

如何利用事务消息实现分布式事务?

那什么是事务呢?如果我们需要对若干数据进行更新操作,为了保证这些数据的完整性和一致性,我们希望这些更新操作**要么都成功,要么都失败。**至于更新的数据,不只局限于数据库中的数据,可以是磁盘上的一个文件,也可以是远端的一个服务,或者以其他形式存储的数据。这就是通常我们理解的事务。其实这段对事务的描述不是太准确也不完整,但是,它更易于理解,大体上也是正确的。所以我还是倾向于这样来讲“事务”这个比较抽象的概念。一个严格意义的事务实现,应该具有4个属性:原子性、一致性、隔离性、持久性。

qq_33240556的博客 1204

【电力系统】高压直流输电VSC-HVDC,四个变流站联合输电 / 交直流混合并网系统

本文研究了一种基于电压源型换流器(VSC)的高压直流输电(HVDC)系统,该系统通过四个变流站实现联合输电并接入交直流混合电网。文章介绍了系统的结构、工作原理以及控制策略,分析了交直流混合并网的特性,并通过仿真验证了系统的性能。结果表明,该系统具有良好的稳定性和灵活性,能够有效实现多点供电和功率协调。

2401_84610415的博客 2239

事务消息实现分布式事务

在电商系统中,用户下单后,订单系统需要通知购物车系统删除已购商品,这一过程通常通过消息队列实现,以确保数据一致性。分布式事务在此场景中至关重要,它确保订单创建和购物车清理要么都成功,要么都失败,避免数据不一致。分布式事务的实现通常遵循ACID原则,包括原子性、一致性、隔离性和持久性。常见的分布式事务实现方法有2PC、TCC和事务消息。事务消息适用于异步更新数据且对实时性要求不高的场景。消息队列如Kafka和RocketMQ提供了事务相关功能,通过事务消息机制实现分布式事务。例如,订单系统在创建订单后发送“半

weiye2012的博客 1283

基于PyTorch的BP神经网络PID控制器动态调参实战

本文详细介绍了基于PyTorch的BP神经网络PID控制器动态调参实战,结合BP神经网络的自适应能力和PID控制算法的经典优势,实现工业控制中的高效参数调整。通过PyTorch实现BP-PID融合架构,包括网络设计、损失函数优化及动态调参技巧,显著提升控制性能,适用于温度控制、电机控制等场景。

weixin_29094775的博客 522

SAGA GIS英文版进行地形分析,计算常用的地形因子等

SAGA GIS中文版是一款专业的自动化地球科学分析系统软件。SAGA GIS最新版界面简洁,操作简便,用户使用时输入要分割的影像,选择要计算特征的影像或者波段,设置越大,得到的斑块越大;反之,则越小,点击Okay,得到分割影像图。SAGA GIS中文版主要通过选择适合你影像的格式,加载影像。 SAGA GIS全称是System for Automated Geoscientific Analyses,是一种用于编辑空间数据的地理信息系统(GIS)计算机程序,它是免费的开源软件,SAGA GIS旨在为科学家

qq_35794085的博客 5645

通过消息队列实现分布式事务

事务是什么东西这里不进行细说,写这篇文章的目的也是因为前不久项目上使用到相关知识,在这里做此记录,其实所谓的分布式事务很好理解也非常简单 一、spring&spring boot下的事务实现(普通事务/基于单库的事务) 首先,我们了解一下spring boot下实现事务,这个相对而言很简单,直接可以通过注解去实现: @EnableTransactionManagement //开启事务管理,相当于在spring中加配置(<tx:annotation-driven />),在spring

qq_41751237的博客 2057

PCL 逐点插入法构建Delaunay三角网(C++详细过程版)

点云构建Delaunay三角网的逐点插入法基于PCL点云库的C++详细过程版实现

点云侠的博客 2992

基于消息队列实现分布式事务

背景 在用户购买商品后,需要给用户添加相应的积分,然而订单服务和用户服务是在两个服务当中的,如果订单确定后积分添加失败了订单是不会回滚的,这样就会造成数据不一致的情况,这其实就是我们所说的分布式事务的问题。 本地事务与分布式事务 本地事务 起初,事务仅限于对单一数据库资源的访问控制,架构服务化以后,事务的概念延伸到了服务中。倘若将一个单一的服务操作作为一个事务,那么整个服务操作只能涉及一个单一的数据库资源,这类基于单个服务单一数据库资源访问的事务,被称为本地事务(Local Transaction)。 分布

yjh258753的博客 1550

自己的搭建的slam机器人建图导航测试

1、前言 这里是对自己搭建的slam机器人建图导航的功能测试,原本并不想写这一篇的,因为每个小伙伴的需求都不一样,但是发现还是有同学有需求,于是就有了这一篇。本篇属于说明分享类文章,不涉及细节解释。按照步骤操作即可。 本次测试需要建图算法my_slam_gmapping、导航框架navigation、以及explore_lite功能包、mbot_teleop键盘控制功能包等。 环境:ubuntu mate 16.04 + ROS Kinetic 功能包下载:在公众号:小白学移动机器人,发送:建图导航测试,即

「小白学移动机器人」一个专注分享移动机器人相关知识的公众号! 8702

SAP-ABAP:ABAP 开发基础概念入门:写给刚踏入 SAP 开发世界的新人

本文介绍了 ABAP 开发语言的基础概念,帮助 SAP 开发新人快速入门。主要内容包括: ABAP 的发展历程与核心优势 - 作为 SAP 平台的专属语言,ABAP 在企业级应用开发中具有深度集成、数据处理高效和长期稳定的特点 ABAP 开发环境概览 - 介绍了 SE38、SE80 等关键事务码,以及 ABAP 工作台的核心组件和开发权限管理 基础语法入门 - 重点讲解了 ABAP 特有的数据类型体系(特别是结构体和内表),并通过 Hello World 示例展示程序基本结构 文章通过对比 ABAP 与 J

baidu_35680696的博客 511

分布式事务三:基于kafka本地消息分布式事务实现

声明: 本篇主要对所用到的技术做了归纳总结,对源码讲解较少,如果有基础的朋友可直接下载源码结合时序图更能容易理解;基础比较弱的朋友建议先看看资料自看源码这样更容易理解。这里的部分资料来源于网络,所以这里对那些资料提供者表达衷心的感谢。 此方案其核心思想是将分布式事务拆分成本地事务进行处理。通过在消费者额外新建事务消息表,消费者处理业务和记录事务消息在本地事务中完成,轮询事务消息表的数据发送事务...

HACKERRONGGE的博客 4898

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

利用消息队列实现分布式事务

引言 听说公司上批员工入职培训有这么一个小demo 之前分布式这块接触比较少,于是尝试做了一下 这边技术选型springcloud,kafka,mysql,docker,quartz 思路分析 首先描述下我这边的场景,也是很常见的一个异步调用场景: 即将服务A假设为某电商用户模块,服务B假设为电商活动模块。 我这边呢,假设用户支付多少钱,就返多少钱的一个代金券 一致性解决 梳理一下流程,上面这一版有一个致命的问题!如下所示事务开始(1)给alili账户扣100元 (2)给alili账户

alili0619的博客 1908

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

RabbitMQ-使用消息队列实现分布式事务

前阵子从支付宝转账1万块钱到余额宝,这是日常生活的一件普通小事,但作为互联网研发人员的职业病,我就思考支付宝扣除1万之后,如果系统挂掉怎么办,这时余额宝账户并没有增加1万,数据就会出现不一致状况了。 上述场景在各个类型的系统中都能找到相似影子,比如在电商系统中,当有用户下单后,除了在订单表插入一条记录外,对应商品表的这个商品数量必须减1吧,怎么保证?!在搜索广告系统中,当用户点击某广告后,除了在...

liberty12345678的专栏 9554

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

RocketMQ事务消息实现分布式事务

使用RocketMQ事务消息实现分布式事务

学习记录和总结 1万+

04 | 如何利用事务消息实现分布式事务?

那什么是事务呢?如果我们需要对若干数据进行更新操作,为了保证这些数据的完整性和一致性,我们希望这些更新操作要么都成功,要么都失败。至于更新的数据,不只局限于数据库中的数据,可以是磁盘上的一个文件,也可以是远端的一个服务,或者以其他形式存储的数据。这就是通常我们理解的事务。其实这段对事务的描述不是太准确也不完整,但是,它更易于理解,大体上也是正确的。所以我还是倾向于这样来讲“事务”这个比较抽象的概念。一个严格意义的事务实现,应该具有 4 个属性:原子性、一致性、隔离性、持久性。

qq_37756660的博客 1295

用消息队列和消息应用状态表来消除分布式事务

由于数据量的巨大,大部分Web应用都需要部署很多个数据库实例。这样,有些用户操作就可能需要去修改多个数据库实例中的数据。传统的解决方法是使用分布式事务保证数据的全局一致性,经典的方法是使用两阶段提交协议。 长期以来,分布式事务提供的优雅的全局ACID保证麻醉了应用开发者的心灵,很多人都不敢越雷池一步,想像没有分布式事务的世界会是怎样。如今就如MySQL和PostgreSQL这类面向低端用户的开源

it_man的专栏 1万+

基于消息队列的分布式事务解决方案

前两天发了工资,第一反应是想着要给远方的女朋友一点惊喜!于是打开了平安银行的APP给女朋友转点钱!填写上对方招商银行卡的卡号、开户名,一键转账!搞定!在我点击的那瞬间,就收到了app的账户变动的提醒,并且出现了图一所示的提示界面:“处理中,正在等待对方银行返回结果…”。嗯!毕竟是跨行转账嘛,等个几秒也正常!脑海开始浮现出女朋友收到转账后惊喜与感动的画面!       然而,一切并没有那么顺...

m0_37477061的博客 1677
上一篇: 消息队列(基础篇)- 3 主题和队列有什么区别
下一篇: 消息队列(基础篇)-5 如何确保消息不会丢失?
木木那年
博客等级 码龄12年 37粉丝 36原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值