作者: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.java
AccountTccAction.java
StorageTccAction.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 云社区,由恒生电子搭建的金融科技业余社区平台,分享实用技术干货、资源数据、金融科技行业趋势,拥抱所有金融开发者。
扫描下方小程序二维码,退出咱们!