当前位置:首页 > 问答 > 正文

分布式事务难题多,阿里为啥偏偏就喜欢用TCC这种方案呢?

说到分布式事务,这确实是微服务架构里一个让人头疼的大问题,想象一下,一个业务需要调用好几个不同团队维护的服务,比如下单要扣库存、扣优惠券、然后创建订单,这几个操作必须要么全部成功,要么全部失败,不能出现库存扣了但订单没生成的情况,这就是分布式事务要解决的“原子性”难题。

业界有很多方案,比如最经典的XA协议(两阶段提交),它依赖数据库本身的能力,像MySQL的XA事务,还有基于消息队列的最终一致性方案,比如阿里自己开源的RocketMQ就有事务消息的功能,那为什么阿里在很多核心业务场景下,偏偏对TCC(Try-Confirm-Cancel)方案情有独钟呢?根据阿里技术团队在多个场合的分享(例如阿里云开发者社区、开源项目Seata的文档以及一些技术博客中的阐述),这背后并不是因为TCC最简单,而是因为它最能满足阿里这种超大规模、高并发、业务逻辑极其复杂的场景对一致性性能的苛刻要求。

XA这种两阶段提交方案,虽然标准、通用,但它有个致命伤:在事务执行过程中,所有涉及到的资源(比如数据库记录)都会被锁住,这在阿里双十一那种瞬间海量并发的场景下是灾难性的,一个用户下单,可能要锁住某个热门商品的库存好几秒钟,那其他用户就只能干等着,系统吞吐量会急剧下降,这完全不可接受,TCC方案巧妙地避开了这个“长事务锁”的问题。

TCC不像XA那样一上来就动真格地锁数据,它把事务过程分成了三个明确的阶段,有点像我们生活中的“预订”流程:

  1. Try阶段(尝试阶段):这个阶段不做最终的资源操作,而是做准备工作资源预留,扣库存不是真的在数据库里减掉1,而是先把这1件库存“冻结”起来,设置一个“冻结数量”的字段为1,扣优惠券也是,先把券的状态从“未使用”改为“锁定中”,这个阶段会进行各种业务规则的检查,比如库存够不够、优惠券有没有过期,Try阶段成功,只意味着“这个操作有极大可能成功”,资源并没有真正减少,其他事务仍然可以来查询和尝试冻结剩余库存,大大降低了锁的冲突和持有时间。

    分布式事务难题多,阿里为啥偏偏就喜欢用TCC这种方案呢?

  2. Confirm阶段(确认阶段):如果所有服务的Try阶段都成功了,事务协调者就会通知大家进入Confirm阶段,这时,各个服务才执行真正的业务操作,把Try阶段冻结的资源正式消耗掉,把冻结的库存清零,同时减少真实库存;把锁定的优惠券状态改为“已使用”,这个阶段通常很快,因为准备工作都在Try阶段做完了,理论上不会失败。

  3. Cancel阶段(取消阶段):如果任何一个服务的Try阶段失败了,或者因为网络超时事务协调者没收到响应,就会启动Cancel阶段,回滚所有已经执行成功的Try操作,把冻结的库存释放掉(冻结数量减1),把锁定的优惠券状态改回“未使用”。

你看,TCC的这种“两阶段”(Try + Confirm/Cancel)和XA的“两阶段”有本质区别,TCC的锁是在Try阶段由业务代码控制的“软性锁”(比如那个冻结状态),而不是数据库层面的“硬性锁”,所以锁的粒度更细,持有时间更短,并发性能自然高出一大截,这正是阿里应对高并发压力的核心诉求。

分布式事务难题多,阿里为啥偏偏就喜欢用TCC这种方案呢?

TCC给了业务极大的灵活性,XA方案是数据库层面的,比较“笨”,它只知道提交和回滚,不理解业务语义,但TCC的Try、Confirm、Cancel三个操作都需要开发者根据具体业务来编码实现,这意味着开发者可以在这个过程中加入任何需要的业务逻辑,比如在Cancel阶段,除了释放资源,还可以记录更详细的取消日志,或者触发一些补偿性的营销活动通知,这种灵活性对于业务逻辑复杂多变的电商、金融场景来说至关重要。

TCC对业务资源的支撑范围更广,XA通常只能支持支持XA协议的关系型数据库,但在阿里的系统里,一个事务可能不仅涉及MySQL,还可能涉及Redis缓存、ES搜索引擎、甚至其他非关系型数据库,这些资源很多都不支持XA协议,TCC是业务层面的,只要你能对这个资源写出对应的Try、Confirm、Cancel代码(比如对Redis的操作是setnx,对ES的操作是创建索引),就能把它纳入到分布式事务管理中,适应性非常强。

TCC也不是完美的,它最大的代价就是业务侵入性高,开发者需要为每个参与分布式事务的服务都设计并实现三套逻辑(Try、Confirm、Cancel),代码量会增加,开发和维护的心智负担也更重,这相当于把分布式事务的复杂性从底层基础设施转移到了业务开发人员身上。

阿里之所以在很多关键场景偏爱TCC,是一种典型的技术权衡,他们用更高的开发成本(需要写更多代码),换来了在超大规模并发下至关重要的高性能(短时间锁)、高灵活性(可融入业务逻辑)和高适应性(支持多种资源),对于阿里这样体量的公司,开发资源相对丰富,而系统的稳定性和性能是生命线,因此TCC就成为了一个非常对路的选择,相比之下,对于并发量没那么大、业务逻辑相对简单的场景,使用基于消息队列的最终一致性方案或者框架封装得更好的XA方案,可能会是更经济实惠的选择。