什么是分布式事务?

典型回答

分布式事务是指在分布式系统中涉及到多个数据库或多个应用程序之间的事务处理,这些数据库或应用程序可能分布在不同的物理节点上,甚至可能位于不同的地理位置。在分布式事务中,需要确保所有参与者的事务操作都能够保持一致性,即所有参与者的事务要么全部提交成功,要么全部回滚。
举个例子,假设一个电商系统,用户下单后需要扣减库存、扣减账户余额、生成订单等操作。在单机环境下,可以将这些操作放在同一个事务中,保证原子性、一致性和持久性。但在分布式环境下,可能存在多个服务(如库存服务、账户服务、订单服务)分布在不同的物理节点上,此时需要确保所有服务操作的事务都能够同步进行,避免出现数据不一致的情况。

为了解决分布式事务的问题,出现了一些分布式事务解决方案,如XA协议、TCC事务、最大努力通知等。这些解决方案的实现方式各不相同,但都需要考虑如何确保所有参与者的事务操作能够保持一致性,以及如何处理可能出现的异常情况。

常见的分布式事务有哪些?

分布式事务的目的是保证分布式系统中的多个参与方的数据能够保证一致性。即所有参与者,在一次写操作过程中要么都成功,要么都失败。
至于这个一致性到底是怎样的一致性,是强一致性、还是最终一致性,不同的分布式事务方案其实达到的效果并不相同。
如果想要实现强一致性,那么就一定要引入一个协调者,通过协调者来协调所有参与者来进行提交或者回滚。所以,这类方案包含基于XA规范的二阶段及三阶段提交、以及支持2阶段提交。

1、有了2阶段提交为什么还需要3阶段提交?

阶段提交(Two-phaseCommit)是XA分布式事务中一个重要的方案,二阶段提交的算法思路可以概括为:参与者将操作成败通知协调者,再由协调者根据所有参与者的反馈情报决定各参与者是否要提交操作还是中止操作。
所谓的两个阶段是指:第一阶段:准备阶段(投票阶段)和第二阶段:提交阶段(执行阶段)。但是2PC本身存在着同步阻塞问题、单点故障问题、数据不一致问题等,所以在二阶段的基础上,增加了一个预提交的阶段,组成了3阶段提交的方案。


如果想要实现最终一致性,那么方案上就比较简单,常见的基于可靠消息的最终一致性(本地消息表、事务消息)、最大努力通知等


如何基于本地消息表实现分布式事务?

本地消息表其实也是借助消息来实现分布式事务的。
这个方案的主要思想是将分布式事务拆分为本地事务和消息事务两个部分,本地事务在本地数据库中进行提交或回滚,而消息事务则将消息写入消息中间件中,以实现消息的可靠投递和顺序性。
般来说的做法是,在发送消息之前,先创建一条本地消息,并且保证写本地业务数据的操作,和,写本地消息记录的操作在同一个事务中。这样就能确保只要业务操作成功,本地消息一定可以写成功。

然后再基于本地消息,调用MQ发送远程消息。
消息发出去之后,等待消费者消费,在消费者端,接收到消息之后,做业务处理,处理成功后再修改本地消息表的状态。
这个过程中,可能有几个步骤都可能发生失败,那么如果失败了怎么办呢?

1、2如果失败,因为在同一个事务中,所以事务会回滚,3及以后的步骤都不会执行。数据是一致的。
3如果失败,那么就需要有一个定时任务,不断的扫描本地消息数据,对于未成功的消息进行重新投递
5如果失败,则依靠消息的重投机制,不断地重试。
6、7如果失败,那么就相当于两个分布式系统中的业务数据已经一致了,但是本地消息表的状态还是错的。这种情况也可以借助定时任务继续重投消息,让下游幂等消费再重新更改消息状态,或者本系统也可以通过定时任务去查询下游系统的状态,如果已经成功了,则直接推进消息状态即可。


可靠消息实现最终一致性的方案其实就是借助支持事务消息的中间件,通过发送事务消息的方式来保证最终一致性,过程及原理可以参考:

RocketMQ的事务消息是如何实现的?

RocketMQ的事务消息是通过TransactionListener接囗来实现的。
在发送事务消息时,i首先向RocketMQ Broker发送一条“half消息”(即半消息),半消息将被存储在Broker端的事务消息日志中,但是这个消息还不能被消费者消费。
接下来,在半消息发送成功后,应用程序通过执行本地事务来确定是否要提交该事务消息。
如果本地事务执行成功,就会通知RocketMQ Broker提交该事务消息,使得该消息可以被消费者消费;否则,就会通知RocketMQ Broker回滚该事务消息,该消息将被删除,从而保证消息不会被消费者消费。

拆解下来的话,主要有以下4个步骤:

  1. 发送半消息:应用程序向RocketMQ Broker发送一条半消息,该消息在Broker端的事务消息日志中被标记为prepared”状态.
  2. 执行本地事务:RocketMO会通知应用程序执行本地事务。如果本地事务执行成功,应用程序通知RocketMQ Broker提交该事务消息,
  3. 提交事务消息:RocketMO收到提交消息以后,会将该消息的状态从“prepared”改为“committed”,并使该消息可以被消费者消费,
  4. 回滚事务消息:如果本地事务执行失败,应用程序通知RocketMQ Broker回滚该事务消息,RocketMQ将该消息的状态从“prepared”改为“rollback”,并将该消息从事务消息日志中删除,从而保证该消息不会被消费者消费。

另外,还有我们比较熟知的TCC,他也是最终一致性的一种实现方案。只不过他比基于消息的最终一致性要稍微更加靠近强一致性一些。或者说他的不一致性的时长会更短。

什么是TCC,和2PC有什么区别?

TCC是Try-Confirm-Cancel的缩写,它是一种分布式事务解决方案,采用了基于业务逻辑的补偿机制,将整个分布式事务分解为若干个子事务,每个子事务都有一个try、confirm和cancel三个操作,通过这些操作来实现分布式事务的执行和回滚

具体来说,TCC事务包括以下三个步骤:

  1. Try:在try阶段,参与者尝试执行本地事务,并对全局事务预留资源。如果try阶段执行成功,参与者会返回一个成功标识,否则会返回一个失败标识。
  2. Confirm:如果所有参与者的try阶段都执行成功,则协调者通知所有参与者提交事务,那么就要执行confirm阶段,这时候参与者将在本地提交事务,并释放全局事务的资源
  3. Cancel:如果任何一个参与者在try阶段执行失败,则协调者通知所有参与者回滚事务。那么就要执行cancel阶段。

以下是一个简单的TCC事务的例子,假设有一个转账服务,需要从A账户中转移到B账户中100元、C账户中200元:

  1. Try阶段:转账服务首先尝试将A账户的金额冻结300元
  2. Confirm阶段:如果所有的try操作都执行成功,转账服务将尝试执行解冻并转账,将金额转到B账户和C账户中
  3. Cancel阶段:如果try过程中,某个转账事务执行失败。那么将执行解冻,将300元解冻。如果在confirm过程中,A->C的转账成功,但是A->B的转账失败,则再操作一次C->A的转账,将钱退回去。

TCC这种事务方案有以下优缺点:

优点:

  1. 灵活性:TCC适用于不同类型的业务场景,例如账户转账、库存扣减等,能够根据业务逻辑实现精细的事务控制。
  2. 高可用性:TCC使用分布式锁来保证分布式事务的一致性,即使其中一个节点出现故障,也不会影响整个系统的运行。
  3. 可扩展性:TCC采用分阶段提交的方式,支持向扩展,可以适应更多的并发访问和业务场景。4.性能:TCC相对于2PC来说,具有更好的性能表现

缺点:

  1. 实现复杂:TCC需要实现Try、Confirm和Cancel三个操作,每个操作都需要实现正确的业务逻辑和补偿机制,代码实现比较复杂。
  2. 存在悬挂事务问题:TCC的实现方式存在悬挂事务的问题,即在执行过程中可能会有部分子事务成功,而其他子事务失败,导致整个事务无法回滚或提交。
  3. 空回滚问题:TCC中的Try过程中,有的参与者成功了,有的参与者失败了,这时候就需要所有参与者都执行Cancel,这时候,对于那些没有Ty成功的参与者来说,本次回就是一次空回滚。需要在业务中做好对空回滚的识别和处理,否则就会出现异常报错的情况,甚至可能导致Cancel一直失败,最终导致整个分布式事务失败。
  4. 业务代码侵入性:TCC需要将事务操作拆分为Try、Confirm和Cancel三个步骤,对业务代码有一定的侵入性,需要针对不同的业务场景进行实现。

另外,还有一些分布式事务的组件,如Seata,他其实是一个开源的分布式事务解决方案,旨在为微服务架构提供高效且透明的事务管理。在讨论 Seata 的一致性特性时,需要明确其支持的不同事务模式,因为每种模式对一致性的保证不同。

什么是Seata?他有哪几种模式?

Seata是一个阿里开源的分布式事务解决方案(Simple Extensible Autonomous Transaction Architecture)用于在分布式系统中实现分布式事务。它旨在简化分布式事务的开发和管理,帮助解决分布式系统中的数据一致性问题。

Seata的实现原理

因为Seata的开发者坚定地认为:一个分布式事务是有若干个本地事务组成的。所以他们给Seata体系的所有组件定义成了三种,分别是Transaction Coordinator、Transaction Manager和Resource Manager
[ransaction Coordinator(TC):这是一个独立的服务,是一个独立的JM 进程,里面不包含任何业务代码,它的主要职责:维护着整个事务的全局状态,负责通知 RM 执行回滚或提交;
[ransaction Manager(TM):在微服务架构中可对应为聚合服务,即将不同的微服务组合起来成一个完成的业务流程,TM 的职责是开启一个全局事务或者提交或回滚一个全局事务;
Resource Manager(RM):RM 在微服务框架中对应具体的某个微服务为事务的分支,RM 的职责是:执行每个事务分支的操作。

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

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

相关文章

三步学会苹果手机怎么关震动的方法!

苹果手机的震动功能在某些情况下可能会被认为是不必要的,比如在会议、课堂或者晚间睡眠时。因此,学会如何关闭苹果手机的震动功能是非常实用的。苹果手机怎么关震动?在本文中,我们将介绍三个步骤,帮助你关闭苹果手机的…

XSS-Labs 靶场通过解析(下)

前言 XSS-Labs靶场是一个专门用于学习和练习跨站脚本攻击(XSS)技术的在线平台。它提供了一系列的实验场景和演示,帮助安全研究人员、开发人员和安全爱好者深入了解XSS攻击的原理和防御方法。 XSS-Labs靶场的主要特点和功能包括:…

K邻算法:在风险传导中的创新应用与实践价值

程序员的实用神器 ⛳️ 写在前面参与规则!!! ✅参与方式:关注博主、点赞、收藏、评论,任意评论(每人最多评论三次) ⛳️本次送书1~4本【取决于阅读量,阅读量越多,送的越…

Python 中使用私有成员的子类化

1、问题背景 Python 语言中,变量名与访问器同名是一个非常好的特性: self.__value 1def value():return self.__value但是,当我们想要子类化一个类,并访问其私有成员时,却没有一种简单的方法。通常,我们…

使用Spring Boot构建RESTful API的最佳实践

在使用Spring Boot构建RESTful API时,遵循一些最佳实践可以帮助你创建可维护、可扩展且安全的应用程序。以下是一些关键的最佳实践: ### 1. 使用Spring Initializr开始项目 Spring Initializr([https://start.spring.io/](https://start.spr…

接收文件(文件上传)

前端的请求内容 Content-Type: multipart/form-data; form-data; name"filedata"; filename"具体的文件名称" 后端定义接口 ApiOperation("文件上传接口")RequestMapping(value "/upload/coursefile", consumes MediaType.MULTIPA…

发挥企业力量,美乐家推动城市绿色发展

在当今时代,环保已成为衡量企业社会责任的重要标准之一。美乐家作为一个具有前瞻性的企业,深刻理解到这一点,并通过其行动积极展示了这种责任感。通过与中华环境保护基金会合作,美乐家开始全国范围内推动了“微行动,守…

C语言 | Leetcode C语言题解之第74题搜索二维矩阵

题目&#xff1a; 题解&#xff1a; bool searchMatrix(int** matrix, int matrixSize, int* matrixColSize, int target) {int m matrixSize, n matrixColSize[0];int low 0, high m * n - 1;while (low < high) {int mid (high - low) / 2 low;int x matrix[mid /…

等保测评—Linux-CentOS标准范例截图

密码输入错误无法登录 用户账户情况包含root、guanli、shenji 查看审计用户权限 身份鉴别&#xff1a; cat /etc/passwd&#xff0c;核查用户名和 UID&#xff0c;是否存在同样的用户名和 UID cat /etc/shadow&#xff0c;查看文件中各用户名状态 &#xff0c; 核查密码一栏为…

Springboot工程创建

目录 一、步骤 二、遇到的问题及解决方案 一、步骤 打开idea,点击文件 ->新建 ->新模块 选择Spring Initializr&#xff0c;并设置相关信息。其中组为域名&#xff0c;如果没有公司&#xff0c;可以默认com.example。点击下一步 蓝色方框部分需要去掉&#xff0c;软件包…

Win11安装Docker Desktop运行Oracle 11g 【详细版】

oracle docker版本安装教程 步骤拉取镜像运行镜像进入数据库配置连接数据库&#xff0c;修改密码Navicat连接数据库 步骤 拉取镜像 docker pull registry.cn-hangzhou.aliyuncs.com/helowin/oracle_11g运行镜像 docker run -d -p 1521:1521 --name oracle11g registry.cn-ha…

React常用组件分享

1、轮播组件&#xff1a; React Awesome Slider React Slider Carousel Component - react-awesome-slider

一起深度学习24/04/30——ResNet

ResNet神经网络 定义ResNet Block定义ResNet18加载数据集并训练、测试 定义ResNet Block ResNet Block 的作用&#xff1a; 是一个残差块&#xff0c;用于构建ResNet 主要是为了解决神经网络中的梯度爆炸和梯度消失问题&#xff0c;以及缓解训练过程中的退化问题。 在传统的神经…

【Spring Security注解详解】

Spring Security 是一个强大的、高度可定制的身份验证和访问控制框架&#xff0c;广泛用于Java应用程序中以确保安全。它提供了多种注解来简化安全控制的实现&#xff0c;特别是在方法级别的权限控制上。以下是几个核心的Spring Security注解及其用途的详细介绍&#xff1a; 1…

MySQL动态列转行

介绍​​ 在实际的数据库查询中&#xff0c;有时候我们需要将表中的动态列&#xff08;即列数不固定&#xff09;转换为行&#xff0c;以便更好地进行数据分析和展示。在MySQL中&#xff0c;可以通过使用一些技巧和函数来实现动态列转行的功能。本文将介绍怎么实现MySQL动态列…

提升执行力的方法论

2024-5-7记录于PR办公室 一个关于求职的节目&#xff0c;提到如果在一个岗位做了多年&#xff0c;不论你是产品经理或项目经理&#xff0c;是否总结出一套产品/项目/研发的方法论。就这件事&#xff0c;我咨询过一个C语言大师星哥&#xff0c;他是这样说的:一件事在不同的时间段…

Arralist训练之罗马字符转换

1.1.1题目&#xff1a; /*键盘录用一个字符串 要求1.长度小于等于9 要求2.只能是数字 将阿拉伯数字与罗马数字对应 注意的是罗马数字里面没有0 1.1.2思路: 把题目分解成小目标 1.键盘录用一个字符串 2.要求 1.长度小于等于9 2.只能是数字 3.将阿拉伯数字与罗马数字对应…

延时任务通知服务的设计及实现(三)-- JDK的延迟队列DelayQueue

一、接着上文 上文我们讲述了使用redisson的RDelayedQueue实现分布式延迟队列&#xff0c;本文我们将自己JDK的延迟队列DelayQueue实现。 相比前者的实现&#xff0c;作为进程内的延迟队列&#xff0c;它会遇到许多技术难点&#xff1a; 如何支持分布式的多个节点部署场景应…

Android Native内存泄漏检测方案详解

文章目录 1. AddressSanitizer (ASan)2. LeakSanitizer (LSan)3. Valgrind4. 手动检测5. 实践建议6. 总结 在Android Native层开发过程中&#xff0c;内存泄漏是一个常见的问题。内存泄漏不仅会导致应用程序占用越来越多的内存&#xff0c;还可能引发性能问题和崩溃。因此&…

Game Theory In Competitive Programming|Part2(原创)

在上一个Part部分&#xff0c;我们介绍了Bash game、Nim game、Misere Nim game 这三个游戏的玩法、必胜策略&#xff0c;以及必胜策略的证明&#xff0c;并介绍了有关必胜态以及必败态的两条定理&#xff0c;接下来我们会以Part1为基础&#xff0c;深挖其中的理论。 文章目录 …