作者:ptti

起源:恒生LIGHT云社区

通过后面的文章《seata入门介绍与seata-service部署与验证》,咱们对seata曾经有一个大体的意识,并且也理解到seata分布式事务AT模式,明天咱们介绍SEATA分布式事务框架中TCC事务框架。打算从原理、理论原型演示、举荐的利用场景、注意事项等这几个维度去介绍TCC分布式事务。

首先介绍一下TCC,对于TCC(Try-Confirm-Cancel)的概念,最早是由Pat Helland于2007年发表的一篇名为《Life beyond Distributed Transactions:an Apostate’s Opinion》的论文提出。

TCC作为一种与平台无关的形象的凋谢的计划,有泛滥厂商有本人的实际。已知比拟风行的有开源框架有ByteTCC, SEATA,恒生电子也有本人的TCC实现。理解SEATA TCC原理举荐浏览以下两个材料:

SEATA的官网介绍:https://SEATA.io/zh-cn/docs/d...

蚂蚁金服相干开发者分享:https://www.bilibili.com/vide...

对于TCC的解释:

  • Try阶段:尝试执行,实现所有业务查看(一致性),预留必须业务资源(准隔离性)
  • Confirm阶段:确认执行真正执行业务,不作任何业务查看,只应用Try阶段预留的业务资源,Confirm操作满足幂等性。要求具备幂等设计,Confirm失败后须要进行重试。
  • Cancel阶段:勾销执行,开释Try阶段预留的业务资源
    Cancel操作满足幂等性Cancel阶段的异样和Confirm阶段异样解决计划基本上统一。

对TCC的了解概括如下:

  • 基于Confirm 与 Cancel工作执行必然胜利的假如下,TCC依然是一个2PC协定。
  • 在分布式环境下,它没有提供一个全局的锁的机制去管制资源竞争,仅是约定一个异样时解决回滚操作的流程。

原型演示:

本文波及demo 基于Springcloud + Feign。采纳Spring Boot工程,整合Spring Cloud Feign,业务数据库采纳的Mysql8.0。

1、业务DB初始化,应用相干脚本构建业务db。

2、maven project部署,蕴含三个业务模块:account用户核心,order订单核心,storage库存核心。

order是整体业务的入口。

要害依赖

  • spring-cloud-alibaba-SEATA-x.x.x.RELEASE-sources.jar SEATA与 Spring Cloud 原生组件(Feign, Hystrix …)适配与集成。
  • SEATA-all-x.x.x.jar SEATA 的外围业务逻辑。
  • SEATA-spring-boot-starter.x.x.x.jar 与spring boot的集成。

业务一致性外围接口

OrderTccAction.javaAccountTccAction.javaStorageTccAction.java

3、整体逻辑如下图:

4、初始化数据信息

账户余额表

订单数据表

库存信息表

场景演示1:演示一次失常下单胜利过程

申请返回失常

数据库合乎预期

场景演示2:演示一次库存有余下单失败过程

注:撤销订单的过程可能是异步实现;

外围代码:

后果演示

数据验证,订单并未生成

以上,演示结束,当然能够设计更多场景进行验证,这里不再开展。

对于seata的TCC模式的一些注意事项与举荐实际

1、对于空回归,悬挂和幂等问题,目前TCC模式下,业务同学必须本人解决这3个问题。如何设计事务查问表去解决这3个问题是具备肯定的技术难度的。例如采纳了一个全局的动态的ConcurrentHashMap ResultHolder.map 作为事务查问表解决了幂等问题,供参考。须要到网上查找更多相干材料学习。当然SEATA目前曾经实现了一个通用的事务查问表性能,框架有能力本人去解决这3个问题。

2、二阶段的动作必须胜利:一阶段胜利后,二阶段的Confirm与Cancel 动作必须胜利是TCC模式的约定与前提。开发者须要依据本人理论的业务场景,去判断相干的业务逻辑是放在Try中还是放在Confirm中。 在示例代码中存在一个比拟典型的业务划分的办法,即在Try中操作frozen 字段锁定账户金额/产品库存,在Confirm中操作used字段去正式扣款/扣库存。如果没有frozen字段,那么扣款/扣库存的动作应该搁置于Try办法中而不是Confirm办法中。

3、默认不反对并发多线程。

基于SEATA的源码剖析与理论代码验证;TCC模式自身对多线程并发执行反对无限。

如果开拓其余线程执行工作调用(无论是本地调用,还是RPC/HTTP近程调用),不会退出本地全局事务。

基于此问题,曾经在社区有相干实践经验的开发者确认,通过本人获取xId退出到相干线程的ThreadLocalMap中就能够把以后线程执行的工作join到全局事务中;

解决了本地调用场景的前提下,实践上近程调用的场景不须要再做额定解决,因为框架会在RPC/Http发动之前拦挡申请,将相干的全局事务信息从Thread中获取,写入到申请中。

上面这个我的项目值得参考https://github.com/caohdgege/seata-async一下,他肯定水平上解决了多线程场景的问题,然而尚未验证。因工夫无限,这里并未进一步确认该计划是否100%准确无误。

4、TCC无默认数据隔离性。TCC通过约定了一个异样回滚的调用流程,仅仅是解决了分布式环境下事务的原子性问题。无论是分布式环境下,还是单机环境下的数据隔离性问题,齐全须要业务同学本人思考。在本Demo中能够看到Try or Confirm办法大多会被@Transactional 关键字润饰;单库的ACID性还须要依赖DB自身提供。

5、二阶段(Confirm与Cancel)可能会异步解决。TCC计划比拟适宜高并发的业务场景。基于confirm 与 rollback操作必然胜利的假如前提,二阶段异步解决会极大晋升高峰期业务的性能。比方本demo中的示例,客户落单后能够先只是解冻账户金额,并不间接划拨款项,等到业务高峰期完结,再约定一个工夫(可能时某个定时工作)对立划拨,从而达到削峰的成果。

到此seata分布式事务TCC模式原理和应用分享实现。


想向技术大佬们多多取经?开发中遇到的问题何处探讨?如何获取金融科技海量资源?

恒生LIGHT云社区,由恒生电子搭建的金融科技业余社区平台,分享实用技术干货、资源数据、金融科技行业趋势,拥抱所有金融开发者。

扫描下方小程序二维码,退出咱们!