承接上文Seata强一致性事务模式XA的设计理念
通用TCC模式
TCC是二阶段提交协议,Try-Confirm-Cancel(资源预留、确认操作、取消操作),Try是对当前业务资源的检查,如果成功,则Confirm提交,否则Cancel回滚。
这三个操作都需要自定义实现业务逻辑,这也是TCC和其他的事务模式不同的地方。
XA和AT都是依赖本地数据库事务进行的分布式事务的执行,而TCC完全不依赖数据库,对业务有非常大的侵入性,因为需要自定义实现这三个接口逻辑:实现Try(对业务资源的检查逻辑),Confirm(Try成功后的提交逻辑),Cancel(出现问题的回滚逻辑)。
好处是不依赖数据库,可以跨数据库、跨应用资源,管理这些对不同数据访问侵入式编码方式实现的原子操作,解决各种复杂场景下的分布式问题。
TCC在金融业务场景下用的比较多。
业务应用是TM,负责开启全局事务,事务协调器是TC,服务A和服务B是RM。
业务应用开启全局事务,具体的服务(比如服务A、B)需要实现实现Try、Confirm、Cancel三个接口逻辑。
业务应用开启全局事务,调用每个服务的Try接口,Try没有问题,则调用具体服务的Confirm进行提交或调用Cancel进行回滚。
假设服务A Try没有问题,服务B出现了问题,则调用Cancel接口,如果有一个服务出现问题就需要全局回滚,由事务协调器发起调用服务A的Cancel接口和调用服务B的Cancel接口进行回滚,这就是TCC的整体逻辑。
Seata TCC模式
Seata TCC模式和通用TCC模式原理一样。
所谓的TCC模式是把自定义的分支事务纳入全局事务中管理。
TCC和AT都是二阶段,AT支持本地事务的ACID(关系型数据库),在一阶段,会记录本地事务对数据的更新和记录更新之前的数据到日志undolog(数据快照)中。
第二阶段,如果没有问题,则提交事务和清理日志,若出现问题,则回滚,自动补偿、清理日志、释放资源。
TCC不依赖底层数据库资源的支持,所以在第一阶段,需要调用自己实现的Try接口里面的逻辑,比如银行提交扣款请求。
第一阶段没有问题的话,则第二阶段进行提交,如果第一阶段出现问题了,则第二阶段调用rollback进行回滚。
TCC侵入性比较强,需要自己实现相关的业务逻辑,但在整个过程中是没有锁的。
AT是有锁的,为了防止脏读和脏写。
下单请求给到事务协调者,首先调用订单服务Try方法执行下单中的逻辑,然后调用库存服务,锁定库存,事务协调者如果没有收到问题反馈,就调用每个具体服务的Confirm,即调用订单服务Confirm执行支付逻辑,调用库存服务Confirm执行扣减库存的逻辑,如果扣减库存出问题了,就调用订单服务的Concel执行未支付或回滚的逻辑。