Seata TCC模式
一. TCC模式介绍
Seata开源了TCC模式,该模式由蚂蚁⾦服贡献。TCC模式需要⽤户根据⾃⼰的业务场景实现Try、Confirm和Cancel三个操作;事务发起⽅在⼀阶段执⾏Try⽅式,在⼆阶段提交执⾏Confirm ⽅法,⼆阶段回滚执⾏Cancel⽅法。
- Try:资源的检测和预留;
- Confirm:执⾏的业务操作提交;要求Try成功Confirm⼀定要能成功;
- Cancel:预留资源释放。
业务模型分2阶段设计:⽤户接⼊TCC,最重要的是考虑如何将⾃⼰的业务模型拆成两阶段来实现。
以“扣钱”场景为例,在接⼊TCC前,对A账户的扣钱,只需⼀条更新账户余额的SQL便能完成;但是在接⼊TCC之后,⽤户就需要考虑如何将原来⼀步就能完成的扣钱操作,拆成两阶段,实现成三个⽅法,并且保证⼀阶段Try成功的话⼆阶段Confirm⼀定能成功。
⽤户接⼊TCC模式,最重要的事情就是考虑如何将业务模型拆成2阶段,实现成TCC的3个⽅法,并且保证Try成功Confirm⼀定能成功。相对于AT模式,TCC模式对业务代码有⼀定的侵⼊性,但是TCC模式⽆AT模式的全局⾏锁,TCC性能会⽐AT模式⾼很多。
二. TCC模式改造
2.1 RM端改造
针对RM端,实现起来需要完成try/commit/rollback的实现,所以步骤相对较多但是前三步骤和AT模式⼀样
-
复制at工程为parent-seata-tcc-demo,用于tcc改造
-
修改数据库表结构,增加预留检查字段,⽤于提交和回滚
ALTER TABLE `seata_order`.`t_order` ADD COLUMN `status` int(0) NULL COMMENT'订单状态-0不可⽤,事务未提交,1-可⽤,事务提交'; ALTER TABLE `seata_points`.`t_points` ADD COLUMN `frozen_points` int(0) NULL DEFAULT 0 COMMENT '冻结积分' AFTER `points`; ALTER TABLE `seata_storage`.`t_storage` ADD COLUMN `frozen_storage` int(0) NULL DEFAULT 0 COMMENT'冻结库存 'AFTER `goods_id`;
-
删除DataSourceConfiguration,因为tcc模式下用不到
-
去掉启动类数据源包扫描 @SpringBootApplication(scanBasePackages = “com.example”, exclude = DataSourceAutoConfiguration.class)
-
具体修改见示例工程: [demo-seata-tcc-demo](git remote add origin https://gitee.com/ixinglan/parent-seata-tcc-demo.git)
注意3个注解
@LocalTCC 该注解需要添加到上⾯描述的接⼝上,表示实现该接⼝的类被 seata 来管理,seata 根据事务的状态,⾃动调⽤我们定义的⽅法,如果没问题则调⽤ Commit ⽅法,否则调⽤ Rollback ⽅法。
@TwoPhaseBusinessAction 描述⼆阶段提交 name: 为 tcc⽅法的 bean 名称,需要全局唯⼀,⼀般写⽅法名即可 commitMethod: Commit⽅法的⽅法名 rollbackMethod:Rollback⽅法的⽅法名 @BusinessActionContextParamete 该注解⽤来修饰 Try⽅法的⼊参, 被修饰的⼊参可以在 Commit ⽅法和 Rollback ⽅法中通过 BusinessActionContext 获取。
2.2 TM端改造
Demo-bussiness 不用变即可,
@GlobalTransactional(rollbackFor = Exception.class, timeoutMills = 6000, name = "sale")
tips:
- debug的时候可以把超时时间调大一点,因为事务结束或超时,则用到的seata中间表数据就清掉了
- undo_log表在tcc模式下没用了
- 所有有数据操作的都必须有try/commit/rollback的实现.
回滚效果:
提交成功效果:
Tips: 感兴趣可以debug看看中间表的数据变化情况