原创声明:本文系做者原创,谢绝我的、媒体、公众号或网站未经受权转载,违者追究其法律责任。
XA 协议在架构上与 TCC 模型相比,最大的不一样是 XA 直接做用于资源层,然后者做用于服务层。
资源层更普适,而且对业务几乎没有侵入,可是为了适应各类业务场景使用,须要严格遵循事务 ACID 特性;服务层更接近业务,能够针对不一样业务作特定的优化处理,追求更高的极限性能。
固然,并非说 XA 协议只能做用于单个服务内部的多资源场景,跨服务的多资源场景也是能够的,只不过一样须要额外的事务传递机制。
在《分布式事务综述》一中介绍过,XA 协议经过每一个 RM(Resource Manager,资源管理器)的本地事务隔离性来保证全局隔离,而且须要经过串行化隔离级别来保证分布式事务一致性。可是,串行化隔离级别存在必定的性能问题,以下所示:
在串行化隔离级别下,会为原本不加锁的 Select 快照读操做都加上读锁,致使锁持有时间增长,并发性能进一步下降。当实现了无锁的全局一致性读取之后,好比分布式 MVCC,能够大幅减小锁持有时间,并发性能会得到较大提高。
可是无论怎么优化实现,分布式事务的热点数据并发性能最高就是趋近于单机本地事务。因此,不管是基于 XA 协议实现的分布式事务,仍是单机本地事务,都是存在热点数据并发性能极限的。
那么 XA 协议最大的做用是什么呢?其最大的做用在于数据库资源横向扩展时,能保证多资源访问的事务属性。
当单台 RM 机器达到资源性能瓶颈,没法知足业务增加需求时,就须要横向扩展 RM 资源,造成 RM 集群。经过横向扩展资源,提高非热点数据的并发性能,这对于大致量的互联网产品来讲,是相当重要的。
以上图为例,假设单台 RM 的非热点数据并发性能为 100 TPS,那么 5台 RM 就是 500 TPS,就算一个分布式事务平均涉及 2 台 RM,也有 250 TPS,提高了 2.5 倍的非热点并发能力。
综上所述,基于 XA 协议实现的分布式事务并不能提高热点并发性能,其意义在于横向扩展资源提高非热点数据并发性能时,能严格保证对多资源访问的事务 ACID 特性。
至于热点数据并发性能问题,对于通常的应用来讲,通过 SQL 层面必定的性能优化以后,其并发性能基本就可以知足业务的需求。若是通过优化,达到性能极限以后,还不能知足,就须要上升到业务层面,根据业务特色,经过专门的业务逻辑或业务架构优化来实现。
直接在资源层实现分布式事务的另一点好处是其普适性,能够对上层业务屏蔽底层实现细节。这一点在云服务时代特别有用,云服务面对的是大量的中小企业,甚至是我的开发者,业务诉求不尽相同,普适、标准的分布式事务产品是很是有必要的,可让开发者从底层技术细节中脱离出来,更专一于业务逻辑的实现,从而得到更高效、快速的业务发展。
TCC 分布式事务模型直接做用于服务层。不与具体的服务框架耦合,与底层 RPC 协议无关,与底层存储介质无关,能够灵活选择业务资源的锁定粒度,减小资源锁持有时间,可扩展性好,能够说是为独立部署的 SOA 服务而设计的。
对于 TCC 分布式事务模型,笔者认为其在业务场景应用上,有两方面的意义。
这一部分的做用与 XA 相似,服务的拆分,也能够认为是资源的横向扩展,只不过方向不一样而已。
1. 功能扩展。根据功能对数据进行分组,并将不一样的功能组分布在多个不一样的数据库上,这实际上就是 SOA 架构下的服务化。
2. 数据分片,在功能组内部将数据拆分到多个数据库上,为横向扩展增长一个新的维度。
横向扩展的两种方法能够同时进行运用:用户信息(Users)、产品信息(Products)与交易信息(Trans)三个不一样功能组能够存储在不一样的数据库中。另外,每一个功能组内根据其业务量能够再拆分到多个数据库中,各功能组能够相互独立地进行扩展。
所以,TCC 的其中一个做用就是在按照功能横向扩展资源时,保证多资源访问的事务属性。
TCC 另外一个做用就是把两阶段拆分红了两个独立的阶段,经过资源业务锁定的方式进行关联。资源业务锁定方式的好处在于,既不会阻塞其余事务在第一阶段对于相同资源的继续使用,也不会影响本事务第二阶段的正确执行。
能够发现 TCC 模型进一步减小了资源锁的持有时间。同时,从理论上来讲,只要业务容许,事务的第二阶段何时执行均可以,反正资源已经业务锁定,不会有其余事务动用该事务锁定的资源。
这对业务有什么好处呢?拿支付宝的担保交易场景来讲,简化状况下,只须要涉及两个服务,交易服务和帐务服务。交易做为主业务服务,帐务做为从业务服务,提供 Try、Commit、Cancel 接口:
1. Try 接口扣除用户可用资金,转移到预冻结资金。预冻结资金就是业务锁定方案,每一个事务第二阶段只能使用本事务的预冻结资金,在第一阶段执行结束后,其余并发事务也能够继续处理用户的可用资金。
2. Commit 接口扣除预冻结资金,增长中间帐户可用资金(担保交易不能当即把钱打给商户,须要有一个中间帐户来暂存)。
假设只有一个中间帐户的状况下,每次调用支付服务的 Commit 接口,都会锁定中间帐户,中间帐户存在热点性能问题。
可是,在担保交易场景中,七天之后才须要将资金从中间帐户划拨给商户,中间帐户并不须要对外展现。所以,在执行完支付服务的第一阶段后,就能够认为本次交易的支付环节已经完成,并向用户和商户返回支付成功的结果,并不须要立刻执行支付服务二阶段的 Commit 接口,等到低锋期时,再慢慢消化,异步地执行。
可能部分读者认为担保交易比较特殊,其实直付交易(直接把钱打到商户帐户的交易模式,Commit 接口扣除预冻结资金之后,不是转移到中间帐务,而是直接转移到商户帐户)也能够这样使用,只要提早告知商户,高峰期交易资金不是实时到帐,但保证在必定时间以内结算完成,商户应该也是能够理解的。
这就是 TCC 分布式事务模型的二阶段异步化功能,从业务服务的第一阶段执行成功,主业务服务就能够提交完成,而后再由框架异步的执行各从业务服务的第二阶段。
通用型 TCC 解决方案就是最典型的 TCC 分布式事务模型实现,全部从业务服务都须要参与到主业务服务的决策当中。
因为从业务服务是同步调用,其结果会影响到主业务服务的决策,所以通用型 TCC 分布式事务解决方案适用于执行时间肯定且较短的业务,好比互联网金融企业最核心的三个服务:交易、支付、帐务:
当用户发起一笔交易时,首先访问交易服务,建立交易订单;而后交易服务调用支付服务为该交易建立支付订单,执行收款动做,最后支付服务调用帐务服务记录帐户流水和记帐。
为了保证三个服务一块儿完成一笔交易,要么同时成功,要么同时失败,可使用通用型 TCC 解决方案,将这三个服务放在一个分布式事务中,交易做为主业务服务,支付做为从业务服务,帐务做为支付服务的嵌套从业务服务,由 TCC 模型保证事务的原子性。
支付服务的 Try 接口建立支付订单,开启嵌套分布式事务,并调用帐务服务的 Try 接口;帐务服务在 Try 接口中冻结买家资金。一阶段调用完成后,交易完成,提交本地事务,由 TCC 框架完成分布式事务各从业务服务二阶段的调用。
支付服务二阶段先调用帐务服务的 Confirm 接口,解冻买家资金;增长卖家可用资金。调用成功后,支付服务修改支付订单为完成状态,完成支付。
当支付和帐务服务二阶段都调用完成后,整个分布式事务结束。
异步确保型 TCC 解决方案的直接从业务服务是可靠消息服务,而真正的从业务服务则经过消息服务解耦,做为消息服务的消费端,异步地执行。
可靠消息服务须要提供 Try,Confirm,Cancel 三个接口。Try 接口预发送,只负责持久化存储消息数据;Confirm 接口确认发送,这时才开始真正的投递消息;Cancel 接口取消发送,删除消息数据。
消息服务的消息数据独立存储,独立伸缩,下降从业务服务与消息系统间的耦合,在消息服务可靠的前提下,实现分布式事务的最终一致性。
此解决方案虽然增长了消息服务的维护成本,但因为消息服务代替从业务服务实现了 TCC 接口,从业务服务不须要任何改造,接入成本很是低。
因为从业务服务消费消息是一个异步的过程,执行时间不肯定,可能会致使不一致时间窗口增长。所以,异步确保性 TCC 分布式事务解决方案只适用于对最终一致性时间敏感度较低的一些被动型业务(从业务服务的处理结果不影响主业务服务的决策,只被动的接收主业务服务的决策结果)。好比会员注册服务和邮件发送服务:
当用户注册会员成功,须要给用户发送一封邮件,告诉用户注册成功,并提示用户激活该会员。但要注意两点:
1. 若是用户注册成功,必定要给用户发送一封邮件;
所以,这一样须要会员服务和邮件服务保证原子性,要么都执行,要么都不执行。不同的是,邮件服务只是一种被动型的业务,并不影响用户是否可以注册成功,它只须要在用户注册成功之后发送邮件给用户便可,邮件服务不须要参与到会员服务的活动决策中。
对于此种业务场景,可使用异步确保型TCC分布式事务解决方案,以下:
由可靠消息服务来解耦会员和邮件服务,会员服务与消息服务组成 TCC 事务模型,保证事务原子性。而后经过消息服务的可靠特性,确保消息必定可以被邮件服务消费,从而使得会员与邮件服务在同一个分布式事务中。同时,邮件服务也不会影响会员服务的执行过程,只在会员服务执行成功后被动接收发送邮件的请求。
补偿型 TCC 解决方案与通用型 TCC 解决方案的结构类似,其从业务服务也须要参与到主业务服务的活动决策当中。但不同的是,前者的从业务服务只须要提供 Do 和 Compensate 两个接口,然后者须要提供三个接口。
Do 接口直接执行真正的完整业务逻辑,完成业务处理,业务执行结果外部可见;Compensate 操做用于业务补偿,抵消或部分抵消正向业务操做的业务结果,Compensate操做需知足幂等性。
与通用型解决方案相比,补偿型解决方案的从业务服务不须要改造原有业务逻辑,只须要额外增长一个补偿回滚逻辑便可,业务改造量较小。但要注意的是,业务在一阶段就执行完整个业务逻辑,没法作到有效的事务隔离,当须要回滚时,可能存在补偿失败的状况,还须要额外的异常处理机制,好比人工介入。
因为存在回滚补偿失败的状况,补偿型 TCC 分布式事务解决方案只适用于一些并发冲突较少或者须要与外部交互的业务,这些外部业务不属于被动型业务,其执行结果会影响主业务服务的决策,好比机票代理商的机票预订服务:
该机票服务提供多程机票预订服务,能够同时预订多趟行程航班机票,好比从北京到圣彼得堡,须要第一程从北京到莫斯科,以及第二程从莫斯科到圣彼得堡。
当用户预订机票时,确定但愿能同时预订这两趟航班的机票,只预订一趟航班对用户来讲没有意义。所以,对于这样的业务服务一样提出了原子性要求,若是其中一趟航班的机票预订失败,另一趟须要可以取消预订。
可是,因为航空公司相对于机票代理商来讲属于外部业务,只提供订票接口和取消预订接口,想要推进航空公司改造是极其困难的。所以,对于此类业务服务,可使用补偿型 TCC 分布式事务解决方案,以下:
网关服务在原有逻辑基础上增长 Compensate 接口,负责调用对应航空公司的取消预订接口。
在用户发起机票预订请求时,机票服务先经过网关 Do 接口,调用各航空公司的预订接口,若是全部航班都预订成功,则整个分布式事务直接执行成功;一旦某趟航班机票预订失败,则分布式事务回滚,由 TCC 事务框架调用各网关的 Compensate 补偿接口,其再调用对应航空公司的取消预订接口。经过这种方式,也能够保证多程机票预订服务的原子性。
对于如今的互联网应用来讲,资源横向扩展提供了更多的灵活性,是一种比较容易实现的向外扩展方案,可是同时也明显增长了复杂度,引入一些新的挑战,好比资源之间的数据一致性问题。
横向数据扩展既能够按数据分片扩展,也能够按功能扩展。XA 与 TCC 模型在这一点上的做用相似,都能在横向扩展资源的同时,保证多资源访问的事务属性,只不过前者做用于数据分片时,后者做用于功能扩展时。
XA 模型另一个意义在于其普适性,抛开性能问题的状况下,几乎能够适用于全部业务模式,这对于一些基础性的技术产品来讲是很是有用的,好比分布式数据库、云服务的分布式事务框架等。
TCC 模型除了跨服务的分布式事务这一层做用以外,还具备两阶段划分的功能,经过业务资源锁定,容许第二阶段的异步执行,而异步化思想正是解决热点数据并发性能问题的利器之一。
本文结合具体的业务场景和例子,对比分析了各分布式事务解决方案在性能、热点冲突、接入复杂度和适用场景等方面的能力,但愿能帮助各位读者对分布式事务有更深一层的理解。
业务各有各的不一样,有些业务能容忍短时间不一致,有些业务的操做能够幂等,不管什么样的分布式事务解决方案都有其优缺点,没有一个银弹可以适配全部。所以,业务须要什么样的解决方案,还须要结合自身的业务需求、业务特色、技术架构以及各解决方案的特性,综合分析,才能找到最适合的方案。
下一篇文章将会介绍蚂蚁金服在分布式事务上,通过多年发展,服务于内外部大量不一样业务,沉淀出的一整套分布式事务产品和多种解决方案。
公众号:金融级分布式架构(Antfin_SOFA)