文档章节

分布式事务之TCC事务

无忌
 无忌
发布于 2018/03/17 17:01
字数 2363
阅读 1.5K
收藏 0

行业解决方案、产品招募中!想赚钱就来传!>>>

TCC 事务介绍

在08年的软件开发2.0技术大会上,支付宝程立在PPT大规模SOA系统中的分布事务处理,提出TCC概念。 在网络上搜索分布式事务相关的博客,基本都会提及这个PPT,目前很多分布式事务开源项目也都是基于TCC的思想实现。

TCC 将事务提交分为 Try - Confirm - Cancel 3个操作。

  • Try:预留业务资源/数据效验
  • Confirm:确认执行业务操作
  • Cancel:取消执行业务操作

TCC事务处理流程和 2PC 二阶段提交类似,不过 2PC通常都是在跨库的DB层面,而TCC本质就是一个应用层面的2PC。

TCC原理图

TCC原理图,图片来自阿里公众号文章

TCC 优缺点

TCC优点:让应用自己定义数据库操作的粒度,使得降低锁冲突、提高吞吐量成为可能。

TCC不足之处:

  • 对应用的侵入性强。业务逻辑的每个分支都需要实现try、confirm、cancel三个操作,应用侵入性较强,改造成本高。
  • 实现难度较大。需要按照网络状态、系统故障等不同的失败原因实现不同的回滚策略。为了满足一致性的要求,confirm和cancel接口必须实现幂等。

TCC 事务应用场景

我们通过用户下单使用余额+红包支付来看一下TCC事务的具体应用。

假设用户下单操作来自3个系统下单系统、资金账户系统、红包账户系统,下单成功需要同时调用资金账户服务和红包服务完成支付

假设购买商品1000元,使用账户红包200元,余额800元,确认支付。

  • Try操作
    tryX 下单系统创建待支付订单
    tryY 冻结账户红包200元
    tryZ 冻结资金账户800元

  • Confirm操作
    confirmX 订单更新为支付成功
    confirmY 扣减账户红包200元
    confirmZ 扣减资金账户800元

  • Cancel操作
    cancelX 订单处理异常,资金红包退回,订单支付失败
    cancelY 冻结红包失败,账户余额退回,订单支付失败
    cancelZ 冻结余额失败,账户红包退回,订单支付失败

TCC 开源项目实战 tcc-transaction

tcc-transaction 是TCC型事务Java实现,tcc-transaction不和底层使用的rpc框架耦合,也就是使用doubbo,thrift,web service,http等都可以
首先感谢开源作者无私奉献,顺手star、fork下。

在 tcc-transaction 事例中有dubbo、http实现,在这里我们使用dubbo事例。

事例的具体功能,其实就是上面介绍的 下单使用余额+红包支付。

tcc-transaction 事务管理器日志持久化支持多种方式

引用官方1.2指南说明:tcc-transaction框架使用transactionRepository持久化事务日志。可以选择FileSystemTransactionRepository、SpringJdbcTransactionRepository、RedisTransactionRepository或ZooKeeperTransactionRepository。

我们这里演示使用SpringJdbcTransactionRepository,存储到MySQL

1. 项目准备

假设本地环境MySQL、Zookeeper都已经准备完毕

使用IDEA,将项目克隆到本地

我们使用的实例为tcc-transaction-dubbo-sample

  • tcc-transaction-dubbo-capital 资金账户dubbo服务
  • tcc-transaction-dubbo-capital-api 资金账户dubbo接口定义
  • tcc-transaction-dubbo-order 下单系统
  • tcc-transaction-dubbo-redpacket 红包账户dubbo服务
  • tcc-transaction-dubbo-redpacket-api 红包账户dubbo接口定义

执行数据库脚本: tcc-transaction\tcc-transaction-tutorial-sample\src\dbscripts\create_db_cap.sql (资金账户)

tcc-transaction\tcc-transaction-tutorial-sample\src\dbscripts\create_db_ord.sql (订单库)

tcc-transaction\tcc-transaction-tutorial-sample\src\dbscripts\create_db_red.sql (红包账户)

tcc-transaction\tcc-transaction-tutorial-sample\src\dbscripts\create_db_tcc.sql (事务日志持久化)

修改项目配置: Zookeeper 配置

zookeeper.address=127.0.0.1:2181

如果非默认配置,需要将tcc-transaction-dubbo-sample 下的模块全部修改

JDBC连接配置:

jdbc.driverClassName=com.mysql.jdbc.Driver
tcc.jdbc.url=jdbc:mysql://127.0.0.1:3306/TCC?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true
jdbc.username=root
jdbc.password=

如果非默认配置,需要将tcc-transaction-dubbo-sample,tcc-transaction-sample-domain 下项目模块修改

2. 项目发布

实例目前都是使用的Tomcat发布,我们先部署Tomcat:

服务全部启动成功:

image

3. 多种事务场景测试

  • 第一种情况:红包账户冻结成功(try)、资金账户冻结成功(try),订单操作异常(try)

模拟异常代码:

image

购买结果:

image

此时订单支付失败,红包账户冻结金额、资金账户冻结金额全部退回。
通过多种类似方式测试,例如:红包账户冻结异常、资金账户冻结异常,都会调cancel,退回冻结资源。所以在try阶段的任意一方异常,都会执行全局回滚。

  • 第二种情况:订单处理成功(confirm),资金账户扣减成功(confirm),但红包账户扣减失败(confirm)

模拟异常代码,在红包扣减 confirm 操作制造异常:

image

购买结果:

image

此时订单为支付成功,但实际红包金额还处在冻结状态,事务管理器记录订单confirm操作未执行成功,系统会不断重试调用订单的confirm操作,直到红包扣减成功。

手动将红包服务异常代码去掉,重启服务,等到下一次重试,红包冻结金额被扣除成功。

  • 第三种情况: 资金账户冻结成功(try),红包账户冻结成功(try),订单处理失败(confirm)

模拟异常代码,在订单 confirm 操作制造异常:

image

购买结果:

image

此时订单支付成功,但实际资金账户冻结金额、红包冻结金额都还没有扣除成功,事务管理器记录订单confirm操作未执行成功,系统会通过不断重试订单的confirm操作,直到资金账户和红包账户扣减成功。

手动将异常代码去掉,重启服务,等到下一次重试,红包和资金账户冻结金额被扣除。

  • 第四种情况:在第一种情况下,订单cancel操作处理失败(cancel)

模拟异常代码,在第一种情况下基础,在cancel操作上在制造异常: image

购买结果:

image

此时订单支付失败,资金账户、红包账户冻结成功,事务管理器记录订单cancel操作失败,系统会不断重试订单的cancel操作,直到资金账户和红包账户冻结金额退回账户。

手动将异常代码去掉,重启服务,下一次重试cancel操作,资金账户和红包账户冻结金额退回。

总结: try 操作成功,进入 confirm 操作,只要 confirm 处理失败(不管是协调者挂了,还是参与者处理失败或超时),系统通过不断重试直到处理成功。 进入 cancel 操作也是一样,只要 cancel 处理失败,系统通过不断重试直到处理成功。

引用一段对话,具体说明TCC使用场景,以及和2PC对比

问题

  1. 对于转账的cancel事务,相对简单,只要把账务冲负即可。可一般的业务逻辑会涉及很多流程、单证等操作,尤其是历史系统,应该很难改造成tcc结构的吧,不知道你们用tcc用在什么场景下?
  2. 我第一次是在支付宝架构师程立PPT中听说tcc结构的,不知道你的实现跟阿里系的实现是什么关系,目前应用的规模大吗?
  3. 我理解try程序完成后,立即提交try事务,不会有锁事务竞争。可这个时候账户余额的状态也被设置成了类似不可读的状态吧,依然不可以在其他业务中查询账户余额,那么这种方案比2PC优势具体在什么地方?

回答

  1. 我的感觉TCC是比较适合具有较强一致性要求的场景,账务系统就是这样场景;应用TCC也有一定的开发成本,如果没有强一致性要求,可以考虑其他补偿型方案;
  2. 目前已应用在线上环境多个应用,主要就是应用账务系统里使用;因为不是开源的,我没有看过阿里的实现,部分借鉴了他们的思路;希望有机会能看看;
  3. 在Try结束后,账户余额会有部分资金冻结,其他业务不可以使用冻结资金;和2PC比较的话,理解下来有两点:
  • 2PC是基于资源层(如数据库),TCC是基于SOA服务
  • 2PC是是用全局事务,数据被lock的时间跨整个事务,直到全局事务结束;而TCC里每个对资源操作的是本地事务,数据被lock的时间短,可扩展性好

其实目前阿里分布式事务解决方案--GTS(Gloabel Trasaction Service)正在公测中,详情可以参考这篇公众号文章:GTS来了!阿里微服务架构下的分布式事务解决方案

参考资料

无忌
粉丝 35
博文 33
码字总数 36205
作品 0
深圳
私信 提问
加载中
请先登录后再评论。
工作流管理系统--Pegasus WMS

Pegasus (飞马座)工作流管理系统包括一套技术标准工作流程应用程序中执行帮助许多不同的环境中,包括桌面、校园集群、网格、云。它弥补了科学领域和执行环境通过自 动映射到分布式资源的高层工...

匿名
2013/02/24
5.3K
0
开源数据访问组件--Smark.Data

Smark.Data是基于Ado.net实现的数据访问组件,提供基于强类型的查询表达式进行灵活的数据查询,统计,修改和删除等操作;采用基于条件驱动的操作模式,使数据操作更简单轻松;内部通过标准SQL...

泥水佬
2013/03/12
2.5K
0
JBoss 事务服务--Narayana

JBoss 事务服务(JBossTS 也叫 Narayana )保护企业数据破坏,保证数据完整、准确。为基于Java的应用程序(包括那些写给JEE和EJB框架)从而消除风险和相关成本非常耗时的和解失败后。...

匿名
2012/11/04
1.3K
0
高效 Java Web 开发框架--JessMA

JessMA 是功能完备的高性能 Full-Stack Web 应用开发框架,内置可扩展的 MVC Web 基础架构和 DAO 数据库访问组件(内部已提供了 Hibernate、MyBatis 与 JDBC DAO 组件),集成了 Action 拦截...

伤神小怪兽
2012/11/13
9.2K
3
创新团队的效率工具--TeamToy

TeamToy是什么? TeamToy是专为创新团队设计的效率工具,它以【事】为核心,带动整个团队进行有价值的交流。在设计上,TeamToy以简捷为目标,更适合于移动设备和触屏。 TeamToy和TODO工具有什...

Easychen
2013/01/05
1.4W
0

没有更多内容

加载失败,请刷新页面

加载更多

什么是移动语义? - What is move semantics?

问题: I just finished listening to the Software Engineering radio podcast interview with Scott Meyers regarding C++0x . 我刚刚结束了对Scott Meyers进行的有关C ++ 0x的Software En......

技术盛宴
今天
24
0
算法与数据结构体系课

算法与数据结构体系课【超清原画】 下载地址:百度云盘 从0到工作5年,面试、进大厂、搭建知识体系、拓展技术上限 你不再需要其它算法与数据结构课程了 为什么学算法已经是一个不应该问的问题...

1930133570
今天
21
0
如何停止跟踪并忽略对Git中文件的更改? - How to stop tracking and ignore changes to a file in Git?

问题: I have cloned a project that includes some .csproj files. 我已经克隆了一个包含一些.csproj文件的项目。 I don't need/like my local csproj files being tracked by Git (or bei......

富含淀粉
今天
25
0
Redis阻塞

可能存在问题 内在原因:API或数据结构使用不合理、CPU饱和、持久化阻塞等 外在原因:CPU竞争、内存交换、网络问题等 问题处理: API或数据结构使用不合理,可能存在慢查询或者大对象: 发现...

游泳鸟
今天
17
0
OSChina 周五乱弹 —— 来人,上幼儿园老师跳舞的图!

Osc乱弹歌单(2020)请戳(这里) 【今日歌曲】 小小编辑:《奇跡の海》- 坂本真綾 《奇跡の海》- 坂本真綾 手机党少年们想听歌,请使劲儿戳(这里) 巴蜀(@巴拉迪维)最近有点闹心了, @巴...

小小编辑
今天
64
1

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部