利用MQ事务消息实现分布式事务

MQ事务消息使用场景

消息队列中的“事务”,主要解决的是消息生产者和消息消费者的数据一致性问题。
拿我们熟悉的电商来举个例子。一般来说,用户在电商 APP 上购物时,先把商品加到购物车里,然后几件商品一起下单,最后支付,完成购物流程,就可以愉快地等待收货了。
这个过程中有一个需要用到消息队列的步骤,订单系统创建订单后,发消息给购物车系统,将已下单的商品从购物车中删除。因为从购物车删除已下单商品这个步骤,并不是用户下单支付这个主要流程中必需的步骤,使用消息队列来异步清理购物车是更加合理的设计。

在这里插入图片描述

对于订单系统来说,它创建订单的过程中实际上执行了 2 个步骤的操作:
1 在订单库中插入一条订单数据,创建订单;
2 发消息给消息队列,消息的内容就是刚刚创建的订单。

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

在分布式系统中,上面提到的这些步骤,任何一个步骤都有可能失败,如果不做任何处理,那就有可能出现订单数据与购物车数据不一致的情况,比如说:
创建了订单,没有清理购物车;
订单没创建成功,购物车里面的商品却被清掉了。

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

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

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

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

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

回到订单和购物车这个例子。

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

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

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

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

RocketMQ 中的分布式事务实现

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

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

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

这个反查本地事务的实现,并不依赖消息的发送方,也就是订单服务的某个实例节点上的任何数据。这种情况下,即使是发送事务消息的那个订单服务节点宕机了,RocketMQ 依然可以通过其他订单服务的节点来执行反查,确保事务的完整性。
综合上面讲的通用事务消息的实现和 RocketMQ 的事务反查机制,使用 RocketMQ 事务消息功能实现分布式事务的流程如下图:
在这里插入图片描述

很多人常有问题:为什么不等待订单创建成功再向消息队列发送订单数据呢?这样也不用考虑订单创建失败而发送消息的情况了。

如果先创建订单,当前服务由于不可抗拒因素不能正常工作了,没有给购物车系统发送消息,这种情况加就会出现订单已经创建并且购物车没有清空的情况。
如果是发送半消息这种情况,可以通过定期查询事务的状态然后根据然后具体的业务回滚操作或者重
新发送消息,保证数据的最终一致性。

代码实现和底层代码原理:RocketMQ源码分析 9.3 9.4 9.5

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

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

相关文章

2路 QSFP,40G 光纤的数据实时采集(5GByte/s 带宽)板卡设计原理图 -PCIE732

板卡概述 PCIE732 是一款基于 PCIE 总线架构的高性能数据传输卡,板卡具有 1 个 PCIex8 主机接口、2 个 QSFP40G 光纤接口,可以实现 2 路 QSFP 40G 光纤的数据实时采集、传输。板卡采用 Xilinx 的高性 能 Kintex UltraScale 系列 FPGA 作为实时处理器…

qiankun 微前端 demo(Vue2)

前言 这是我最近刚开始学微前端(qiankun框架)做的一个小demo,做的时候还是遇到很多问题的,在网上也是看了很多别人的Blog,最后也是磨出来了😂😂😂;这篇文章总统分为分为…

windows 编译 opencv

编译需要的基础工具 #cmake是配置构建工具,mingw是编译工具 cmake CMake是一款跨平台的编译管理工具,可以自动生成各种不同编译环境(如Makefile、Visual Studio Solution等),从而实现在不同平台上进行代码编译的目的…

Qwik 1.0 发布,全栈式 Web 框架

Qwik 是一个全栈式 Web 框架,Qwik 基于 React、Angular 和 Vue 等其他 Web 框架的概念,但以 JavaScript 流等更新的方法脱颖而出,允许以高性能向用户交付复杂的 Web 应用程序。 随着 Web 应用程序变得越来越大,它们的启动性能会下…

强烈推荐:一款中文AI问答、创作、绘画工具

前言 相信很多人已经听过ChatGPT这款人工智能机器人了,它能够根据用户输入的内容,自动生成智能回复。它使用自然语言处理技术,通过学习大量的文本资料,能够模拟人类的对话行为。它是由OpenAI开发的,一家非常伟大的人工…

Http知识

一、http协议 目前存在HTTP1.1(当前广泛运用的版本)、HTTP2.0和HTTP3.0协议,有以下的优点和缺点 1. HTTP1.1 优点:默认支持长连接,即在一个TCP连接上可以传送多个HTTP请求和响应,减少了建立和关闭连接的…

Flutter框架:从入门到实战,构建跨平台移动应用的全流程解析

第一章:Flutter框架介绍 Flutter框架是由Google推出的一款跨平台移动应用开发框架。相比其他跨平台框架,Flutter具有更高的性能和更好的用户体验。本章将介绍Flutter框架的概念、特点以及与其他跨平台框架的比较,以及Flutter开发环境的搭建和…

应急物流 | 灾后早期阶段多目标选址路径问题的混合元启发式算法

解读作者:李奡,闫同仁 A hybrid meta-heuristic algorithm for the multi-objective location-routing problem in the early post-disaster stage Tongren Yan, Fuqiang Lu, Suxin Wang, Leizhen Wang, Hualing Bi Journal of industrial and managem…

设计原则之【接口隔离原则】,我只做我能做的事

文章目录 一、什么是接口隔离原则二、实例三、总结接口隔离原则与单一职责原则的区别 一、什么是接口隔离原则 接口隔离原则(Interface Segregation Principle, ISP)是指用多个专门的接口,而不使用单一的总接口,客户端不应该依赖…

【中级软件设计师】—(下午题)试题三精讲总结(四十二)

【中级软件设计师】—(下午题)试题三精讲总结(四十二) 一、关系 二、UML中的图 A包含B,那么A执行操作前必须要先执行B 试题一(2021年下半年) 试题2(2021年上半年) 官方…

Docker中部署监控

Docker概念 一、部署Prometheus+grafana环境 1.1 、部署Prometheus+grafana环境 docker pull registry.cn-hangzhou.aliyuncs.com/lhrbest/lhrprometheus:1.0 docker tag registry.cn-hangzhou.aliyuncs.com/lhrbest/lhrprometheus:1.0 lhrbest/lhrprometheus:1.01.2 、创建镜…

linux 定时器

Linux 系统实现底半部的机制主要有tasklet,工作队列和软中断。 tasklet 和工作队列都是调度中断底半部的良好机制,tasklet 基于软中断实现。 内核定时器也依靠软中断实现;内核中的延时是忙等待或者睡眠等待,为了充分利用CPU资源&#xff0c…

docker 搭建 Elasticsearch和Kibana 8.x版本

参考: docker入门:单机elasticsearch安装记录,保证无坑_8月日更_小鲍侃java_InfoQ写作社区 新建文件夹 同上文所述相同,需要在宿主机上挂载配置文件与数据文件。 mkdir -p /Users/louye/data/learn-data/elastic/config mkdir -p /Users/lo…

从地方旅游的宣传谈起:如何吸引主流媒体报道,强势刷屏?

传媒如春雨,润物细无声,大家好,我是51媒体网胡老师。 五一小长假已经过去好几天了,大家渐渐的从假期舒适的闲暇转到正常的工作生活中了,但利用五一热点宣传的余温还在继续,今天胡老师就i注意到一篇题为&am…

华为nqa实验拓扑案例

nqa是一种实时的网络性能探测和统计技术,可以对响应时间、网络抖动、丢包率等网络信息进行统计。如图1所示,接口备份与NQA联动功能配置相对简单,只需在本端RouterA上配置NQA测试例,并在RouterA的备份接口上配置接口备份与NQA联动&…

重写Properties类,实现对properties文件的有序读写,数据追加,解决中文乱码

前言 *.properties文件,是 Java 支持的一种配置文件类型,并且 Java 提供了 properties 类来读取 properties 文件中的信息。文件中以键值对 "键值"的形式,存储工程中会多次重复使用的配置信息,通过“Properties”类来读…

4.Redis10大数据类型

Redis10大数据类型 Which 101.String(字符串)2.List(列表)3.hash (哈希)4.Set(集合)5.zset(sorted set:有序集合)6.Redis GEO (地理空间)7.HyperL…

Linux最常用的15个基本命令

目录 Linux基本命令 命令1:ls (查看指定目录中有哪些内容) ls / 相当于查看根目录中的内容,相当于查看我的电脑 ls -l(小写l,或者使用ll)详细查看目录下所有内容 ls /usr/lib&#xff08…

“AI代劳”,跨域赋能“智慧企业”

随着全球数字信息化的到来,各大新兴行业企业也逐渐意识到“智慧化”转型的重要性,但目前仍有不少企业在面临着人力成本高、运营管理效率低、营销获客效果差、数据分析能力薄弱等瓶颈,那么,处于这些瓶颈期的企业该如何实现“智慧化…

【Java零基础入门篇】第 ④ 期 - 继承(二)

博主:命运之光 专栏:JAVA入门 学习目标 1.掌握继承性的主要作用、实现、使用限制; 2.掌握this和super的含义及其用法; 3.掌握方法覆写的操作; 4.掌握final关键字的使用; 5.掌握类变量、实例变量和局部变量的…