基础概念 什么是事务 什么是事务?举个例子:你去超市买东西,“一手交钱,一手交货"就是一个事务的例子。 交钱和交货必须同时成功,事务才算成功,其......
+概览 什么是事务?举个例子,你去超市买东西,“一手交钱,一手交货"就是一个事务的例子。 交钱和交货必须同时成功,事务才算成功,其中有一个环节失......
From 5b4bcf5ff41cfc0a5f96d21fc4ec3cd2364c81ad Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E6=9D=8E=E6=B5=8E=E8=8A=9D?= 基础概念 什么是事务 什么是事务?举个例子:你去超市买东西,“一手交钱,一手交货"就是一个事务的例子。 交钱和交货必须同时成功,事务才算成功,其...... 概览 什么是事务?举个例子,你去超市买东西,“一手交钱,一手交货"就是一个事务的例子。 交钱和交货必须同时成功,事务才算成功,其中有一个环节失......
-出现原因是当一个分支事务所在的服务器宕机或网络异常,分支事务调用记录为失败,这个时候其实是没有执行Try阶段,当故障恢复后,分布式事务进行回滚则会调用二阶段的Cancel方法,从而形成空回滚。
-
-解决思路关键就是要标识这个空回滚,就是要知道try阶段是否已经执行了,如果执行了那就是正常回滚;如果没执行,那就是空回滚。可以在try阶段执行完毕后向表里插入一条记录进行标识,如果记录存在则try阶段执行了,如果不存在try阶段则未执行。
-
-2. **幂等**:为了保证TCC二阶段提交重试机制不会引发数据不一致,要求TCC二阶段Try、Confirm、Cancel接口保证幂等性,这样不会重复使用或示释放资源。如果幂等控制没有做好,很有可能导致数据不一致等严重问题。
+Hmily实现的TCC服务与普通的服务一样,只需要暴露一个接口,也就是它的`Try`业务。`Confirm/Cancel`业务逻辑,只是因为全局事务提交/回滚的需要才提供的,因此`Confirm/Cancel`业务只需要被Hmily TCC事务框架发现即可,不需要被调用它的其他业务服务所感知。
-3. **悬挂**:悬挂就是对于一个分布式事务,其二阶段Cancel接口对比Try接口先执行。
+要实现TCC协议,必须要实现三个方法:`Try`、`Confirm`、`Cancel`,其中最关键的方法是`Try`方法,Try方法是一个事务的起点,三个方法会由不同的线程来分别调用。
-出现原因是在RPC调用分支事务时,先注册分支事务,在执行RPC调用,如果此时RPC调用的网络发生错误,RPC超时后,TM就会通知RM回滚该分布式事务,可能回滚完成后,RPC请求才到达,然后执行,而一个try方法预留的业务资源,只有该分布式事务才能使用,该分布式事务第一阶段预留的业务资源也就在也没有人能够处理,对于这种情况就称为悬挂,即业务资源预留后没办法处理。
+TCC需要注意三种异常处理:
+1. 空回滚:在没有调用TCC资源`Try`方法的情况下,调用了二阶段的`Cancel`方法,`Cancel`方法需要识别出这是一个空回滚,然后直接返回成功。
+出现原因是当一个分支事务所在的服务器宕机或网络异常,分支事务调用记录为失败,这个时候其实是没有执行`Try`阶段,当故障恢复后,分布式事务进行回滚则会调用二阶段的`Cancel`方法,从而形成空回滚。
+解决思路关键就是要标识这个空回滚,就是要知道`Try`阶段是否已经执行了,如果执行了那就是正常回滚;如果没执行,那就是空回滚。可以在try阶段执行完毕后向表里插入一条记录进行标识,如果记录存在则`Try`阶段执行了,如果不存在`Try`阶段则未执行。
+2. 幂等:为了保证TCC二阶段提交重试机制不会引发数据不一致,要求TCC二阶段`Try`、`Confirm`、`Cancel`接口保证幂等性,这样不会重复使用或示释放资源。如果幂等控制没有做好,很有可能导致数据不一致等严重问题。
+3. 悬挂:悬挂就是对于一个分布式事务,其二阶段`Cancel`接口对比`Try`接口先执行。
+出现原因是在RPC调用分支事务时,先注册分支事务,在执行RPC调用。如果此时RPC调用的网络发生错误、RPC超时后,TM就会通知RM回滚该分布式事务,可能回滚完成后RPC请求才到达,然后执行,而一个`Try`方法预留的业务资源,只有该分布式事务才能使用,该分布式事务第一阶段预留的业务资源也就在也没有人能够处理,对于这种情况就称为悬挂,即业务资源预留后没办法处理。
-## 分布式事务解决方案-可靠消息最终一致性
-针对不同的分布式场景常见的解决方案有2PC、TCC、可靠消息最终一致性、最大努力通知这几种。
-
-### 什么是可靠消息最终一致性
+### 可靠消息最终一致性
可靠消息最终一致性是指当事务发起方执行完本地事务后并发出一条消息,事务参与方(消息消费者)一定能接收到消息并成功处理事务,此方案强调的是只要消息发给事务参与方最终事务要达到一致。
此方案利用消息中间件完成,事务发起方将消息发送给消息中间件,事务参与方从消息中间件接收消息,事务发起方和消息中间件之间,事务参与方和消息中间件之间都是通过网络进行通信,由于网络通信的不稳定会导致分布式事务问题。
![分布式事务-013](/iblog/posts/annex/images/essays/分布式事务-013.png)
-因此可靠消息最终一致性方案要解决几个问题:
-
-- **本地事务与消息发送的原子性** 即:事务发起方在本地事务执行成功后消息必须发出去,否则就丢弃消息。即实现本地事务和消息发送的原子性,要么都成功,要么都失败。本地事务与消息发送的原子性问题是实现可靠消息最终一致性方案的关键。
-- **事务参与方接收消息的可靠性** 事务参与方必须能够从消息队列接收消息,如果接收消息失败可以重复接收消息。
-- **消息重复消费问题** 由于网络存在问题,若某一个消费结点超时但是消费成功,此时消息中间件会重复投递此消息,就导致了消息重复消费问题。要解决消息重复消费问题就要实现事务参与方的方法的幂等性。
-
-### 解决方案
+此方案利用消息中间件完成,因此可靠消息最终一致性方案要解决几个问题:
+- 本地事务与消息发送的原子性:即事务发起方在本地事务执行成功后消息必须发出去,否则就丢弃消息。即实现本地事务和消息发送的原子性,要么都成功,要么都失败。本地事务与消息发送的原子性问题是实现可靠消息最终一致性方案的关键。
+- 事务参与方接收消息的可靠性:事务参与方必须能够从消息队列接收消息,如果接收消息失败可以重复接收消息。
+- 消息重复消费问题:由于网络存在问题,若某一个消费结点超时但是消费成功,此时消息中间件会重复投递此消息,就导致了消息重复消费问题。要解决消息重复消费问题就要实现事务参与方的方法的幂等性。
#### 本地消息表方案
本地消息表该方案最初是eBay提出,此方案的核心是通过本地事务保证数据业务操作和消息的一致性,然后通过定时任务将消息发送至消息中间件,待确认消息发送给消费方成功后在将消息删除。
-以用户注册送积分举例:用户服务负责添加用户,积分服务负责添加积分
+以用户注册送积分举例,用户服务负责添加用户,积分服务负责添加积分。
![分布式事务-014](/iblog/posts/annex/images/essays/分布式事务-014.png)
执行流程:
- 用户注册,用户服务在本地新增用户和增加积分消息日志。用户表和消息表本地事务保持一致,这种情况下本地数据库操作与存储积分消息日志处于同一个事务中,本地数据库操作记录与记录消息日志操作具备原子性。
-
-**如何保证将消息发送给消息队列?**
- 当消息已经写入到消息日志中去后,可以启动独立的线程,定时对消息日志表中的消息进行扫描并发送至消息中间件,在消息中间件反馈发送成功后删除该消息日志,否则等待定时任务下一周期重试。
+- 使用MQ的ACK机制即消息确认机制,消费者监听MQ,如果消费者接收到消息并且业务处理完成后想MQ发送ACK,此时说明消费者正常消费消息完成,MQ将不再向消费者推送消息,否则生产者会不断重试向消费者发送消息。
+由于消息会重复投递,因此积分服务的增加积分操作功能要实现幂等性。
-**如何保证消费者一定能消费到消息?**
-- 可以使用MQ的ACK机制即消息确认机制,消费这监听MQ,如果消费者接收到消息并且业务处理完成后想MQ发送ACK,此时说明消费者正常消费消息完成,MQ将不再向消费者推送消息,否则生产者会不断重试向消费者发送消息。
-
-由于消息会重复投递,积分服务的增加积分操作功能要实现幂等性。
-
-#### RocketMQ事务消息方案
-RocketMQ是阿里巴巴的分布式消息中间件,于2012年开源并在2017年正式称为apache的项目。ApacheRocketMQ4.3之后的版本正式支持事务消息,并为分布式事务提供了便利性支持。
+#### RocketMQ方案
+RocketMQ是阿里巴巴的分布式消息中间件,于2012年开源并在2017年正式称为Apache的项目。ApacheRocketMQ4.3之后的版本正式支持事务消息,并为分布式事务提供了便利性支持。
-RocketMQ事务消息设计则主要是为了解决生产者端的消息发送与本地事务执行的原子性问题,RockerMQ设计中broker与生产者端的双向通信能力,使得broker天生可以作为一个事务协调者存在;RockerMQ的高可用机制以及可靠消息设计原则则为事务消息在系统发生异常时依然能够保证达成事务的最终一致性。
+RocketMQ事务消息设计则主要是为了解决生产者端的消息发送与本地事务执行的原子性问题。RockerMQ设计中`broker`与生产者端的双向通信能力,使得`broker`天生可以作为一个事务协调者存在。
+RockerMQ的高可用机制以及可靠消息设计原则则为事务消息在系统发生异常时依然能够保证达成事务的最终一致性。
![分布式事务-015](/iblog/posts/annex/images/essays/分布式事务-015.png)
执行流程:
1. MQ的发起方会向MQ发送一条消息,MQ发起方会监听MQ是否响应;
2. MQ收到该消息会响应消息发起方,代表发送给MQ成功;但是此时MQ并未发送消息给消费者;
-3. MQ发起方开始执行本地事务,执行完本地事务后,给MQ发送commit消息,此时MQ将该消息更改为可消费状态,消费者可以消费该消息;如果消费者执行本地事务失败,给MQ发送rollback消息,MQ会将该消息丢弃;
-4. 消费者方利用MQ的ACK机制来保证消息一定被消费到;
+3. MQ发起方开始执行本地事务,执行完本地事务后,给MQ发送`commit`消息,此时MQ将该消息更改为可消费状态,消费者可以消费该消息;如果消费者执行本地事务失败,给MQ发送`rollbac`k消息,MQ会将该消息丢弃;
+4. 消费者方利用MQ的ACK机制来保证消息一定被消费到。
+如果发起方与MQ之间的网络出现问题,但MQ里的消息不会一直存着。MQ服务会定回查消费者方本地事务状态(实现MQ事务回查接口),如果事务已经提交了消费者仍然可以接收到该消息,如果没有提交MQ则丢弃该消息;
-**注意:发起方与MQ之间的网络出现问题,但此时MQ里的消息不会一直存着;MQ服务会定回查消费者方本地事务状态(实现MQ事务回查接口),如果事务已经提交了消费者仍然可以接收到该消息,如果没有提交MQ则丢弃该消息。**
-
-## 分布式事务解决方案-最大努力通知
-针对不同的分布式场景常见的解决方案有2PC、TCC、可靠消息最终一致性、最大努力通知这几种。
+### 最大努力通知
+最大努力通知,顾名思义就是发起通知方通过一定机制,最大努力的将业务处理结果通知到接收方。
-### 什么是最大努力通知
-顾名思义,发起通知方通过一定机制最大努力的将业务处理结果通知到接收方。
-
-举个例子:
+举个例子,账户系统调用充值系统接口,充值系统完成处理后向账户账户接口发起充值结果通知,如果通知失败则充值充值系统则按策略进行重复通知。
+账户系统接收到充值系统的通知后修改充值状态,如果账户系统未接受到通知,账户系统会主动调用充值系统接口进行结果查询。
![分布式事务-016](/iblog/posts/annex/images/essays/分布式事务-016.png)
-账户系统调用充值系统接口,充值系统完成处理后向账户账户接口发起充值结果通知,如果通知失败则充值充值系统则按策略进行重复通知;账户系统接收到充值系统的通知后修改充值状态。如果账户系统未接受到通知,账户系统会主动调用充值系统接口进行结果查询。
-
最大努力通知特点:
- 有一定的消息重复通知机制。因接收方可能没有收到通知,此时要有一定的机制对消息重复通知。
- 消息校对机制。如果发起方尽最大努力也没有通知到接收方,或接收方消费消息后要再次消费,此时可由接收方主动向通知方查询处理结果来满足需求。
-**最大努力通知与可靠消息一致性不同点**
-- 解决方案思想不同:
+最大努力通知与可靠消息一致性方案不同点:
+1. 解决方案思想不同:
- 可靠消息一致性,发起通知方需要保证将消息发送出去,并且将消息发送到接收方,消息的可靠性关键由发起方来保证。
- 最大努力通知,发起通知尽最大努力的将业务处理结果通知接收方,但是消息可能接收不到,此时需要接收通知方主动调用发起方的查询业务处理结果接口,通知的可靠性关键在接收方。
-- 业务场景不同:
+2. 业务场景不同:
- 可靠消息一致性关注的是交易过程事务的一致性,以异步的方式完成交易。
- 最大努力通知关注的是交易后的通知事务,即将交易结果可靠的通知出去。
-- 技术解决方向不同:
+3. 技术解决方向不同:
- 可靠消息一致性要解决消息从发出到接收的一致性,即发出消息并且被接收到。
- 最大努力通知无法保证发出到接收的一致性,只提供消息接收的可靠性机制。消息接收可靠机制指,最大努力的将通知发送给接收方,当消息无法被接收方接收时,由接收方主动查询该消息。
-### 解决方案
-通过对最大努力通知的理解,采用MQ的ack机制可以实现最大努力通知。
+采用MQ的ACK机制可以实现最大努力通知。
-#### 方案1
+#### MQ方案1
![分布式事务-017](/iblog/posts/annex/images/essays/分布式事务-017.png)
执行流程:
- 发起通知方将通知发送给MQ;
- 接收方监听MQ;
-- 接收通知方接收消息,业务处理完成回应ack,接收方若没有回应ack则MQ重复通知;
+- 接收通知方接收消息,业务处理完成回应ACK,接收方若没有回应ACK则MQ重复通知;
- 如果消息没有发送出去可由接收方主动请求发起方查询业务结果接口,通过该接口校对消息的一致性;
方案1中接收通知方MQ接口,即接收通知方监听MQ,此方案主要应用于应用与内部应用之间的通知。
-#### 方案2
+#### MQ方案2
![分布式事务-018](/iblog/posts/annex/images/essays/分布式事务-018.png)
交互流程:
- 发起通知方将消息通知给MQ。使用可靠消息一致方案中的事务消息保证本地事务与消息的原子性,最终将通知先发给MQ;
-- 通知程序监听MQ,接收MQ消息。通知程序如果没有回应ack则MQ会重复通知;
+- 通知程序监听MQ,接收MQ消息。通知程序如果没有回应ACK则MQ会重复通知;
- 通知程序通过互联网接口协议调用接收通知方接口,完成通知。通知程序调用接收方接口成功就表示通知成功,即MQ消费成功,MQ将不再向通知程序投递消息;
- 接收通知方可通过消息校对接口来校对消息的一致性;
-方案2中由于通知程序与MQ接口,通知程序监听MQ,收到MQ消息后由通知程序通过互联网接口协议调用接收通知方。此方案主要应用于外部应用之间的通知。
-
-
-## 分布式解决方案对比
-**2PC**最大的诟病是一个阻塞协议。RM在执行分支事务后需要等待MT决定,此时服务会堵塞并锁定资源,由于其堵塞机制和最差时间复杂度较高,因此这种设计不能适应随着事务涉及的服务数量增多而扩展的需要,很难用于并发较高以及事务生命周期较长的分布式服务中。
-
-如果拿**TCC**的事务处理流程与2PC做比较,2PC通常都是在跨库的DB层面,而TCC则在应用层面的处理,需要通过业务逻辑来实现。这种分布式事务的实现方式优势在于,可以让应用自己定义数据库操作的粒度,使得降低锁冲突、提高吞吐量。不足之处是对应用的侵入性非常强,业务逻辑的每个分支都要实现try、confirm、cancel三个操作;此外实现难度也比较大,需要按照网络状态、系统故障的等不同失败原因进行不同回滚策略。
-
-**可靠消息最终一致性**适合执行周期长且实时性要求不高的业务场景。引入消息机制后,同步的事务操作变为基于消息执行的异步操作,避免了分布式事务中同步堵塞操作的影响,并实现了两个服务之间的解耦。
-
-**最大努力通知**是分布式事务中要求最低的一种,适用于一些最终一致性时间敏感度低的业务;允许发起通知方处理失败,在接收通知方收到失败通知后积极进行失败处理,无论发起通知方如何处理结果都不会影响到接收方的后续处理;发起通知方需要提供查询执行情况的接口,用于接收通知方校对结果。
-
-| | 2PC | TCC | 可靠消息最终一致性 | 最大努力通知 |
-| ---------- | -------- | ---------- | ------------------ | ------------ |
-| 一致性 | 强一致性 | 最终一致性 | 最终一致性 | 最终一致性 |
-| 吞吐量 | 低 | 中 | 高 | 高 |
-| 实现复杂度 | 易 | 难 | 中 | 易 |
-
-
-
-
+方案2中由于通知程序与MQ接口,通知程序监听MQ,收到MQ消息后由通知程序通过互联网接口协议调用接收通知方,此方案主要应用于外部应用之间的通知。
diff --git a/blog-site/public/index.xml b/blog-site/public/index.xml
index e4ca4db5b..9b6d9aa86 100644
--- a/blog-site/public/index.xml
+++ b/blog-site/public/index.xml
@@ -734,7 +734,7 @@
http://localhost:1313/iblog/posts/essays/distributed-transaction/
分布式事务详解
A(Availability
):可用性是指任何事务操作都可以获得响应结果,且不会出现响应超时或响应错误。
-上图中,商品信息的读取满足可用性就是要实现如下目标:1.从数据库接收到数据查询的请求则立即能够响应数据的查询结果;2.从数据库不允许出现响应超时或响应错误的情况;
如何实现可用性:
-Availability
):可用性是指任何事务操作都可以获得响应结果,且不会出现响应超时或响应错误。
+上图中,商品信息的读取满足可用性就是要实现如下目标:1.从数据库接收到数据查询的请求则立即能够响应数据的查询结果;2.从数据库不允许出现响应超时或响应错误的情况;
+写入主数据库后要将数据数据同步到从数据库,但由于要保证从数据库的可用性,不可将从数据库中的资源进行锁定。
+即使数据还没有从主数据库同步过来,从数据库也要返回查询的数据,哪怕是旧数据,如果连旧数据也没有则可以按照约定返回一个默认信息,但不能返回错误或超时。
+分布式系统可用性的特点就是所有请求都要有响应,且不会出现响应超时或响应错误。Partition tolerance
):分布式系统的各个结点部署在不同的子网,这就是网络分区,不可避免的会出现由于网络问题而导致结点之间的通信失败,此时仍可以对外提供服务,这就是分区容忍性。
+上图中,商品信息的读写满足分区容忍性就是要实现如下目标:1.主数据库向从数据库同步数据失败,不影响读写操作;2.其中一个结点挂掉不影响另外一个结点提供服务;
+实现分区容忍性尽量使用异步取代同步操作,例如使用异步的方法将数据从数据库同步到从数据库,这样的结点之间才能有效的解耦合。添加从数据库结点,其中一个从数据结点挂掉其他从结点来提供服务
+分区容忍性是分布式系统具备的基本的能力。分布式系统可用性的特点:
-P-Partition tolerance: -分布式系统的各个结点部署在不同的子网,这就是网络分区,不可避免的会出现由于网络问题而导致结点之间的通信失败,此时仍可以对外提供服务,这就是分区容忍性。
-上图中,商品信息的读写满足分区容忍性就是要实现如下目标:
-如何实现分区容忍性:
-分布式分区容忍性特点:
-在所有分布式事务场景中不会同时具备CAP三个特征,因为在具备了P的前提下C和A是不能共存的。
-例如,下图满足了P分区容忍性
- -上图分区容忍性含义:
+例如,下图满足了P分区容忍性 +
在分区容忍性存在的前提下,一致性和可用性存在矛盾:
在分布式的环境下,一致性和可用性只能存在一种,即AP、CP。
+在分布式的环境下,一致性和可用性只能存在一种,即AP、CP:
zookeeper
就是一个追求强一致性的例子;例如,跨行转账,一次转账请求需要等待双方银行都完成整个事务才算完成。如果不在分布式的环境下,一致性和可用性其实是不矛盾的:
CAP是一个已经被证实的理论:一个分布式系统最多只能同时满足一致性、可用性、分区容忍性中的两种。它可以作为我们进行架构设计、技术选型的考量标准。对于大型互联网应用场景来说,结点众多、部署分散,而且现在的集群规模越来越大,所以结点故障、网络故障是常态,而且要保证服务可用性达到N个9(99.99..%),并要达到良好的响应性能来提高用户的体验,因此一般都会做出以下选择:保证可用性和分区容忍性即AP,舍弃C,强一致性,保证最终一致性。
+CAP是一个已经被证实的理论,一个分布式系统最多只能同时满足一致性、可用性、分区容忍性中的两种。它可以作为我们进行架构设计、技术选型的考量标准。对于大型互联网应用场景来说,结点众多、部署分散,而且现在的集群规模越来越大,所以结点故障、网络故障是常态,而且要保证服务可用性达到N个9(99.99..%),并要达到良好的响应性能来提高用户的体验。 +因此一般都会做出以下选择,保证可用性和分区容忍性即AP,舍弃C,强一致性,保证最终一致性。
--理解强一致性与最终一致性: -CAP理论说明一个分布式系统最多能同时满足一致性、可用性、分区容忍性这三项中的两项;其中AP在实际应用中比较多,AP舍弃一致性,保证可用性和分区容忍性,但是在实际生产中很多场景都要实现一致性,比如前边的例子,主数据库向从数据库同步数据,即使不要一致性,但是最终也要将数据同步成功来保证数据一致,这种一致性和CAP中的一致性不同,CAP中的一致性要求在任何时间查询每个结点数据都必须保证一致,它强调的是一致性; -但是最终一致性是允许可以在一段时间内每个结点数据不一致,但是经过一段时间后每个结点的数据必须一致,它强调的是数据的最终一致性。
-
BASE是Basically Available(基本可用)、Soft state(软状态)、Eventually consistent(最终一致性) 这三个短语的缩写。 +
CAP理论说明一个分布式系统最多能同时满足一致性、可用性、分区容忍性这三项中的两项。其中AP在实际应用中比较多,AP舍弃一致性,保证可用性和分区容忍性,但是在实际生产中很多场景都要实现一致性,比如主数据库向从数据库同步数据,即使不要一致性,但是最终也要将数据同步成功来保证数据一致,这种一致性和CAP中的一致性不同。 +CAP中的一致性要求在任何时间查询每个结点数据都必须保证一致,但是最终一致性是允许在一段时间内每个结点数据不一致,经过一段时间后每个结点的数据必须一致,它强调的是数据的最终一致性。
+BASE理论强调的就是最终一致性,BASE是Basically Available
(基本可用)、Soft state
(软状态)、Eventually consistent
(最终一致性) 这三个短语的缩写。
BASE理论是对于CAP中AP的一个扩展,通过牺牲强一致性来获得可用性,当出现故障允许的部分不可用但要保证核心功能可用,允许数据在一段时间内是不一致的,但最终达到一致的状态。满足BASE理论的事务,我们称之为柔性事务。
针对不同的分布式场景常见的解决方案有2PC、TCC、可靠消息最终一致性、最大努力通知这几种。
-2PC即两阶段提交协议,是将整个事务流程分为两个阶段:准备阶段(Prepare)、提交阶段(Commit),2是指两个阶段,P是准备阶段,C是提交阶段。
-举例,张三,李四聚餐,饭店老板要求先买单才能出票。张三李四都不愿请客,只能AA。只有张三和李四都付款,老板才能出票安排就餐。
-例子中形成了一个事务,若张三或李四其中一人拒绝付款,或者钱不够,老板都不会出票,并且把已收的钱退回。
-整个事务过程由事务管理器和参与者组成,老板就是事务管理器,张三、李四就是事务参与者,事务管理器负责抉择整个分布式事务的提交和回滚,事务参与者负责自己的本地事务提交和回滚。
-在计算机中部分关系型数据库如oracle、mysql支持两阶段提交协议:
+解决方案 | +描述 | +优点 | +缺点 | +适用场景 | +
---|---|---|---|---|
2PC (Two-Phase Commit) | +一种经典的分布式事务协议,确保所有参与者要么全部提交,要么全部回滚。 | +确保了事务的原子性,事务一致性较强。 | +协调者崩溃或参与者崩溃可能导致事务不一致或阻塞。 | +需要强一致性保证的场景。 | +
TCC (Try-Confirm-Cancel) | +通过预留资源、确认提交或取消操作来保证分布式事务的一致性。 | +相比2PC更具弹性,支持更高的可用性和容错性。 | +实现复杂,需处理预留资源和取消操作的逻辑。 | +适用于需要灵活处理和补偿的场景。 | +
可靠消息最终一致性 | +通过消息中间件保证消息可靠投递,最终实现数据一致性。 | +高可用性,适用于网络中断和系统崩溃情况,能够实现最终一致性。 | +消息处理可能会出现延迟,需要处理重复消息和消息丢失等问题。 | +数据一致性需求不那么强,但需容忍最终一致性的场景。 | +
最大努力通知 | +通过尽最大努力发送消息,尝试确保消息到达,但不保证最终一致性。 | +实现简单,性能开销小,适用于不严格要求一致性的场景。 | +消息可能会丢失或重复处理,无法保证一致性。 | +不需要严格一致性的场景,如日志记录等。 | +
2PC最大的诟病是一个阻塞协议。RM在执行分支事务后需要等待MT决定,此时服务会堵塞并锁定资源,由于其堵塞机制和最差时间复杂度较高,因此这种设计不能适应随着事务涉及的服务数量增多而扩展的需要,很难用于并发较高以及事务生命周期较长的分布式服务中。
+如果拿TCC的事务处理流程与2PC做比较,2PC通常都是在跨库的DB层面,而TCC则在应用层面的处理,需要通过业务逻辑来实现。这种分布式事务的实现方式优势在于,可以让应用自己定义数据库操作的粒度,使得降低锁冲突、提高吞吐量。不足之处是对应用的侵入性非常强,业务逻辑的每个分支都要实现try、confirm、cancel三个操作;此外实现难度也比较大,需要按照网络状态、系统故障的等不同失败原因进行不同回滚策略。
+可靠消息最终一致性适合执行周期长且实时性要求不高的业务场景。引入消息机制后,同步的事务操作变为基于消息执行的异步操作,避免了分布式事务中同步堵塞操作的影响,并实现了两个服务之间的解耦。
+最大努力通知是分布式事务中要求最低的一种,适用于一些最终一致性时间敏感度低的业务;允许发起通知方处理失败,在接收通知方收到失败通知后积极进行失败处理,无论发起通知方如何处理结果都不会影响到接收方的后续处理;发起通知方需要提供查询执行情况的接口,用于接收通知方校对结果。
+在实际开发中,可靠消息最终一致性是较为常见的解决方案,特别是在微服务架构和高并发场景中,它能够提供较好的灵活性和扩展性。如果对于需要严格事务保证的系统,2PC和TCC可以提供更强的一致性保障。
+2PC即两阶段提交协议,是将整个事务流程分为两个阶段:准备阶段(Prepare
)、提交阶段(Commit
)。
举例,张三、李四聚餐,饭店老板要求先买单才能出票。张三李四都不愿请客,只能AA。只有张三和李四都付款,老板才能出票安排就餐。 +准备阶段,老板要求张三付款,张三付款;老板要求李四付款,李四付款;提交阶段:老板出票,两人拿票纷纷入座就餐。
+例子中形成了一个事务,若张三或李四其中一人拒绝付款,或者钱不够,老板都不会出票,并且把已收的钱退回。 +整个事务过程由事务管理器和参与者组成,老板就是事务管理器,张三、李四就是事务参与者,事务管理器负责抉择整个分布式事务的提交和回滚,事务参与者负责自己的本地事务提交和回滚。
+在计算机中部分关系型数据库如Oracle、MySql支持两阶段提交协议:
Prepare
消息,每个数据库参与者执行本地事务,并写本地的Undo/Redo
日志,此时事务还没有提交。
-Undo日志是记录修改前的数据,用于数据库回滚;Redo日志是记录修改后的数据,用于提交事务后写入数据文件。
-注意:必须在最后释放锁资源
-
成功情况:
失败情况:
-2PC具体解决方案.
2PC的传统方案是在数据库层面实现的,如:oracle、mysql都支持2PC协议,为了统一标准减少行业内不必要的对接成本,需要制定标准化的处理模型即接口标准,国际开放标准组织OpenGroup定义了分布式处理模型DTP(Distributed Transaction Processing Reference Model
)。
2PC的传统方案是在数据库层面实现的,如Oracle
、MySql
都支持2PC协议。为了统一标准减少行业内不必要的对接成本,需要制定标准化的处理模型即接口标准,国际开放标准组织OpenGroup
定义了分布式处理模型DTP(Distributed Transaction Processing Reference Model
)。
DTP模型定义如下角色:
Application Program
即应用程序,可以理解为使用分布式事务的程序。Resource Manager
即资源管理器,可理解为事务的参与者,一般情况是指一个数据库实例,通过资源管理器对该数据库进行控制,资源管理器控制这分支事务。Transacition Manager
即事务管理器,负责协调事务和事务管理,它控制着全局的事务,管理事务的生命周期,并协调各个资源管理器。Transacition Manager
即事务管理器,负责协调事务和事务管理,它控制着全局的事务,管理事务的生命周期,并协调各个资源管理器。
+全局事务是指分布式处理事务环境中,需要操作多个数据库共同完成一个动作,这个工作即是一个全局事务。
以新用户注册送积分为例:
执行流程如下:
应用程序持有数据库和积分库两个数据源。
-应用程序通过事务管理器通知用户库的资源管理器新增用户,同时也通知积分库的资源管理器为该用户增加积分,资源管理器此时并未提交事务,此时用户和积分资源锁定。
-事务管理器收到执行回复,只要有一方失败则分别向其他方发起事务回滚,回滚完毕,资源释放锁;或事务管理器收到执行回复,全部成功,此时向所有资源管理器发起提交事务,提交完毕,资源释放。
-DTP模型定义TM和RM之间通讯的接口规范叫XA,简单理解为数据库提供的2PC接口协议,基于数据库的XA协议来实现2PC又称为XA方案。
-以上三个角色之间的交互方式如下:
-整个2PC的事务管理流程涉及到三个角色:AP、RM、TM。AP指的是使用2PC分布式事务的应用程序;RM指的是资源管理器,它控制这分支事务;TM指的是事务管理器,它控制着全局事务。
-在准备阶段RM执行实际的业务操作,但是不提交事务,资源锁定;在提交阶段TM会接受RM在准备阶段的执行回复,只要任何一个RM执行失败,TM会通知所有的RM进行回滚操作,否则TM将会通知RM提交事务。提交阶段结束释放资源。
-XA方案存在的问题:
+整个2PC的事务管理流程涉及到三个角色:AP、RM、TM。AP指的是使用2PC分布式事务的应用程序;RM指的是资源管理器,它控制这分支事务;TM指的是事务管理器,它控制着全局事务。三个角色之间的交互方式如下:
在准备阶段RM执行实际的业务操作,但是不提交事务,资源锁定。在提交阶段TM会接受RM在准备阶段的执行回复,只要任何一个RM执行失败,TM会通知所有的RM进行回滚操作,否则TM将会通知RM提交事务,提交阶段结束释放资源。
+DTP模型定义TM和RM之间通讯的接口规范叫XA,简单理解为数据库提供的2PC接口协议,基于数据库的XA协议来实现2PC又称为XA方案。 +XA方案需要本地数据库支持XA协议,资源锁需要等到准备阶段和提交阶段结束才释放,所以性能较差。
Seata是由阿里中间件团队发起的开源项目Fescar,后更名为Seata,它是一个开源的分布式事务框架。
-传统2PC的问题在Seata中的到了解决,它通过对本地关系型数据库的分支事务的协调来驱动完成全局事务,是工作在应用层的中间件。主要优点是性能较好,且不长时间占用连接资源,它以高效并对业务0入侵的方式解决微服务场景下面临的分布式事务问题,目前提供AT模式(即2PC)和TCC模式的分布式事务解决方案。
-Seata的设计思想:
-Seata的设计目标其一是对业务零侵入,因此从业务无侵入的2PC入手,在传统方案2PC的基础上演进,并解决2PC方案面临的问题。
-Seata把一个分布式的事务理解为一个包含了若干分支事务的全局事务。全局事务的职责是协调其下管辖的分支事务达成一致,要么一起成功提交事务,要么一起回滚失败。此外,通常分支事务本身就是一个关系型数据库的本地事务。
+传统2PC的问题在Seata中得到了解决,它通过对本地关系型数据库的分支事务的协调来驱动完成全局事务,是工作在应用层的中间件。 +主要优点是性能较好,且不长时间占用连接资源,它以高效并对业务0入侵的方式解决微服务场景下面临的分布式事务问题,目前提供AT模式(即2PC)和TCC模式的分布式事务解决方案。
+Seata的设计目标其一是对业务零侵入,因此从业务无侵入的2PC入手,在传统方案2PC的基础上演进,并解决2PC方案面临的问题。 +Seata把一个分布式的事务理解为一个包含了若干分支事务的全局事务。全局事务的职责是协调其下管辖的分支事务达成一致,要么一起成功提交事务,要么一起回滚失败。此外,通常分支事务本身就是一个关系型数据库的本地事务。
-与传统2PC的模型类似,Seata定义了3个组件来协调分布式事务的处理过程:
- +与传统2PC的模型类似,Seata定义了3个组件来协调分布式事务的处理过程: +
Transaction Manager
事务管理器,需要嵌入(jar包)应用程序中工作,负责开启一个全局事务,并最终向TC发起全局提交或全局回滚的指令。Resource Manager
资源管理器,控制分支事务,负责分支事务注册,状态回报,并接收事务调节器的指令,驱动分支事务的提交和回滚。具体执行流程:
--注意:在执行注册分支事务的时候,这里事务已经提交了,提交后可以释放资源,从而提升程序性能。
+在执行注册分支事务的时候,这里事务已经提交了,提交后可以释放资源,从而提升程序性能。
Seata实现2PC与传统2PC的差别:
commit
还是rollback
,事务性资源的锁都要保持到第二阶段才释放。而Seata的做法是在第一阶段就将本地事务提交,这样可以省去第二阶段持有锁的时间,提高整体效率。Seata两阶段提交协议的演变:
+架构方面,传统2PC方案的RM实际上是在数据库层,RM本质上就是数据库自身,通过XA协议实现,而Seata的RM则是以jar包的形式作为中间件层部署在应用程序这一侧的。
+一阶段:Seata会拦截,解析SQL语义,找到SQL要更新的数据,在业务员数据更新前,将其保存为before image
,随后执行业务SQL。在业务数据更新后,将其保存为after image
,插入UNDO LOG
回滚日志;提交前向TC注册分支并生成行锁。
+随后本地事务提交,将本地事务提交的结果上报给TC,由TC协调。
+
两阶段提交方面,传统2PC无论第二阶段的决策是commit还是rollback,事务性资源的锁都要保持到第二阶段才释放。而Seata的做法是在第一阶段就将本地事务提交,这样可以省去第二阶段持有锁的时间,提高整体效率。
+二阶段-提交:执行提交操作,说明SQL执行顺利,因业务SQL在一阶段已经提交至数据库,所以Seata框架只需将一阶段保存的快照数据和行锁删掉,完成数据清理即可。 +
+二阶段-回滚:要执行回滚操作,说明SQL执行不顺利,Seata需要回滚一阶段已经执行的业务SQL还原数据。回滚方式是用before image
还原数据,但是在还原前还要校验脏写,对比数据库当前业务数据和after image
。
+对比数据库当前业务数据和after image
。
+
Seata原理简介:
---两阶段提交协议的演变:
--
-- 一阶段:业务数据和回滚日志记录在同一个本地事务中提交,释放本地锁和连接资源。
-- 二阶段: +
-TCC
+TCC是
+Try
、Confirm
、Cancel
三个词语的缩写,TCC要求每个分支事务实现三个操作,预处理Try
、确认Confirm
、撤销Cancel
。 +Try
操作做业务检查及资源预留,Confirm
做业务确认操作,Cancel
实现一个与Try
相反的操作,即回滚操作。TCC的三个阶段:
-
-- 提交异步化,非常快速地完成。
-- 回滚通过一阶段的回滚日志进行反向补偿。
+- +
Try
阶段是做业务检查一致性及资源预留,此阶段仅是一个初步操作,它和后续的Confirm
一起才能真正的构成一个完整的业务逻辑。- +
Confirm
阶段是确认提交,Try
阶段所有的分支事务执行成功后开始执行Confirm
。通常情况下,采用TCC则认为Confirm
阶段是不会出错的。即只要Try
成功,Confirm
一定成功。若Confirm
阶段真的出错了,需要引入重试机制或进行人工处理。Cancel
阶段是在业务执行错误需要回滚的状态下,执行分支事务的业务取消了,预留资源释放。通常情况下,采用TCC则认为Cancel
阶段也是一定成功的。如果Cancel
阶段真的出错了,需要引入重试机制或进行人工处理。
一阶段:seata会拦截,解析SQL语义,找到SQL要更新的数据,在业务员数据更新前,将其保存为before image,随后执行业务SQL,在业务数据更新后,将其保存为after image,插入UNDO LOG回滚日志;提交前,向 TC 注册分支生成行锁。 -随后本地事务提交,将本地事务提交的结果上报给 TC,由TC协调。
- -二阶段-提交:执行提交操作,说明SQL执行顺利,因业务SQL在一阶段已经提交至数据库,所以Seata框架只需将一阶段保存的快照数据和行锁删掉,完成数据清理即可。
- -二阶段-回滚:要执行回滚操作,说明SQL执行不顺利,Seata需要回滚一阶段已经执行的业务SQL还原数据。回滚方式是用before image还原数据,但是在还原前还要校验脏写,对比数据库当前业务数据和after image。 -对比数据库当前业务数据和after image。
- -针对不同的分布式场景常见的解决方案有2PC、TCC、可靠消息最终一致性、最大努力通知这几种。
-TCC是Try、Confirm、Cancel三个词语的缩写,TCC要求每个分支事务实现三个操作:预处理Try、确认Confirm、撤销Cancel。 -Try操作做业务检查及资源预留,Confirm做业务确认操作,Cancel实现一个与Try相反的操作,即回滚操作。TM首先发起所有分支事务的try操作,任何一个分支事务的try操作执行失败,TM将会发起所有分支事务的Cancel操作,若try操作全部成功,TM将发起所有分支事务的Confirm操作,其中Confirm或Cancel操作失败,TM会重试。
+TM首先发起所有分支事务的Try
操作,任何一个分支事务的Try
操作执行失败,TM将会发起所有分支事务的Cancel
操作。
+若Try
操作全部成功,TM将发起所有分支事务的Confirm
操作,其中Confirm
或Cancel
操作失败,TM会重试。
TM即事务管理器,TM事务管理器可以实现为独立的服务,也可以让全局事务发起方充当TM的角色。TM独立出来是为了成为公用的组件,为了考虑系统结构和软件复用。
+TM发起全局事务时生成全局事务记录,全局事务ID贯穿整个分布式事务调用链,用来记录事务上下文,追踪和记录状态。
+由于Confirm
和Cancel
失败需要进行重试或人工处理,因此需要实现幂等性,幂等性是指同一个操作无论请求多少次,其结果都相同。
分布式事务执行成功情况:
分布式事务执行失败情况:
-TCC的三个阶段:
-TM事务管理器:
-TM发起全局事务时生成全局事务记录,全局事务ID贯穿整个分布式事务调用链,用来记录事务上下文,追踪和记录状态,由于Confirm和Cancel失败需要进行重试或人工处理,因此实现为幂等,幂等性是指同一个操作无论请求多少次,其结果都相同。
-Hmily是一个高性能分布式事务TCC开源框架。基于Java语言来开发(JDK1.8),支持Dubbo,Spring Cloud等RPC框架进行分布式事务。 -目前支持以下特性:
+Hmily是一个高性能分布式事务TCC开源框架。基于Java语言来开发(JDK1.8),支持Dubbo,Spring Cloud等RPC框架进行分布式事务。
+支持以下特性:
disruptor
框架进行事务日志的异步读写,与RPC框架的性能毫无差别;SpringBoot-Starter
项目启动,使用简单;Aspect AOP
切面思想与Spring无缝集成,天然支持集群;Hmily利用AOP对参与分布式事务的本地方法与远程方法进行拦截处理,通过多方拦截,事务参与者能透明的调用到另一方的Try、Confirm、Cancel方法; -传递事务上下文;并记录事务日志,酌情进行补偿,重试等。
-Hmily是一个轻量级的TCC事务框架不需要部署独立的事务协调服务,但需要提供一个数据库来进行日志存储。
-Hmily实现的TCC服务与普通的服务一样,只需要暴露一个接口,也就是它的Try业务。Confirm/Cancel业务逻辑,只是因为全局事务提交/回滚的需要才提供的,因此Confirm/Cancel业务只需要被Hmily TCC事务框架发现即可,不需要被调用它的其他业务服务所感知。
---要实现TCC协议,必须要实现三个方法:Try、Confirm、Cancel,其中最关键的方法是Try方法,Try方法是一个事务的起点。三个方法会由不同的线程来分别调用。
-
TCC需要注意三种异常处理:空回滚、幂等、悬挂:
+Hmily是一个轻量级的TCC事务框架不需要部署独立的事务协调服务,但需要提供一个数据库来进行日志存储。
+Hmily利用AOP对参与分布式事务的本地方法与远程方法进行拦截处理,通过多方拦截,事务参与者能透明的调用到另一方的Try
、Confirm
、Cancel
方法,传递事务上下文;并记录事务日志,酌情进行补偿,重试等。
Hmily实现的TCC服务与普通的服务一样,只需要暴露一个接口,也就是它的Try
业务。Confirm/Cancel
业务逻辑,只是因为全局事务提交/回滚的需要才提供的,因此Confirm/Cancel
业务只需要被Hmily TCC事务框架发现即可,不需要被调用它的其他业务服务所感知。
要实现TCC协议,必须要实现三个方法:Try
、Confirm
、Cancel
,其中最关键的方法是Try
方法,Try方法是一个事务的起点,三个方法会由不同的线程来分别调用。
TCC需要注意三种异常处理:
空回滚:在没有调用TCC资源Try方法的情况下,调用了二阶段的Cancel方法,Cancel方法需要识别出这是一个空回滚,然后直接返回成功。
-
-出现原因是当一个分支事务所在的服务器宕机或网络异常,分支事务调用记录为失败,这个时候其实是没有执行Try阶段,当故障恢复后,分布式事务进行回滚则会调用二阶段的Cancel方法,从而形成空回滚。
-
-解决思路关键就是要标识这个空回滚,就是要知道try阶段是否已经执行了,如果执行了那就是正常回滚;如果没执行,那就是空回滚。可以在try阶段执行完毕后向表里插入一条记录进行标识,如果记录存在则try阶段执行了,如果不存在try阶段则未执行。
幂等:为了保证TCC二阶段提交重试机制不会引发数据不一致,要求TCC二阶段Try、Confirm、Cancel接口保证幂等性,这样不会重复使用或示释放资源。如果幂等控制没有做好,很有可能导致数据不一致等严重问题。
-悬挂:悬挂就是对于一个分布式事务,其二阶段Cancel接口对比Try接口先执行。
-Try
方法的情况下,调用了二阶段的Cancel
方法,Cancel
方法需要识别出这是一个空回滚,然后直接返回成功。
+出现原因是当一个分支事务所在的服务器宕机或网络异常,分支事务调用记录为失败,这个时候其实是没有执行Try
阶段,当故障恢复后,分布式事务进行回滚则会调用二阶段的Cancel
方法,从而形成空回滚。
+解决思路关键就是要标识这个空回滚,就是要知道Try
阶段是否已经执行了,如果执行了那就是正常回滚;如果没执行,那就是空回滚。可以在try阶段执行完毕后向表里插入一条记录进行标识,如果记录存在则Try
阶段执行了,如果不存在Try
阶段则未执行。Try
、Confirm
、Cancel
接口保证幂等性,这样不会重复使用或示释放资源。如果幂等控制没有做好,很有可能导致数据不一致等严重问题。Cancel
接口对比Try
接口先执行。
+出现原因是在RPC调用分支事务时,先注册分支事务,在执行RPC调用。如果此时RPC调用的网络发生错误、RPC超时后,TM就会通知RM回滚该分布式事务,可能回滚完成后RPC请求才到达,然后执行,而一个Try
方法预留的业务资源,只有该分布式事务才能使用,该分布式事务第一阶段预留的业务资源也就在也没有人能够处理,对于这种情况就称为悬挂,即业务资源预留后没办法处理。出现原因是在RPC调用分支事务时,先注册分支事务,在执行RPC调用,如果此时RPC调用的网络发生错误,RPC超时后,TM就会通知RM回滚该分布式事务,可能回滚完成后,RPC请求才到达,然后执行,而一个try方法预留的业务资源,只有该分布式事务才能使用,该分布式事务第一阶段预留的业务资源也就在也没有人能够处理,对于这种情况就称为悬挂,即业务资源预留后没办法处理。
-针对不同的分布式场景常见的解决方案有2PC、TCC、可靠消息最终一致性、最大努力通知这几种。
-可靠消息最终一致性是指当事务发起方执行完本地事务后并发出一条消息,事务参与方(消息消费者)一定能接收到消息并成功处理事务,此方案强调的是只要消息发给事务参与方最终事务要达到一致。
此方案利用消息中间件完成,事务发起方将消息发送给消息中间件,事务参与方从消息中间件接收消息,事务发起方和消息中间件之间,事务参与方和消息中间件之间都是通过网络进行通信,由于网络通信的不稳定会导致分布式事务问题。
-因此可靠消息最终一致性方案要解决几个问题:
+此方案利用消息中间件完成,因此可靠消息最终一致性方案要解决几个问题:
本地消息表该方案最初是eBay提出,此方案的核心是通过本地事务保证数据业务操作和消息的一致性,然后通过定时任务将消息发送至消息中间件,待确认消息发送给消费方成功后在将消息删除。
-以用户注册送积分举例:用户服务负责添加用户,积分服务负责添加积分
+以用户注册送积分举例,用户服务负责添加用户,积分服务负责添加积分。
执行流程:
如何保证将消息发送给消息队列?
-如何保证消费者一定能消费到消息?
-由于消息会重复投递,积分服务的增加积分操作功能要实现幂等性。
-RocketMQ是阿里巴巴的分布式消息中间件,于2012年开源并在2017年正式称为apache的项目。ApacheRocketMQ4.3之后的版本正式支持事务消息,并为分布式事务提供了便利性支持。
-RocketMQ事务消息设计则主要是为了解决生产者端的消息发送与本地事务执行的原子性问题,RockerMQ设计中broker与生产者端的双向通信能力,使得broker天生可以作为一个事务协调者存在;RockerMQ的高可用机制以及可靠消息设计原则则为事务消息在系统发生异常时依然能够保证达成事务的最终一致性。
+RocketMQ是阿里巴巴的分布式消息中间件,于2012年开源并在2017年正式称为Apache的项目。ApacheRocketMQ4.3之后的版本正式支持事务消息,并为分布式事务提供了便利性支持。
+RocketMQ事务消息设计则主要是为了解决生产者端的消息发送与本地事务执行的原子性问题。RockerMQ设计中broker
与生产者端的双向通信能力,使得broker
天生可以作为一个事务协调者存在。
+RockerMQ的高可用机制以及可靠消息设计原则则为事务消息在系统发生异常时依然能够保证达成事务的最终一致性。
执行流程:
commit
消息,此时MQ将该消息更改为可消费状态,消费者可以消费该消息;如果消费者执行本地事务失败,给MQ发送rollbac
k消息,MQ会将该消息丢弃;注意:发起方与MQ之间的网络出现问题,但此时MQ里的消息不会一直存着;MQ服务会定回查消费者方本地事务状态(实现MQ事务回查接口),如果事务已经提交了消费者仍然可以接收到该消息,如果没有提交MQ则丢弃该消息。
-针对不同的分布式场景常见的解决方案有2PC、TCC、可靠消息最终一致性、最大努力通知这几种。
-顾名思义,发起通知方通过一定机制最大努力的将业务处理结果通知到接收方。
-举个例子:
+最大努力通知,顾名思义就是发起通知方通过一定机制,最大努力的将业务处理结果通知到接收方。
+举个例子,账户系统调用充值系统接口,充值系统完成处理后向账户账户接口发起充值结果通知,如果通知失败则充值充值系统则按策略进行重复通知。 +账户系统接收到充值系统的通知后修改充值状态,如果账户系统未接受到通知,账户系统会主动调用充值系统接口进行结果查询。
-账户系统调用充值系统接口,充值系统完成处理后向账户账户接口发起充值结果通知,如果通知失败则充值充值系统则按策略进行重复通知;账户系统接收到充值系统的通知后修改充值状态。如果账户系统未接受到通知,账户系统会主动调用充值系统接口进行结果查询。
最大努力通知特点:
最大努力通知与可靠消息一致性不同点
-最大努力通知与可靠消息一致性方案不同点:
+通过对最大努力通知的理解,采用MQ的ack机制可以实现最大努力通知。
-采用MQ的ACK机制可以实现最大努力通知。
+执行流程:
方案1中接收通知方MQ接口,即接收通知方监听MQ,此方案主要应用于应用与内部应用之间的通知。
-交互流程:
方案2中由于通知程序与MQ接口,通知程序监听MQ,收到MQ消息后由通知程序通过互联网接口协议调用接收通知方。此方案主要应用于外部应用之间的通知。
-2PC最大的诟病是一个阻塞协议。RM在执行分支事务后需要等待MT决定,此时服务会堵塞并锁定资源,由于其堵塞机制和最差时间复杂度较高,因此这种设计不能适应随着事务涉及的服务数量增多而扩展的需要,很难用于并发较高以及事务生命周期较长的分布式服务中。
-如果拿TCC的事务处理流程与2PC做比较,2PC通常都是在跨库的DB层面,而TCC则在应用层面的处理,需要通过业务逻辑来实现。这种分布式事务的实现方式优势在于,可以让应用自己定义数据库操作的粒度,使得降低锁冲突、提高吞吐量。不足之处是对应用的侵入性非常强,业务逻辑的每个分支都要实现try、confirm、cancel三个操作;此外实现难度也比较大,需要按照网络状态、系统故障的等不同失败原因进行不同回滚策略。
-可靠消息最终一致性适合执行周期长且实时性要求不高的业务场景。引入消息机制后,同步的事务操作变为基于消息执行的异步操作,避免了分布式事务中同步堵塞操作的影响,并实现了两个服务之间的解耦。
-最大努力通知是分布式事务中要求最低的一种,适用于一些最终一致性时间敏感度低的业务;允许发起通知方处理失败,在接收通知方收到失败通知后积极进行失败处理,无论发起通知方如何处理结果都不会影响到接收方的后续处理;发起通知方需要提供查询执行情况的接口,用于接收通知方校对结果。
-- | 2PC | -TCC | -可靠消息最终一致性 | -最大努力通知 | -
---|---|---|---|---|
一致性 | -强一致性 | -最终一致性 | -最终一致性 | -最终一致性 | -
吞吐量 | -低 | -中 | -高 | -高 | -
实现复杂度 | -易 | -难 | -中 | -易 | -
方案2中由于通知程序与MQ接口,通知程序监听MQ,收到MQ消息后由通知程序通过互联网接口协议调用接收通知方,此方案主要应用于外部应用之间的通知。