分布式系统漫谈【拾】_分布式事务一致性:阿里方案

 

上篇文章:分布式系统漫谈【玖】_分布式事务一致性:协议支持

 

其实对于生产环境的分布式事务一致,各大互联网公司都是自己实现的解决方案,总结起来无非是异步补偿实时查询定期校对几种模式,大部分场景都是使用到消息中间件。下面介绍下阿里对分布式事务一致的解决方案,内容总结自钟华老师的《企业IT架构转型之道 阿里巴巴中台战略思想与架构实战》,严重安利这本书,任何想向架构方向发展的同学,此书不可不读。购书链接如下:

 

分布式系统漫谈【拾】_分布式事务一致性:阿里方案_第1张图片

 

 

柔性事务

 

阿里提出了柔性事务的概念。柔性事务的思想就是,尽量在处理分布式事务的时候不引入锁而增加时间开销(对比两阶段提交协议),也不要增加其他额外的时间延迟(Paxos协议需要多台机器确认议案)。考虑通过补偿、异步和乐观锁等方式,来实现事务的最终一致性。

 

补偿

柔性事务的补偿机制主要由日志保证。事务日志记录事务的开始、结束状态,可能还包括事务参与者信息。参与者节点也需要根据重做或回滚记录redo/undo日志,当事务重试或回滚时,可以根据这些日志最终将数据恢复到一致状态。

 

异步

由于引入了异步操作,因此需要消息中间件保证可靠的消息传递:事务消息至少投递一次,可能投递多次。这还要求消息处理程序必须实现幂等。幂等就是对于同一操作反复执行多次,响应或计算的结果不变。

 

乐观锁

可以避免长事务中的数据库加锁开销,大大提升了高并发量下的系统整体性能。其实乐观锁的实现,就是类似之前在多线程系列文章中讲的cas操作,对需要并发更新的数据增加版本号的记录,每次去更新的时候先进行版本号的比对,版本号一致才进行更新操作。

 

下面介绍一下阿里的关于分布式事务一致性的三种解决方案:

 

消息分布式事务

 

顾名思义,就是基于消息中间件MQ事务消息功能特性,达到分布式事务的最终一致。整体流程可以简单描述如下:

 

假设有A、B两个系统需要进行两个事务的操作。首先A系统发送一条事务消息到消息中间件的某个频道上,B系统订阅了该频道。但此时B系统无法扫描到该条消息,因为事务消息特殊定制了一个状态(类似于初始、正常等),只有某种状态的消息才可以被正常扫描。当A系统成功将事务消息发送到消息中间件后,就回头执行自己的事务操作,此时有两种可能,分别为成功和失败。

 

如果成功,则向消息中间件发送请求将之前的事务消息状态更改为正常,这样B系统就可以扫描并获取到该条消息,并开始执行自己的本地事务操作。如果成功,则实现了此次两个数据库上的事务同时成功;如果失败,则通过消息方法发送到消息中间件另一个频道,已订阅该频道的A系统收到该回滚消息后,对自己之前提交的事务操作进行回滚。

 

如果失败,则不进行任何操作。消息中间件上有自我扫描机制,会定期扫描缓存在本地的事务消息,如果发现某条事务消息超过指定时间仍为初始状态,则发送消息回查A系统该消息对应的事务是否成功提交,如果已提交则更新消息状态为正常,投递到B系统;如果没有成功提交,则清理掉此事务消息。

 

从上面的流程可以看出,通过消息进行事务异步的方式避免了传统两阶段提交事务方式对数据长时间的资源锁定,所以数据库整体的吞吐率和性能大大超过传统的两阶段提交方式。

从本质上来说,对比柔性事务解决分布式事务的思路,消息服务在其中扮演了事务日志的职能,对全局事务有一个统一的记录和调度能力;事务的参与者通过对消息订阅关系建立了事务间的关联。在采用消息服务实现分布式事务的场景如果出现异常时,一般会采用正向补偿的方式,即不会像传统事务方式出现异常时依次进行回滚,会通过消息的不断重试或人工干预的方式让该事务链路继续朝前执行,而避免出现事务回滚。


支付宝XTS框架

 

支付宝开发了XTS分布式事务框架,是一套基于BASE思想实现的一套类似2阶段提交的分布式事务方案。

 

XTS是TCC(Try/Confirm/Cancel,预占/确认/取消)型事务,典型的补偿型事务实现。上文已经介绍过,TCC协议包括如下三个阶段:

try阶段:主要是对业务系统做检测及资源预留;

confirm阶段:主要是对业务系统做确认提交,try阶段执行成功并开始执行confirm阶段时,默认confirm阶段是不会出错的。也就是说,只要try成功,confirm一定成功。

cancel阶段:主要是在业务执行错误需要回滚的状态下,执行业务取消,预留资源释放。

 

XTS框架引入了主事务管理器和分支事务管理器两个角色。其中,主事务管理器用于生成全局事务id,而分支事务管理器用于和各业务系统交互记录各子事务提交情况。XTS框架整体运转流程如下:

 

业务系统先提交事务给主业务管理器,拿到全局事务编号txId。之后带上txId再去调用其他参与事务的业务系统,这个txId在整个分布式事务的声明周期中用于建立主事务和分支事务之前的对应关系。参与事务的业务系统接收到请求后,最好必要的准备工作后将内容记录到分支事务管理器。

 

进入事务提交阶段后,业务系统向主事务系统提交事务,主事务系统先完成本地事务的提交,后发送请求给分支事务管理器确认分支事务,分支事务管理器再去调用各业务系统执行事务操作并等待返回结果发送给主事务管理器。如果分支事务全部成功,则该分布式事务成功执行;如果失败,则进入回滚流程:主事务管理器线回滚本地事务,再依次去取消分支事务。

 

这里有一个地方需要注意:该框架的事务回滚和补偿机制需要开发人员自行实现,这对于开发工作增添了额外的负担。为了减消这个负担,阿里开发了TXC事务平台:

 

 

分布式事务平台TXC

 

 

TXC也是阿里基于两阶段提交理论实现的分布式事务框架,支持分布式数据库事务、多库事务、消息事务、服务链路调用事务及各种其他事务。和支付宝XTS框架相比,主要区别有两个:一是主事务和分支事务都是维护在同一台TXC服务器上的;二是事务回滚或补偿代码不需要开发人员编写,平台支持自动生成。

 

相比于传统的两阶段提交方式,最大的区别在于XA在准备阶段是没有提交本地事务的,而TXC则是立即执行并可见,在隔离性级别上实现的是读未提交(read uncommitted), 所以避免了在分布式事务中对于数据的长时间锁占用。也就是说,Txc在允许数据脏读的业务场景中,能充分发挥性能上的优势。比如商品在大促秒杀场景下,允许商品的库存在事务没有提交前给前端应用提供查询,只不过在最后订单扣减库存时进行控制,避免商品超卖现场的发生。如果业务场景不允许数据的脏读,TXC平台也支持select for update以及提供@hint的功能临时提升事务的隔离级别。

同时TXC服务器端会记录当前处理事务对数据库中进行了修改数据的信息(行信息),当有其他事务也要对这些数据进行修改操作时,TXC服务端会协调两个事务间的执行,避免在第一个事务没有提交前,同样的数据会被另一个事务对数据进行修改。从本质来说,将原来传统事务场景下,由数据库提供的锁机制提升到了Txc服务端进行了实现,这样相比于数据库锁的实现成本更加轻量, Txc本身服务能力的扩展能力,最终在同样实现事务隔离性的前提下,大大提升了整体的数据库处理吞吐率。

 

这里再主要说说TXC如何实现的事务自动回滚。

 

1 )用户在向TXC服务器发起事务请求后,进入到数据库的操作时,会对该分支事务在TXC服务器上进行注册。当资源管理器捕捉到SQL的请求后,会对 SQL语句进行SQL解析,如果是执行Insert/Delete/Update的SQL操作,则会针对该SQL语句构造出对应的SQL查询语句,将当前SQL请求要修改的数据先从数据库中获取,以undo日志的方式保存起来,用于将来回滚;

2 )进行实际的SQL语句的执行,在SQL执行完毕以后,会再次通过查询方式获取到修改后的数据,并保存为redo日志,用于业务回滚前脏数据的校验。

3 )当SQL的执行和undo/redo日志作为一个本地事务提交给数据库的同时,也会更新分支事务状态。当整个事务成功提交后,则会删除undo/redo曰志。

当出现事务回滚时,会按以下顺序进行数据的恢复和操作。首先对比当数据库中数据值与之前保存的redo日志中被修改的值是否一致,如果一致则根据undo曰志生成回滚用的undo SQL并执行,恢复数据到执行事务前的状态;如果当前数据库中的数据与redo日志中的值不一致,则说明是该分布式事 务在第一阶段修改了数据后,又被其他线程(可能是通过非TXC事务控制的数据访问渠道)修改了该数据,这样就不能再继续进行数据的自动回滚,否则会出现业务不一致的情况,回滚会抛出异常,由TXC Server发出告警,引入人工干预。

 

分布式系统漫谈【壹】_发展历程

分布式系统漫谈【贰】_分布式系统带来的问题

分布式系统漫谈【叁】_负载层技术:Nginx

分布式系统漫谈【肆】_负载层技术:CDN

分布式系统漫谈【伍】_远程调用

分布式系统漫谈【陆】_SOA和微服务

分布式系统漫谈【柒】_微服务的挑战和解决方案

分布式系统漫谈【捌】_分布式事务一致性:理论基础

分布式系统漫谈【玖】_分布式事务一致性:协议支持

分布式系统漫谈【拾】_分布式事务一致性:阿里方案

分布式系统漫谈【拾壹】_分布式事务一致性:秒杀实现

分布式系统漫谈【拾贰】_分库分表带来的问题和解决方案

分布式系统漫谈【拾叁】_缓存带来的问题和解决方案

你可能感兴趣的:(分布式,从分布式到微服务,分布式系统,事务,阿里,XTS,TXC)