带你读懂事务(下)、分布式事务

简介: 带你读懂事务(下)、分布式事务

上篇文章我们说了事务的基本概念,以及事务的几种隔离级别,但是说的都是单机事务。随着现在微服务的流行,很多时候我们需要考虑的事务,往往都不再是单节点的事务,这种分布式的事务给我们造成了很大的麻烦,事实上这也是微服务中比较难处理的问题。我们先来看下现在业界分布式事务的解决方案都有哪些:


两阶段提交(2PC)


两阶段提交,就是把原本的事务拆解成了准备阶段和提交阶段这两个阶段(prepare和commit/rollback),在这个阶段中,需要额外的事务管理者TM(Transaction Manager)来对事务的状态进行管理,各个分支事务参与方则称为RM(Resource Manager),这个阶段的流程如下:


1686815847602.png


我们可以看到,当各个RM的prepare动作成功之后,便向TM发出ok的信息,TM收到RM ok的信息之后,认为事务已经可以提交,就向各个TM发出提交的命令。在这个过程中,如果有任何一个prepare动作失败或者是commit失败,都会导致最终的rollback。


TCC


TCC是一种采用了补偿机制的事务,它把事务分成了以下三个阶段:

  • Try 阶段:主要是对业务系统做检测及资源预留
  • Confirm 阶段:主要是对业务系统做确认提交,Try阶段执行成功并开始执行 Confirm阶段时,默认 Confirm阶段是不会出错的。即:只要Try成功,Confirm一定成功。
  • Cancel 阶段:主要是在业务执行错误,需要回滚的状态下执行的业务取消,预留资源释放

我们举个例子,假如说现在有一个业务流程是电商的付款之后扣库存,则这里涉及到了订单和库存服务,那么如果要使用TCC的话,业务都需要做什么改造


订单服务
try:设置一个中间状态,来表示用户正在支付中
confirm:将状态改为支付成功
cancel:把订单设置为取消
库存服务
try:先用一个冻结库存字段保存冻结库存数,而不是直接扣掉库存
confirm:扣掉库存并清除冻结库存的记录
cancel:把库存加回去


我们可以看出来,TCC和2PC看起来很相似,都是分为了两个阶段去提交,但是实际运用上还是有相当的差别。2PC是XA的标准实现,这种解决方案多数都是需要数据库层面的支持的,因此2PC其实是强一致性事务,因此锁的时间会比较长,高并发之下会有性能问题。TCC的话,由于有中间状态,一致性会差一些,但是性能相对比较友好,只不过对业务的侵入性太大了,需要比较高的改造成本。


本地消息表


这种解决方案其实是基于base理论的,base理论是指Basically Available(基本可用的),Soft state(软状态),Eventual consistency(最终一致性)。它最开始是由eBay提出的,基本思路如下:

消息生产方,需要额外建一个消息表,并记录消息发送状态。消息表和业务数据要在一个事务里提交,也就是说他们要在一个数据库里面。然后消息会经过MQ发送到消息的消费方。如果消息发送失败,会进行重试发送。

消息消费方,需要处理这个消息,并完成自己的业务逻辑。此时如果本地事务处理成功,表明已经处理成功了,如果处理失败,那么就会重试执行。如果是业务上面的失败,可以给生产方发送一个业务补偿消息,通知生产方进行回滚等操作。

生产方和消费方定时扫描本地消息表,把还没处理完成的消息或者失败的消息再发送一遍。如果有靠谱的自动对账补账逻辑,这种方案改造成本相对较低,并且还能够很容易的做成通用能力,因此也是现在使用的比较多的。

事务消息

事务消息则需要引入mq,它的流程如下:


主流程
 (1) 发送消息(half消息)。
 (2) 服务端响应消息写入结果。
 (3) 根据发送结果执行本地事务(如果写入失败,此时half消息对业务不可见,本地逻辑不执行)。
 (4) 根据本地事务状态执行Commit或者Rollback(Commit操作生成消息索引,消息对消费者可见)
补偿流程
 (1) 对没有Commit/Rollback的事务消息(pending状态的消息),从服务端发起一次“回查”
 (2) Producer收到回查消息,检查回查消息对应的本地事务的状态
 (3) 根据本地事务状态,重新Commit或者Rollback


这种方案比较依赖mq的可靠性,如果要采用这种方案,建议mq选型RocketMq。


FMT(FrameWork Managed Transactions)

这是一个比较特殊的分布式事务解决方案,因为这种方式把分布式事务的处理完全交给了框架,比较典型的是Seata的At模式,这种模式完全不需要修改代码,只需要加上一个注解在事务方法上,就可以完成分布式事务。其原理是业务数据提交时,自动拦截所有的SQL,分别保存SQL对数据修改前后的快照,如果分布式事务成功了,那我们后续只需清理每个数据源中对应的日志数据即可。如果分布式事务需要回滚,就要根据日志数据自动产生用于补偿的逆向SQL。

优点是业务代码改造量是非常小的,但是缺点也很明显,一是性能损耗比较明显,每次修改都需要插入一条log,二是复杂的sql就不能搞得定了。


其他

这里面都是一些用的比较少的,比如3PC,这种方案目前还几乎只存在于理论中,因为不好落地且不实用。

相关实践学习
RocketMQ一站式入门使用
从源码编译、部署broker、部署namesrv,使用java客户端首发消息等一站式入门RocketMQ。
消息队列 MNS 入门课程
1、消息队列MNS简介 本节课介绍消息队列的MNS的基础概念 2、消息队列MNS特性 本节课介绍消息队列的MNS的主要特性 3、MNS的最佳实践及场景应用 本节课介绍消息队列的MNS的最佳实践及场景应用案例 4、手把手系列:消息队列MNS实操讲 本节课介绍消息队列的MNS的实际操作演示 5、动手实验:基于MNS,0基础轻松构建 Web Client 本节课带您一起基于MNS,0基础轻松构建 Web Client
目录
相关文章
|
4天前
|
运维 监控 Java
Spring Cloud Alibaba分布式事务问题之事务commit失败如何解决
Spring Cloud Alibaba提供了一套在Spring Cloud框架基础上构建的微服务解决方案,旨在简化分布式系统的开发和管理;本合集将探讨Spring Cloud Alibaba在实际应用中的部署和使用技巧,以及该框架常见问题的诊断方法和解决步骤。
|
8月前
|
Oracle 关系型数据库 分布式数据库
OBCP第五章 分布式事务高级技术-分布式两阶段提交
OBCP第五章 分布式事务高级技术-分布式两阶段提交
74 0
|
8月前
|
Oracle 关系型数据库 MySQL
第四章:OceanBase集群技术架构(分布式事务、MVCC、事务隔离级别)
第四章:OceanBase集群技术架构(分布式事务、MVCC、事务隔离级别)
279 0
|
8月前
|
消息中间件 存储 中间件
常用本地事务和分布式事务解决方案模型 2
常用本地事务和分布式事务解决方案模型
51 1
|
8月前
|
算法 关系型数据库 API
常用本地事务和分布式事务解决方案模型 1
常用本地事务和分布式事务解决方案模型
46 1
|
4天前
|
消息中间件 Dubbo 应用服务中间件
分布式事物【Hmily实现TCC分布式事务、Hmily实现TCC事务、最终一致性分布式事务解决方案】(七)-全面详解(学习总结---从入门到深化)
分布式事物【Hmily实现TCC分布式事务、Hmily实现TCC事务、最终一致性分布式事务解决方案】(七)-全面详解(学习总结---从入门到深化)
90 0
|
8月前
|
SQL OceanBase Python
OBCP第五章 分布式事务高级技术-分布式两阶段提交
OBCP第五章 分布式事务高级技术-分布式两阶段提交
138 0
|
4天前
|
Dubbo 应用服务中间件 微服务
分布式事物【Hmily实现TCC分布式事务、Hmily实现TCC事务、最终一致性分布式事务解决方案】(七)-全面详解(学习总结---从入门到深化)(上)
分布式事物【Hmily实现TCC分布式事务、Hmily实现TCC事务、最终一致性分布式事务解决方案】(七)-全面详解(学习总结---从入门到深化)
52 1
|
4天前
|
消息中间件 Java 关系型数据库
Spring事务与分布式事务
这篇文档介绍了事务的概念和数据库事务的ACID特性:原子性、一致性、隔离性和持久性。在并发环境下,事务可能出现更新丢失、脏读和不可重复读等问题,这些问题通过设置事务隔离级别(如读未提交、读已提交、可重复读和序列化)来解决。Spring事务传播行为有七种模式,影响嵌套事务的执行方式。`@Transactional`注解用于管理事务,其属性包括传播行为、隔离级别、超时和只读等。最后提到了分布式事务,分为跨库和跨服务两种情况,跨服务的分布式事务通常通过最终一致性策略,如消息队列实现。
|
4天前
|
消息中间件 RocketMQ Docker
分布式事物【RocketMQ事务消息、Docker安装 RocketMQ、实现订单微服务、订单微服务业务层实现】(八)-全面详解(学习总结---从入门到深化)
分布式事物【RocketMQ事务消息、Docker安装 RocketMQ、实现订单微服务、订单微服务业务层实现】(八)-全面详解(学习总结---从入门到深化)
58 0