-
2021-03-07 22:01:48
什么是分布式事务
在大的操作集合中,所有的小操作都属于不同的服务器,不同的应用,分布式事务需要保证这些小操作要么一起成功,要么一起失败。本质上,分布式事务为了保证数据的一致性
分布式事务产生的原因
数据库分库分表(当一个操作需要访问01库又要访问02库的时候就会有这个问题)
SOA服务化(所有业务拆分到不同的模块中,数据存储在不同的服务器中,所以需要用到分布式事务)
ACID事务特性
原子性
一致性
隔离性
持久性
分布式事务的解决方案
基于XA协议的二阶段提交
消息事务+最终一致性
TCC编程模式
二阶段提交
XA是分布式事务协议,
总的来说 XA协议比较简单,容易实现,但是缺点是
同步阻塞 所有事务参与都在等待其他参与者响应的时候都处于同步阻塞的状态
单点问题
数据不一致
太过保守 任何节点失败 都会导致整个事务失败
性能不理想,mysql的XA实现,没有记录prepare阶段日志,许多nosql也没有支持XA
消息事务+最终一致性
A系统 发送prepare信息到 mq 然后得到mq 的返回后进行本地事务 然后在发送执行成功的消息进入mq,接着B系统获得到A系统完成本地事务的通知后
执行自己的事务 A系统通过消息回调来知晓 事务是否成功
如果A完成事务 B没完成 则再mq中会不断发起请求,知道B完成事务为止
缺点: 该解决方案只是最终一致性,如果B一直不成功,那其实AB 就不是一致性,所以需要业务方去抉择,判断
TCC编程模式
TCC 提供一个编程框架,Try Confirm Cancel 三个操作
每个业务方都需要实现这3种操作 try用于事务资源的预留,cancel用户资源不足时候的cancel方法,必须保证幂等。
协调器调用每个业务方的confirm接口 发现所有参与者的confirm方法都ok了 则分布式事务结束
如果失败次数过多,都需要进行事务补偿
缺点 业务需要实现这3个操作 对业务侵入较大
总结
分布式事务,本质上针对多个数据库的事务进行统一控制,按照控制力度分为 不控制,部分控制,完全控制
不控制 表现为不引入分布式事务
部分控制 消息事务+最终一致性,TCC编程
完全控制 两阶段提交
性能优缺点: 控制力度越大 性能,qps 都会下降,但是一致性会提高
复制代码
有疑问加站长微信联系(非本文作者)
更多相关内容 -
分布式事务-常用的分布式事务解决方案介绍.pptx
2021-12-01 13:58:13分布式事务ppt -
基于RabbitMQ消息队列的分布式事务解决方案
2021-02-24 02:37:56介绍Rabbitmg用于解决分布式事务必须掌握的5个核心概念一款分布式消息中间件,基于erlang语言开发,具备语言级别的高并发处理能力。和Spring框架是同一家公司。...●基于可靠消息(MQ)的解决方案异步场景 -
微服务架构的分布式事务解决方案(Dubbo分布式事务处理)
2018-09-01 15:33:46尤其是在订单业务、资金业务等系统核心业务流程中,一定要有可靠的分布式事务解决方案来保证业务数据的可靠性和准确性。 为了解决大家在实施分布式服务化架构过程中关于分布式事务问题的困扰,本教程将基于支付系统... -
微服务架构的分布式事务解决方案,完整31讲-龙果学院
2018-08-29 13:53:28第03节--常用的分布式事务解决方案介绍 第04节--消息发送一致性方案探讨(可靠消息的前提保障) 第05节--JMS规范的消息发送与接收特点 第06节--消息重复发送问题及业务接口的幂等性设计 第07节--可靠消息服务... -
springboot分布式事务解决方案LCN
2021-02-24 13:39:56本文来自于csdn,将从原理,调用时序图,客户端,启动类配置代理连接池,测试代码和效果这几个方面来阐述分布式事务解决方案LCN。对比LCN和saga(华为apache孵化器项目),LCN使用代理连接池封装补偿方法,saga需要... -
微服务架构的分布式事务解决方案,完整31讲
2018-06-23 17:41:27微服务架构的分布式事务解决方案,完整31讲。,百度云资源 非加密,无密码, -
微服务架构的分布式事务解决方案(附课件)
2017-10-30 16:35:09微服务架构的分布式事务解决方案(附课件),完整版。附件是 txt 文件,内含网盘地址。 -
springboot多数据源即分布式事务解决方案
2018-10-16 17:24:36实现系统对多数据源的操作。 实现系统对多数据源的分布式事务管理,包括事务的提交和回滚。 -
完整版微服务架构的分布式事务解决方案
2018-11-03 21:29:01完整版微服务架构的分布式事务解决方案 -
分布式事务解决方案框架(LCN)
2021-01-27 12:56:33本文来自于简书,本章主要介绍了分布式事物概念与分布式事物产生原因,以及分布式事物理论知识和解决方案,希望对您的学习有所帮助。 事物特性(ACID) 原子性(A)所谓的原子性就是说,在整个事务中的所有操作,要么... -
常用的分布式事务解决方案
2021-02-24 23:47:01本文来自于CSDN,文章详细介绍了梳理分布式事务的基本概念和理论基础,然后介绍几种目前常用的分布式事务解决方案等。事务由一组操作构成,我们希望这组操作能够全部正确执行,如果这一组操作中的任意一个步骤发生... -
微服务架构分布式事务解决方案设计思路
2021-01-27 13:39:16很多大型企业自主研发了自己的分布式事务解决方案,如:支付宝 XTS,去哪儿QMQ。1.基于可靠消息的最终一致性解决方案(异步确保型)(适用场景比较广)2.TCC事务补偿性方案(try-confirm-cancel)(也属于两阶段型的... -
Java微服务系统分布式事务解决方案.docx
2021-10-26 07:35:44Java微服务系统分布式事务解决方案.docx -
分布式事务解决方案总结(2)seata方案.docx
2021-10-26 08:16:08分布式事务解决方案总结(2)seata方案.docx -
5种分布式事务解决方案优缺点对比.docx
2021-10-26 07:17:225种分布式事务解决方案优缺点对比.docx -
Saga分布式事务解决方案与实践-姜宁39页.pdf
2021-07-07 16:34:56Saga分布式事务解决方案与实践-姜宁39页.pdf -
分布式事务解决方案微服务分布式事务解决方案.docx
2021-10-26 08:16:05分布式事务解决方案微服务分布式事务解决方案.docx -
微服务架构的分布式事务解决方案
2019-07-04 09:45:07微服务架构的分布式事务解决方案,无解压缩密码,通过百度网盘下载即可学习使用 -
这六种目前最常见分布式事务解决方案!请拿走不谢
2022-06-18 19:41:13分布式事务就是指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于不同的分布式系统的不同节点之上。以上是百度百科的解释,简单的说,就是一次大的操作由不同的小操作组成,这些小的操作分布在...一、分布式事务
分布式事务就是指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于不同的分布式系统的不同节点之上。以上是百度百科的解释,简单的说,就是一次大的操作由不同的小操作组成,这些小的操作分布在不同的服务器上,且属于不同的应用,分布式事务需要保证这些小操作要么全部成功,要么全部失败。本质上来说,分布式事务就是为了保证不同数据库的数据一致性。
以商品流水账单为例,我们拆分为商品购买系统,订单系统,支付系统。
用户看中一件商品,点击购买。
商品购买系统响应用户的点击,向订单系统插入一条订单信息。
跳转到支付系统完成支付。
在用户整个购买商品的过程中,我们需要保证事件1,2,3在没有异常的情况下全部执行成功,一旦某个系统抛出异常,都需要回滚。
那么,如何保证各个子系统的操作具有一致性呢?这就是我们下面提到的分布式事务的解决方案。
在这里,文章中没有提到分布式一致性协议,下面简单列举一下,有兴趣的读者可以参考其他详细资料:
- 两阶段提交协议
- 三阶段提交协议
- Paxos协议
- Raft协议
二、分布式事务的解决方案
1.两阶段提交方案/XA方案
该方案基于两阶段提交协议,因此也叫做两阶段提交方案。在该分布式系统中,其中 需要一个系统担任协调器的角色,其他系统担任参与者的角色。主要分为Commit-request阶段和Commit阶段
请求阶段:首先协调器会向所有的参与者发送准备提交或者取消提交的请求,然后会收集参与者的决策。
提交阶段:协调者会收集所有参与者的决策信息,当且仅当所有的参与者向协调器发送确认消息时协调器才会提交请求,否则执行回滚或者取消请求。
该方案的缺陷:
- 同步阻塞:所有的参与者都是事务同步阻塞型的。当参与者占有公共资源时,其他第三方节点访问公共资源不得不处于阻塞状态。
- 单点故障:一旦协调器发生故障,系统不可用。
- 数据不一致:当协调器发送commit之后,有的参与者收到commit消息,事务执行成功,有的没有收到,处于阻塞状态,这段时间会产生数据不一致性。
- 不确定性:当协调器发送commit之后,并且此时只有一个参与者收到了commit,那么当该参与者与协调器同时宕机之后,重新选举的协调器无法确定该条消息是否提交成功。
XA方案的实现方式可以使用Spring+JTA来实现,可以参考文章:Springboot+atomikos+jta实现分布式事务统一管理
2.TCC方案
TCC方案分为Try Confirm Cancel三个阶段,属于补偿性分布式事务。
Try:尝试待执行的业务
这个过程并未执行业务,只是完成所有业务的一致性检查,并预留好执行所需的全部资源
Confirm:执行业务
这个过程真正开始执行业务,由于Try阶段已经完成了一致性检查,因此本过程直接执行,而不做任何检查。并且在执行的过程中,会使用到Try阶段预留的业务资源。
Cancel:取消执行的业务
若业务执行失败,则进入Cancel阶段,它会释放所有占用的业务资源,并回滚Confirm阶段执行的操作。
以一个电商系统用户购买商品的流水线为例。
Try阶段:
在Try阶段成功之后进入Confirm阶段,如有任何异常,进入Cancel阶段。
Confirm阶段
Cancel阶段
假设库存扣减失败,此时需要回滚取消事务。
TCC方案适用于一致性要求极高的系统中,比如金钱交易相关的系统中,不过可以看出,其基于补偿的原理,因此,需要编写大量的补偿事务的代码,比较冗余。不过现有开源的TCC框架,比如TCC-transaction。
3. 本地消息表
本地消息表分布式事务解决方案是国外的eBay提出的一套方案。
需要注意的是,该方案中,在A系统中,我们首先写入业务表,然后写入消息表,然后将消息发送到MQ中,在B系统中需要先写入消息表,这是为了保证消息重复消费,为了保证消息消费的幂等性,我们可以使用数据的唯一键来约束。
当B系统执行成功之后,需要通知A系统执行成功,此时可以使用一个监听器,如Zookeeper,ZK监听到执行成功更新A系统成功。然后开始发送下一条消息。
A系统中需要有一个后台线程,不断的去判断A系统的状态为待确认的消息,设置超时机制,如果超时,重新发送到MQ中。直到执行成功。
可以看出,本地消息表方案需要写入消息表中,如果在高并发的场景下会进行大量的磁盘IO,因此该方案不适用于高并发场景。
4.可靠消息最终一致性方案
该方案基于本地消息表进行优化,不使用本地消息表,而是基于MQ,比如阿里的RocketMQ就支持消息事务。
在该方案中,首先A系统需要向MQ中发送prepare消息,然后执行A系统的业务,写入数据库成功之后向MQ发送confirm消息,当消息为confirm状态时,B系统就可以消费到消息,消费成功之后返回ACK确认消息给MQ。
需要注意的是。需要保证B系统消费消息的幂等性,可以借助第三方系统。比如在redis中设置标识,标明已经消费过该消息,或者借助ZK基于分布式锁的原理,创建节点,重复消费消息,创建失败。
5.最大努力通知方案
最大努力通知型( Best-effort delivery)是最简单的一种柔性事务,适用于一些最终一致性时间敏感度低的业务,且被动方处理结果 不影响主动方的处理结果。典型的使用场景:如银行通知、商户通知等。
在该系统中,A系统执行完本地事务,向MQ发送消息,最大努力通知服务消费消息,比如消息服务,然后调用B系统的接口,执行B系统的本地事务,如果B系统执行成功则OK,否则不断重试,重复多次之后还是失败的话就放弃执行。
-
分布式事务解决方案详解
2021-12-10 13:02:19分布式事务 在分布式系统中,为了保证数据的高可用,通常,我们会将数据保留多个副本(replica),这些副本会放置在不同的物理的机器上。为了对用户提供正确的 CRUD 等语义,我们需要保证这些放置在不同物理机器上的...- 分布式事务
在分布式系统中,为了保证数据的高可用,通常,我们会将数据保留多个副本(replica),这些副本会放置在不同的物理的机器上。为了对用户提供正确的 CRUD 等语义,我们需要保证这些放置在不同物理机器上的副本是一致的。分布式事务在现在遍地都是分布式部署的系统中几乎是必要的。
1.1 事务简介
事务(Transaction)是访问并可能更新数据库中各种数据项的一个程序执行单元(unit)。在关系数据库中,一个事务由一组SQL语句组成。事务应该具有4个属性:原子性、一致性、隔离性、持久性。这四个属性通常称为ACID特性。
-
原子性
事务是一个不可分割的工作单位,事务中包括的诸操作要么都做,要么都不做。
-
一致性
事务必须是使数据库从一个一致性状态变到另一个一致性状态,事务的中间状态不能被观察到的。
-
隔离性
一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。隔离性又分为四个级别:读未提交(read uncommitted)、读已提交(read committed,解决脏读)、可重复读(repeatable read,解决虚读)、串行化(serializable,解决幻读)。
-
持久性
持久性也称永久性(permanence),指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。
任何事务机制在实现时,都应该考虑事务的ACID特性,包括:本地事务、分布式事务,及时不能都很好的满足,也要考虑支持到什么程度。
1.2 本地事务
大多数场景下,我们的应用都只需要操作单一的数据库,这种情况下的事务称之为本地事务( Local Transaction )。本地事务的ACID特性是数据库直接提供支持。本地事务应用架构如下所示:
很多java应用都整合了spring,并使用其声明式事务管理功能来完成事务功能。一般使用的步骤如下:
1、配置事务管理器。spring提供了一个 PlatformTransactionManager 接口,其有2个重要的实现类:
-
DataSourceTransactionManager
用于支持本地事务,事实上,其内部也是通过操作java.sql.Connection 来开启、提交和回滚事务。
-
JtaTransactionManager
用于支持分布式事务,其实现了JTA规范,使用XA协议进行两阶段提交。需要注意的是,这只是一个代理,我们需要为其提供一个JTA provider,一般是Java EE容器提供的事务协调器(Java EE server’s transaction coordinator),也可以不依赖容器,配置一个本地的JTAprovider。
2、在需要开启的事务的bean的方法上添加 @Transitional 注解
可以看到,spring除了支持本地事务,也支持分布式事务,下面我们先对分布式事务的典型应用场景进行介绍。
1.3 不同场景下的分布式事务
当下互联网发展如火如荼,绝大部分公司都进行了数据库拆分和服务化(SOA)。在这种情况下,完成某一个业务功能可能需要横跨多个服务,操作多个数据库。这就涉及到到了分布式事务,用需要操作的资源位于多个资源服务器上,而应用需要保证对于多个资源服务器的数据的操作,要么全部成功,要么全部失败。本质上来说,分布式事务就是为了保证不同资源服务器的数据一致性。
1.3.1 跨库事务
跨库事务指的是,一个应用某个功能需要操作多个库,不同的库中存储不同的业务数据。下图演示了一个服务同时操作2个库的情况:
1.3.2 分库分表事务
通常一个库数据量比较大或者预期未来的数据量比较大,都会进行水平拆分,也就是分库分表。如下图,将数据库B拆分成了2个库:
对于分库分表的情况,一般开发人员都会使用一些数据库中间件来降低sql操作的复杂性。如,对于sql: insert into user(id,name) values (1,“chen”),(2,“jack”) 。这条sql是操作单库的语法,单库情况下,可以保证事务的一致性。
但是由于现在进行了分库分表,开发人员希望将1号记录插入分库1,2号记录插入分库2。所以数据库中间件要将其改写为2条sql,分别插入两个不同的分库,此时要保证两个库要不都成功,要不都失败。因此基本上所有的数据库中间件都面临着分布式事务的问题。
1.3.3 跨应用事务
微服务架构是目前一个比较一个比较火的概念。例如上面提到的一个案例,某个应用同时操作了9个库,这样的应用业务逻辑必然非常复杂,对于开发人员是极大的挑战,应该拆分成不同的独立服务,以简化业务逻辑。拆分后,独立服务之间通过RPC框架来进行远程调用,实现彼此的通信。下图演示了一个3个服务之间彼此调用的架构:
Service A完成某个功能需要直接操作数据库,同时需要调用Service B和Service C,而Service B又同时操作了2个数据库,Service C也操作了一个库。需要保证这些跨服务的对多个数据库的操作要不都成功,要不都失败,实际上这可能是最典型的分布式事务场景。
上述讨论的分布式事务场景中,无一例外的都直接或者间接的操作了多个数据库。如何保证事务的ACID特性,对于分布式事务实现方案而言,是非常大的挑战。同时,分布式事务实现方案还必须要考虑性能的问题,如果为了严格保证ACID特性,导致性能严重下降,那么对于一些要求快速响应的业务,是无法接受的。
2. 分布式事务理论
分布式事务可以有多种分类,比如柔性事务和强一致性事务,这些事务操作会遵循一定的定理,比如CAP原理、BASE理论。
2.1 CAP原理
由于对系统或者数据进行了拆分,我们的系统不再是单机系统,而是分布式系统,针对分布式系统的CAP原理包含如下三个元素:
-
C:Consistency
一致性。在分布式系统中的所有数据 备份,在同一时刻具有同样的值,所有节点
在同一时刻读取的数据都是最新的数据副本。
-
A:Availability
可用性,好的响应性能。完全的可用性指的是在任何故障模型下,服务都会在有
限的时间内处理完成并进行响应。
-
P: Partition tolerance
分区容忍性。尽管网络上有部分消息丢失,但系统仍然可继续工作。
CAP原理指的是,这三个要素最多只能同时实现两点,不可能三者兼顾。因此在进行分布式架构设计时,必须做出取舍。而对于分布式数据系统,分区容忍性是基本要求,否则就失去了价值。因此设计分布式数据系统,就是在一致性和可用性之间取一个平衡。对于大多数web应用,其实并不需要强一致性,因此牺牲一致性而换取高可用性,是目前多数分布式数据库产品的方向。
当然,牺牲一致性,并不是完全不管数据的一致性,否则数据是混乱的,那么系统可用性再高分布式再好也没有了价值。牺牲一致性,只是不再要求关系型数据库中的强一致性,而是只要系统能达到最终一致性即可,考虑到客户体验,这个最终一致的时间窗口,要尽可能的对用户透明,也就是需要保障“用户感知到的一致性”。通常是通过数据的多份异步复制来实现系统的高可用和数据的最终一致性的,“用户感知到的一致性”的时间窗口则取决于数据复制到一致状态的时间。
2.2 BASE理论
BASE理论是指,Basically Available(基本可用)、Soft-state( 软状态/柔性事务)、EventualConsistency(最终一致性)。是基于CAP定理演化而来,是对CAP中一致性和可用性权衡的结果。核心思想:即使无法做到强一致性,但每个业务根据自身的特点,采用适当的方式来使系统达到最终一致性。
-
基本可用 BA:(Basically Available)
指分布式系统在出现故障的时候,允许损失部分可用性,保证核心可用。但不等价于不可用。比如:搜索引擎0.5秒返回查询结果,但由于故障,2秒响应查询结果;网页访问过大时,部分用户提供降级服务等。简单来说就是基本可用。
-
软状态 S:(Soft State):
软状态是指允许系统存在中间状态,并且该中间状态不会影响系统整体可用性。即允许系统在不同节点间副本同步的时候存在延时。简单来说就是状态可以在一段时间内不同步。
-
最终一致性 E:(Eventually Consistent):
系统中的所有数据副本经过一定时间后,最终能够达到一致的状态,不需要实时保证系统数据的强一致性。最终一致性是弱一致性的一种特殊情况。BASE理论面向的是大型高可用可扩展的分布式系统,通过牺牲强一致性来获得可用性。ACID是传统数据库常用的概念设计,追求强一致性模型。简单来说就是在一定的时间窗口内, 最终数据达成一致即可。
2.3 刚柔事务
何谓刚柔事务?刚性事务它的事务是原子的,要么都成功要么都失败,也就是需要保障ACID理论,而柔性事务只需要保障数据最终一致即可,需要遵循BASE理论。
-
刚性事务满足ACID理论
-
柔性事务满足BASE理论(基本可用,最终一致)
柔性事务分为:
-
两阶段型
-
补偿型
-
异步确保型
-
最大努力通知型。
金融项目对柔性事务用的比较多,例如支付宝、微信支付、银联支付几乎所有架构是SOA架构,因此传统单机环境下数据库的ACID事务满足了分布式环境下的业务需要,以上几种事务类似就是针对分布式环境下业务需要设定的。
3. 常用事务解决方案模型
分布式事务解决方案几乎都是柔性事务,常见的有2PC/3PC、TCC、MQ最终一致性解决方案,至于工作中用哪种方案,需要根据业务场景选取, 2PC/3PC、TCC 数据强一致性高,而MQ是最终数据一致。
3.1 TDP模型
DTP模型中有5个基本元素:
-
应用程序(Application Program ,简称AP):
用于定义事务边界(即定义事务的开始和结束),并且在事务边界内对资源进行操作。
-
资源管理器(Resource Manager,简称RM):
如数据库、文件系统等,并提供访问资源的方式。
-
事务管理器(Transaction Manager,简称TM):
负责分配事务唯一标识,监控事务的执行进度,并负责事务的提交、回滚等。
-
通信资源管理器(Communication Resource Manager,简称CRM):
控制一个TM域(TM domain)内或者跨TM域的分布式应用之间的通信。
-
通信协议(Communication Protocol,简称CP):
提供CRM提供的分布式应用节点之间的底层通信服务。
3.2 2PC/3PC
3.2.1 2PC
两阶段提交又称2PC,2PC是一个非常经典的 强一致、中心化的原子提交协议 。
这里所说的中心化是指协议中有两类节点:一个是中心化 协调者节点 (coordinator)和 N个参与者节点 (partcipant)。
两个阶段 :第一阶段:投票阶段 和第二阶段:提交/执行阶段。
举例
订单服务A,需要调用 支付服务B 去支付,支付成功则处理购物订单为待发货状态,否则就需要将购物订单处理为失败状态。
那么看2PC阶段是如何处理的:
-
1PC
1: 事务询问
协调者 向所有的 参与者 发送事务预处理请求,称之为Prepare,并开始等待各 参与者 的响应。
2: 执行本地事务
各个 参与者 节点执行本地事务操作,但在执行完成后并不会真正提交数据库本地事务,而是先向 协调者报告说:“我这边可以处理了/我这边不能处理”。
3: 各参与者向协调者反馈事务询问的响应
如果 参与者 成功执行了事务操作,那么就反馈给协调者 Yes 响应,表示事务可以执行,如果没有 参与者 成
功执行事务,那么就反馈给协调者 No 响应,表示事务不可以执行。
-
2PC:
4: 所有的参与者反馈给协调者的信息都是Yes,那么就会执行事务提交
协调者 向 所有参与者 节点发出Commit请求.
5: 事务提交
参与者 收到Commit请求之后,就会正式执行本地事务Commit操作,并在完成提交之后释放整个事务执行期间占用的事务资源。
3.2.2 3PC
三阶段提交又称3PC,其在两阶段提交的基础上增加了CanCommit阶段,并引入了超时机制。一旦事务参与者迟迟没有收到协调者的Commit请求,就会自动进行本地commit,这样相对有效地解决了协调者单点故障的问题。
但是性能问题和不一致问题仍然没有根本解决。下面我们还是一起看下三阶段流程的是什么样的?
-
1PC
这个阶段类似于2PC中的第二个阶段中的Ready阶段,是一种事务询问操作,事务的协调者向所有参与者询问“你们是否可以完成本次事务?”,如果参与者节点认为自身可以完成事务就返回“YES”,否则“NO”。而在实际的场景中参与者节点会对自身逻辑进行事务尝试,简单来说就是检查下自身状态的健康性,看有没有能力进行事务操作。
-
2PC
-
在阶段一中,如果所有的参与者都返回Yes的话,那么就会进入PreCommit阶段进行事务预提交。此时分布式事务协调者会向所有的参与者节点发送PreCommit请求,参与者收到后开始执行事务操作,并将Undo和Redo信息记录到事务日志中。参与者执行完事务操作后(此时属于未提交事务的状态),就会向协调者反馈“Ack”表示我已经准备好提交了,并等待协调者的下一步指令。
否则,如果阶段一中有任何一个参与者节点返回的结果是No响应,或者协调者在等待参与者节点反馈的过程中超时(2PC中只有协调者可以超时,参与者没有超时机制)。整个分布式事务就会中断,协调者就会向所有的参与者发送**“abort”**请求。
-
3PC
在阶段二中如果所有的参与者节点都可以进行PreCommit提交,那么协调者就会从**“预提交状态”》提交状态”。然后向所有的参与者节点发送"doCommit"请求,参与者节点在收到提交请求后就会各自执行事务提交操作,并向协调者节点反馈“Ack”**消息,协调者收到所有参与者的Ack消息后完成事务。
相反,如果有一个参与者节点未完成PreCommit的反馈或者反馈超时,那么协调者都会向所有的参与者 节点发送abort请求,从而中断事务。
3.2.3 两者区别
相比较2PC而言,3PC对于协调者(Coordinator)和参与者(Partcipant)都设置了超时时间,而2PC只有协调者才拥有超时机制。这解决了一个什么问题呢?这个优化点,主要是避免了参与者在长时间无法与协调者节点通讯(协调者挂掉了)的情况下,无法释放资源的问题,因为参与者自身拥有超时机制会在超时后,自动进行本地commit从而进行释放资源。而这种机制也侧面降低了整个事务的阻塞时间和范围。
另外,通过CanCommit、PreCommit、DoCommit三个阶段的设计,相较于2PC而言,多设置了一个缓冲阶段保证了在最后提交阶段之前各参与节点的状态是一致的。
以上就是3PC相对于2PC的一个提高(相对缓解了2PC中的前两个问题),但是3PC依然没有完全解决数据不一致的问题。
3.3 TCC
TCC与2PC、3PC一样,也是分布式事务的一种实现方案。TCC(Try-Confirm-Cancel)又称补偿事务。其核心思想是:“针对每个操作都要注册一个与其对应的确认和补偿(撤销操作)”。它分为三个操作:
-
Try阶段:主要是对业务系统做检测及资源预留。
-
Confirm阶段:确认执行业务操作。
-
Cancel阶段:取消执行业务操作。
TCC事务的处理流程与2PC两阶段提交类似,不过2PC通常都是在跨库的DB层面,而TCC本质上就是一个应用层面的2PC,需要通过业务逻辑来实现。这种分布式事务的实现方式的优势在于,可以让应用自己定义数据库操作的粒度,使得降低锁冲突、提高吞吐量成为可能。
不足之处则在于对应用的侵入性非常强,业务逻辑的每个分支都需要实现try、confirm、cancel三个操作。此外,其实现难度也比较大,需要按照网络状态、系统故障等不同的失败原因实现不同的回滚策略。为了满足一致性的要求,confirm和cancel接口还必须实现幂等。
3.4 MQ分布式事务
在OLTP系统领域,我们在很多业务场景下都会面临事务一致性方面的需求,而大型互联网平台往往是由一系列分布式系统构成的,开发语言平台和技术栈也相对比较杂,尤其是在SOA和微服务架构盛行的今天,一个看起来简单的功能,内部可能需要调用多个“服务”并操作多个数据库或分片来实现,情况往往会复杂很多,如果对数据一致性要求很高,可以采用上面的2PC或者3PC以及TCC方案,如果数据强一致性要求没那么高,可以采用消息中间件(MQ)实现事务最终一致。
在支付系统中,常常使用的分布式事务解决方案就是基于MQ实现的,它对数据强一致性要求没那么高,但要求数据最终一致即可。例如:向借呗申请借钱,借呗审核通过后支付宝的余额才会增加,但借呗和支付宝有可能不是同一个系统,这时候如何实现事务呢?实现方案如下图:
上图执行流程:
1:找花呗借钱 2:花呗借钱审核通过,同步生成借款单 3:借款单生成后,向MQ发送消息,通知支付宝转账 4:支付宝读取MQ消息,并增加账户余额
上图最复杂的其实是如何保障2、3在同一个事务中执行(本地事务和MQ消息发送在同一个事务执行),借款结束后,借呗数据处理就完成了,接下来支付宝才能读到消息,然后执行余额增加,这才完成整个操作。如果中途操作发生异常,例如支付宝余额增加发生问题怎么办?此时需要人工解决,没有特别好的办法,但这种事故概率极低。
以上便是一些我们常用的事务解决方案模型,目前比较主流的分布式事务处理我们可以采用Seata进行处理,具体会单独说明。
-
龙果学院(微服务架构的分布式事务解决方案)pdf ppt
2019-03-25 11:36:06龙果学院(微服务架构的分布式事务解决方案)pdf ppt -
常用的分布式事务解决方案介绍.ppt
2022-05-27 18:51:41常用的分布式事务解决方案介绍.ppt常用的分布式事务解决方案介绍.ppt常用的分布式事务解决方案介绍.ppt常用的分布式事务解决方案介绍.ppt常用的分布式事务解决方案介绍.ppt -
分布式事务解决方案:7种常见解决方案汇总
2021-10-29 20:00:42为了解决分布式事务的问题,出现了很多协议,如2PC(二阶段提交协议)、3PC(三阶段提交协议) 在二阶段提交协议中有一个事务管理器和多个资源管理器。事务管理器分两阶段协调资源管理器。 一阶段:事务管理器告诉...二阶段提交协议
为了解决分布式事务的问题,出现了很多协议,如2PC(二阶段提交协议)、3PC(三阶段提交协议)
在二阶段提交协议中有一个事务管理器和多个资源管理器。事务管理器分两阶段协调资源管理器。
一阶段:事务管理器告诉资源管理器准备执行事务,并锁住需要的资源。当准备完成后,资源管理器向事务管理器报告已准备就绪。
二阶段:如果所有资源管理器都准备成功,第二阶段事务管理器回要求所有的资源管理器执行提交操作。如果任一资源管理器在第一阶段返回准备失败,那么事务管理器回要求所有的资源管理器在第二阶段执行回滚操作。
二阶段看起来能提供原子性操作,但是不幸的是,二阶段提交还是有几个缺点的- 2PC是一个同步阻塞协议,资源管理器在执行的过程中会锁定资源。其他第三方节点想访问这些资源的时候不得不处于阻塞状态
- 一阶段有超时机制,在第一阶段事务管理器没有收到资源管理的响应,或者资源管理器挂了。超时就会判端事务失效,向所有资源管理器发送回滚命令。但二阶段只能不断重试
- 事务管理器存在单点风险,如果发生故障,则资源管理器会一直阻塞下去。
基于2PC的问题,人们又提出了3PC的概念,但是很少被使用,没研究过,大家可以看看其他文章
XA规范
XA规范是X/Open 组织针对二阶段提交协议的实现做的规范。目前几乎所有的主流数据库都对XA规范提供了支持
XA规范的特点是:
- 对代码无侵入,开发比较快速
- 对资源进行了长时间的锁定,并发程度比较低
TCC
TCC这种方案应该是在企业中应用最广泛的一种方案,在业务层面实现分布式事务。TCC是Try、Confirm、Cancel三个词语的缩写。
TCC主要分为3个操作。
Try:一阶段,负责业务资源检查和预留
Confirm:二阶段提交操作,所有的Try都成功了,则执行Confirm操作。Confirm真正执行业务,使用Try预留的资源
Cancel:二阶段回滚操作,只有一个Try失败了,则走到Cancel操作。Cancel释放Try预留的资源
TCC的特点为:- 并发程度高,在业务层面锁定资源
- 开发量大,一个业务员需要提供Try/Confirm/Cancel三个方法
SAGA
SAGA是一种补偿协议,在SAGA模式下,分布式事务有多个参与者。在分布式事务的执行过程中,依次执行各参与者的正向操作,如果所有正向操作都执行成功,那么分布式事务提交。如果任何一个正向操作失败,则会执行前面各参与者的回滚操作,将事务状态回到初始状态
SAGA特点为
- 并发度高,不需要长期锁定资源
- 开发量大,需要定义正向操作和补偿操作
- 不能保证隔离型
本地消息表
本地消息表这个解决方案是eBay 的系统架构师丹 · 普利切特(Dan Pritchett)在 2008 年发表于 ACM 的论文中提出的
我们以买书为例说一下大致流程- 账号服务扣减账户余额,同时写入一条消息(状态为进行中),注意扣减账户余额和写消息在一个本地事务中
- 账号服务轮询消息表,将进行中的消息发送到消息队列
- 仓库服务收到消息后,扣减相应的库存。扣减完成后将结果通过给账号服务,账号服务将消息的状态更新为已完成(或者删除)
- 当消息发送失败,或者消息消费失败时,会不断重试,因此仓库服务要保证消费的幂等性。
通过这种方案就能达到事务的最终一致性,这种不断重试的思路,也体现了我们后面要提到的最大努力通知
本地消息表特点为:
- 需要创建额外的消息表,不断对消息表轮询
RocketMQ事务消息
在本地消息表方案中,生产者需要额外创建本地消息表,还要对本地消息进行轮询。RocketMQ在4.3之后的版本正式支持事务消息,该事务消息的本质是把本地消息表放在RocketMQ上,解决生产端消息发送和本地事务执行的原子性问题
RocketMQ实现分布式事务的流程如下- producer向mq server发送一个半消息
- mq server将消息持久化成功后,向发送方确认消息已经发送成功,此时消息并不会被consumer消费
- producer开始执行本地事务逻辑
- producer根据本地事务执行结果向mq server发送二次确认,mq收到commit状态,将消息标记为可投递,consumer会消费该消息。mq收到rollback则删除半消息,consumer将不会消费该消息,如果收到unknow状态,mq会对消息发起回查
- 在断网或者应用重启等特殊情况下,步骤4提交的2次确认有可能没有到达mq server,经过固定时间后mq会对该消息发起回查
- producer收到回查后,需要检查本地事务的执行状态
- producer根据本地事务的最终状态,再次提交二次确认,mq仍按照步骤4对半消息进行操作
看到这,可能有人会问了,我们先执行本地事务,执行成功后再发送消息,这样不也可以保证生产端消息发送和本地事务执行的原子性?
其实这样做还是有可能会造成数据不一致的问题。假如本地事务执行成功,发送消息,由于网络延迟,消息发送成功,但是回复超时了,抛出异常,本地事务回滚。但是消息其实投递成功并被消费了,此时就会造成数据不一致的情况
那消息投递到mq server,consumer消费失败怎么办?
如果是消费超时,重试即可。如果是由于代码等原因真的消费失败了,此时就得人工介入,重新手动发送消息,达到最终一致性。
最大努力通知
做过微信充值或者支付宝充值的小伙伴对这个方案应该比较熟悉,因为最大努力通知这种方案在充值系统中经常被使用。充值系统通过不断的重试将充值结果推送给账户系统。因此账户系统接收充值结果的系统要保持幂等。另外充值充值系统还要提供回查接口,让账户系统主动校验充值的状态。
从微信支付的开发文档就可以看到微信支付用到了最大努力通知
https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_7
Seata AT模式
这是阿里开源的事务框架Seata中主推的事务模式。Seata AT是一种无侵入的事务解决方案。事务的一阶段和二阶段均由框架自动生成。用户SQL作为分布式事务的一阶段,而二阶段由框架自动生成提交/回滚操作。和XA模式很类似
Seata AT模式特点:
- 对代码无侵入,开发速度较快
- 需要用全局锁来保证隔离性,并发程度较低
参考博客
[1]https://segmentfault.com/a/1190000040321750
[2]https://zhuanlan.zhihu.com/p/141645172 -
26.第二十六阶段、微服务架构的分布式事务解决方案视频全集
2018-02-05 11:31:3226.第二十六阶段、微服务架构的分布式事务解决方案视频全集26.第二十六阶段、微服务架构的分布式事务解决方案视频全集26.第二十六阶段、微服务架构的分布式事务解决方案视频全集26.第二十六阶段、微服务架构的分布式...