导读:数据库
本文就微服务事务一致性问题产生根源、业界经常使用方案优缺点进行了分析对比,在此基础上提出了用友微服务事务一致性解决方案,详细介绍了用友CC事务模型及原理,以及此方案解决的场景。编程
在传统巨石应用架构模式下,架构特色主要是mvc模式,由controller层负责对外提供服务接口,全部功能集中在一个服务实例中,经过增减服务实例来扩展集群的处理能力,但数据持久化集中在一个数据库存储,数据一致性主要依靠传统数据库本地事务机制保证,这种架构模式特色是简单、快捷,方便业务规模不大,业务功能单一的场景,随着业务增加,不管是业务规模仍是业务范围都在快速变化,这种巨石架构模式就显得力不从心,不易于开发协调,所以,微服务架构模式应运而生,所谓微服务通俗来讲就是对服务进行垂直拆分,将一个总体服务拆分红功能相对独立的单元服务,各单元服务之间经过rpc进行同步或异步调用。微服务架构模式下各个服务单元各自有独立的数据持久层,一个业务请求须要多个微服务单元共同协做,要求各服务单元要么同时成功或同时失败,但微服务实例分别部署在不一样的进程或主机节点上,每一个服务实例的状态、网络等状况是不可预知的,所以,如何保证一个业务请求中各单元服务数据保持一致性成为微服务架构中一个关键的问题。网络
两阶段提交架构
两阶段提交属于刚性事务,两阶段分为准备阶段和提交阶段,在准备阶段,由事务协调器向各个参与者发送Prepare消息,参与者收到消息后,要么返回失败,要么执行本地事务,并写本地redo和undo日志,可是并不commit事务,此时,本地事务资源是被锁定状态,其它服务或应用是不能使用此资源的。在提交阶段,事务协调者在接收到全部参与者事务消息通知以后,根据全部参与者提交阶段返回的状态肯定在提交阶段是回滚仍是提交事务,只要有一个参与者超时或者失败,协调者就向全部参与者发送回滚请求,不然就向参与者发送提交请求。mvc
二阶段提交的优势框架
1)实现了事务的隔离,确保了强一致性,即本地事务未提交的数据对其它事务不可见,事务要么都提交成功要么都失败异步
2)业务编程简单,因为事务管理是由事务协调者及本地事务资源管理器实现,开发者必需要介入太多事务相关的工做分布式
二阶段提交缺点微服务
1)同步阻塞调用,在事务执行过程当中,全部参与者同步锁定资源以实现隔离,被锁定的资源不能被其余事务访问性能
2)须要本地事务支持,即本地数据库须要支持xa协议
3)须要事务协调者,协调者存在单点问题
4)事务会出现没法确认的状态。当协调者发出commit请求后,而后协调者宕机,而参与者可能只有一个已提交,其它参与者还没有提交,此时若是惟一的参与者也宕机,整个事务状态将没法确认
5)主要解决的单JVM跨库的事务一致性
TCC事务
TCC事务即Try-Confirm-cancel三个阶段,是柔性事务的一种,实现的是最终一致性,适合于同步调用过程。TCC是应用层的两阶段提交,不须要事务本地数据库对XA协议的支持。TCC事务模型有三个部分组成
·主业务服务
主业务服务为整个业务活动的发起方,一般是服务聚合应用,好比商城系统的下单系统,下单时须要调用库存系统减库存,支付系统付款及积分系统给用户积分以及购物车系统清理购物车内容。
·从业务服务
从业务服务负责提供TCC业务操做,是整个业务活动的操做方。从业务服务必须实现Try、Confirm和Cancel三个接口,供主业务服务调用。因为Confirm和Cancel操做可能被重复调用,故要求Confirm和Cancel两个接口必须是幂等的。
·业务活动管理器
业务活动管理器管理控制整个业务活动,包括记录维护TCC全局事务的事务状态和每一个从业务服务的子事务状态,并在业务活动提交时确认全部的TCC型操做的confirm操做,在业务活动取消时调用全部TCC型操做的cancel操做。
1)Try:尝试执行业务
完成全部业务检查(一致性)
预留必须业务资源(准隔离性)
2)Confirm:确认执行业务
真正执行业务
不作任何业务检查
只使用Try阶段预留的业务资源
只要Try阶段执行成功,须要确保Confirm必定成功,能够不断重试
3)Cancel:取消执行业务
释放Try阶段预留的业务资源
只要try阶段失败,必须确保Cancel最终必定成功
TCC模式优势
1)解决了跨应用的事务问题
2)把数据库层面的两阶段提交提到应用层来实现,不须要数据库层面来支持XA协议,规避了数据库的XA支持的缺陷
TCC模式缺点
1)须要从业务的角度来设计业务接口,确保业务可分解成Try、Confirm、Cancel三个阶段,增长了业务编程的复杂性
2)因为每一个应用的网络不必定可靠,可能会屡次调用业务接口,须要业务层面考虑幂等性操做
3)因为三个阶段都是同步调用过程,所以随着参与者增多,对主业务响应速度有影响
基于消息队列的最终一致性
基于消息队列的最终一致性考虑的场景是业务之间经过异步调用来实现,即做为服务调用方发起方异步调用以后当即返回,没必要等待被调用服务实际返回结果,这样就能够基于消息队列来实现业务之间的解耦,由各业务来确保最终一致性。
基于消息队列的最终一致性方案的优势
1)各业务之间彻底解耦,单个业务性能不会影响总体服务
2)有助于提高服务的总体性能和吞吐量
3)实现起来简单,只须要参与事务的各方在收到消息后确保本地事务一致性、幂等性
基于消息队列的最终一致性方案的缺点
1)须要业务调用方来确保本地事务和发送消息的原子性,虽然像ActiveMq支持事务消息,可是事务消息对性能影响较大,能够在本地创建消息表的方式来确保本地事务与发送消息同时成功或失败
2)当出现不一致时,须要人工介入处理各个业务的执行状态
用友微服务治理中的事务一致性解决方案综合了TCC与基于消息队列的最终一致性,CC事务模型,即Confirm 和Cancel模型。该模型将分布式事务边界划以异步调用为边界,只要在调用链中加入事务的同步调用,都属于一个全局事务,在这个全局事务中,保证事务的最终一致性,如图:
在此图中一个完整的调用链从A服务开始,在左边方框内是rpc同步调用,而右边也是一个rpc同步调用,两个方框之间的服务C是经过异步调用框架EOS基于可靠消息队列对服务E发起调用,CC事务模型将这次调用当作两个事务处理。
CC事务模型事务状态变化时序图,rpc调用链关系为A->B,B->C,B->D,C->E,时序图以下:
CC事务模型过程,A同步调用B服务,事务框架在A服务内部数据库记录对B的调用上下文及事务记录,事务状态为Confirming状态,同时,rpc框架将事务上下文传递给B,B服务接收到rpc调用请求,B服务记录事务,同时事务为Confirming状态,同理,B调用C,C调用E,B调用D.此时,若是B调用D异常,则B本地事务回滚,同时B服务捕捉到异常后根据B服务记录的调用关系上下文,经过EOS框架向C和D发起异步补偿方法调用,全部方法补偿方法调用成功,则B事务状态为Cancelled,C服务补偿调用成功后继续向E服务发起异步补偿调用。同时,B向A抛出异常,A捕捉异常后执行补偿异步调用,同时本地事务回滚,最终AB事务状态为Cancelled或者Confirming状态,C、D、E已提交事务执行补偿方法后状态为Cancelled.最终,全部的事务状态都会confirmed时,则事务成功,或者全部状态都为Cancelled时,回退成功,若是有节点处于Confirming状态,说明整个事务发生了不一致状态,须要人工介入处理。
CC事务模型优势
1)没有事务管理器的概念,每一个事务节点都是对等的
2)模型简单,代码侵入少,开发者只须要在业务接口上方法上使用@CCTransaction(cancel='异常时补偿事务方法')标识此方法归入事务管理,同时,补偿方法上加入@CCTransCancel
3)异步消息补偿机制。事务补偿机制经过EOS可靠消息投递,减小事务补偿回调对业务系统性能的影响
CC事务模型缺点
1)该事务模型与自研rpc框架iris绑定,不支持其它rpc框架
2)没有Try阶段锁定资源,一进入事务本地事务就已实际提交,不具有事务隔离能力,业务须要考虑如何实现Cancel才能符合业务实际回滚需求。