[分布式事务-TCC] 6. TCC的优化方案之三:二阶段异步化

二阶段异步化

采用TCC模型实现分布式事务之后,分布式事务所需的资源也是按照业务的维护进行切分,每笔分布式事务之间的资源都是独立预留和消费。

单说这些可能有点难理解举个栗子就很容易理解了,账户A同时参与了两笔分布式事务,一笔是转账50元到账户B;另一笔是转账100元到账户C。

那么每笔分布式事务都会各自预留所需的资源,它们感知不到彼此的存在,也不会互相干扰。这里顺便复习一下实现TCC模型的一个关键点:业务模型的重构。

对于转账这个场景而言,是通过将原账户的余额字段一拆为三来实现的:

  1. 可用余额
  2. 未达金额
  3. 未出金额(预留资源)

优化方案都是依托于系统的运行时和业务的实际需要。在转账这个业务场景下,数据不一致的时间是很短的,当我们转账的时候,我们也是希望这笔交易能够在很短的时间内完成,否则我们肯定会认为银行不靠谱,进而产生很大的不安全感。所以,业务上就决定了转账对RT的要求很高,一阶段执行完了二阶段马上就要执行。

但是天底下的业务场景何其多,不是所有业务都需要这么极端的RT保证。

一笔交易的链路其实是很长的,收单只是万里长征第一步,后面还涉及到计收费,结算等各个环节。收了买家的钱,需要将这笔钱打到卖家的账户上。但是在现实中,卖家一般都不会实时地就能够收到这笔钱,而是通过记账的方式记录下来这笔收入,保证可以准实时地看到这笔交易出现在账单中,然后根据和收单服务方约定的结算周期(比如周,半月,月等)完成结算。

所以对结算这个业务场景,TCC一阶段执行成功后,二阶段并不一定需要马上就执行。

再举个例子,在双十一这类短时间并发量井喷到极致的时候,即使对服务集群做了最大程度的扩容,也会将能够延迟执行的任务全部延迟,来保证主要核心功能和链路的稳定性和吞吐量。

因此,二阶段的异步化是有其存在之必要和用武之地的。

有了TCC模型对于数据最终一致性的保证,只要一阶段处理成功,那么二阶段是立即,还是几小时后,甚至一个月之后执行其实都没有本质的区别。因为资源已经在一阶段中被锁定和预留了,这个资源只有在对应的二阶段才能够继续被消费。

基于这个前提,就出现了实现最终一致性的各种异步化方案。比如所谓的事务性消息服务(也被成为可靠的消息服务),这里简单介绍一下:

它能够保证两件事情:

  1. 消息发送端的本地事务业务逻辑与真正的消息投递是一个原子操作。要么同时成功,要么同时失败。
  2. 消息投递一定会保证下游消费者能够收到并完成处理。

如何理解?

可以分三个阶段来看这件事:

  1. 消息发送方在本地事务中执行业务逻辑,发送消息到事务性消息服务,后者收到消息并持久化,但是不会马上投递将这条消息投递到消息队列中
  2. 站在消息服务的角度,根据发送方的本地事务执行结果:
    • 本地事务提交成功,发送CONFIRM指令给事务性消息服务,后者更新之前收到的消息状态为有效,然后再将此消息投递到消息队列中
    • 本地事务失败回滚,发送ROLLBACK指令给事务性消息服务,后者更新之前收到的消息状态为无效,然后删除此条消息
    • 本地事务结果未知,事务性消息服务需要回查消息发送方咨询消息是可以发送,还是需要删除
  3. 消息确定可以发送到下游后添加消息到实际MQ,下游消费成功返回ACK,消息服务删除消息,否则等待下次重投,直到下游成功消费此条消息

对于时效性要求没那么高,但是又要保证最终数据一致性的业务场景,使用这种方案是非常理想的。它很好地实现了削峰填谷,让业务平稳运行的运维目标。

当然,事务性消息服务这里只是点到为止。它们本身也是很大的命题,值得花时间单独讨论。

©️2020 CSDN 皮肤主题: 大白 设计师: CSDN官方博客 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值