柔性事务解决方案之TCC

LoyaltyLu

675d8747bee7b39a6823b30b4ce76d4e.jpg

前言

在开始之前先聊一聊什么是微服务,顾名思义,微服务得从两个方面去理解,什么是"微"、什么是"服务", 微 狭义来讲就是体积小、著名的"2 pizza 团队"很好的诠释了这一解释(2 pizza 团队最早是亚马逊 CEO Bezos提出来的,意思是说单个服务的设计,所有参与人从设计、开发、测试、运维所有人加起来 只需要2个披萨就够了 )。 而所谓服务,一定要区别于系统,服务一个或者一组相对较小且独立的功能单元,是用户可以感知最小功能集。

场景

这里就不啰嗦哪些东西了,百度一大堆,咱们用代码看问题~ ~。

public function completeOrder() {
orderDao::update(); // 订单服务本地更新订单状态
accountService::update(); // 调用资金账户服务给资金帐户加款
pointService::update(); // 调用积分服务给积分帐户增加积分
}

在传统的单体架构的业务中可以使Mysql事务来保持数据的一致性,如果跨系统、跨服务、跨数据库,应该如何保持数据一致性呢?

概念引入

在了解分布式事务之前要先了解这两个概念:BASE理论及CAP定理。

BASE理论

BASE是Basically Available(基本可用)、Soft state(软状态)和Eventually consistent(最终一致性)三个短语的简写,BASE是对CAP中一致性和可用性权衡的结果,其来源于对大规模互联网系统分布式实践的结论,是基于CAP定理逐步演化而来的,其核心思想是即使无法做到强一致性(Strong consistency),但每个应用都可以根据自身的业务特点,采用适当的方式来使系统达到最终一致性(Eventual consistency)。

  • BA: Basic Availability 基本业务可用性(支持分区失败)
  • S: Soft state 柔性状态(状态允许有短时间不同步,异步)
  • E: Eventual consistency 最终一致性(最终数据是一致的,但不是实时一致)
CAP定理

对于共享数据系统,最多只能同时拥有CAP其中的两个,没法三者兼顾,任两者的组合都有其适用场景,真实系统应当是ACID与BASE的混合体,不同类型的业务可以也应当区别对待
image.png

柔性事务解决方案之TCC

进入主题,介绍下分布式事务TCC的技术方案,先上一张图。
image.png

实现

这里讲述下,我在代码中的实现思路以及方法,供大家参考,方法不一定是最好的,主要讲的是实现的一个基本思路,可能有很多内容没考虑到,需要大家的指正。

业务中设计阶段有:
try尝试阶段:预留扣除(增加)资源
confirm提交阶段:确认扣除(增加)资源
cancel回滚阶段:回滚预留资源
也就是说每个服务提供者必须要实现这三个阶段的方法
image.png

  1. 一个完整的业务活动由一个主业务服务与若干从业务服务组成;
  2. 主业务服务负责发起并完成整个业务活动;
  3. 从业务服务提供TCC型业务操作;
  4. 业务活动管理器控制业务活动的一致性,它登记业务活动中的操作, 并在业务活动提交时确认所有的TCC型操作的confirm操作,在业务活动取消时调用所有TCC型操作的cancel操作

TCC事务注意事项

并发控制

用户在实现 TCC 时,应当考虑并发性问题,将锁的粒度降到最低,以最大限度提高分布式事务的并发性。

在一阶段 Try 操作中,分布式事务 T1 和分布式事务 T2 分别预留的那一部分资源,相互之间无干扰。这样在分布式事务的二阶段,无论 T1 是提交还是回滚,都不会对 T2 产生影响,这样 T1 和 T2 可以在同一笔业务数据上并行执行。
image.png

允许空回滚

如下图所示,事务协调器在调用 TCC 服务的一阶段 Try 操作时,可能会出现因为丢包而导致的网络超时。此时事务管理器会触发二阶段回滚,调用 TCC 服务的 Cancel 操作,而 Cancel 操作调用未出现超时。

TCC 服务在未收到 Try 请求的情况下收到 Cancel 请求,这种场景被称为空回滚。空回滚在生产环境经常出现,用户在实现 TCC 服务时,应允许空回滚的执行,即收到空回滚时返回成功。
image.png

防悬挂控制

如下图所示,事务协调器在调用 TCC 服务的一阶段 Try 操作时,可能会出现因网络拥堵而导致的超时。此时事务管理器会触发二阶段回滚,调用 TCC 服务的 Cancel 操作,Cancel 调用未超时。在此之后,拥堵在网络上的一阶段 Try 数据包被 TCC 服务收到,出现二阶段 Cancel 请求比一阶段 Try 请求先执行的情况,此 TCC 服务在执行晚到的Try 之后,将永远不会再收到二阶段的 Confirm 或者 Cancel,造成 TCC 服务悬挂。

用户在实现 TCC 服务时,要允许空回滚,但是要拒绝执行空回滚之后 Try 请求,要避免出现悬挂。
图片1.png

幂等控制

无论是网络数据包重传,还是异常事务的补偿执行,都会导致 TCC 服务的 Try、Confirm 或者 Cancel 操作被重复执行;用户在实现 TCC 服务时,需要考虑幂等控制,即 Try、Confirm、Cancel 执行一次和执行多次的业务结果是一样的。
image.png

TCC事务组件

组件是基于hyper实现的,实现其主要目的是为了加强自己对TCC事务认识,组件没有生产环境使用,主要是先学习一个简单思想,然后从中找到不足加以改正,如果大家发现有什么问题可以及时联系我^ ^
GitHub:https://github.com/LoyaltyLu/...

谢谢观赏

这个篇幅较长,谢谢耐心观看,希望对您有所帮助,也希望大家提供下不同的意见,谢谢!

阅读 4k

Grace development
记录分享开发、学习中的点点滴滴
1.7k 声望
88 粉丝
0 条评论
1.7k 声望
88 粉丝
文章目录
宣传栏