共计 3370 个字符,预计需要花费 9 分钟才能阅读完成。
导读:本文就微服务事务一致性问题产生根源、业界常用方案优缺点进行了分析对比,在此基础上提出了用友微服务事务一致性解决方案,详细介绍了用友 CC 事务模型及原理,以及此方案解决的场景。一致性问题的产生在传统巨石应用架构模式下,架构特点主要是 mvc 模式,由 controller 层负责对外提供服务接口,所有功能集中在一个服务实例中,通过增减服务实例来扩展集群的处理能力,但数据持久化集中在一个数据库存储,数据一致性主要依靠传统数据库本地事务机制保证,这种架构模式特点是简单、快捷,方便业务规模不大,业务功能单一的场景,随着业务增长,无论是业务规模还是业务范围都在快速变化,这种巨石架构模式就显得力不从心,不易于开发协调,因此,微服务架构模式应运而生,所谓微服务通俗来说就是对服务进行垂直拆分,将一个整体服务拆分成功能相对独立的单元服务,各单元服务之间通过 rpc 进行同步或异步调用。微服务架构模式下各个服务单元各自有独立的数据持久层,一个业务请求需要多个微服务单元共同协作,要求各服务单元要么同时成功或同时失败,但微服务实例分别部署在不同的进程或主机节点上,每个服务实例的状态、网络等情况是不可预知的,因此,如何保证一个业务请求中各单元服务数据保持一致性成为微服务架构中一个关键的问题。常见解决方案两阶段提交两阶段提交属于刚性事务,两阶段分为准备阶段和提交阶段,在准备阶段,由事务协调器向各个参与者发送 Prepare 消息,参与者收到消息后,要么返回失败,要么执行本地事务,并写本地 redo 和 undo 日志,但是并不 commit 事务,此时,本地事务资源是被锁定状态,其它服务或应用是不能使用此资源的。在提交阶段,事务协调者在接收到所有参与者事务消息通知之后,根据所有参与者提交阶段返回的状态确定在提交阶段是回滚还是提交事务,只要有一个参与者超时或者失败,协调者就向所有参与者发送回滚请求,否则就向参与者发送提交请求。二阶段提交的优点 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=’ 异常时补偿事务方法 ’)标识此方法纳入事务管理,同时,补偿方法上加入 @CCTransCancel3)异步消息补偿机制。事务补偿机制通过 EOS 可靠消息投递,减少事务补偿回调对业务系统性能的影响 CC 事务模型缺点 1)该事务模型与自研 rpc 框架 iris 绑定,不支持其它 rpc 框架 2)没有 Try 阶段锁定资源,一进入事务本地事务就已实际提交,不具备事务隔离能力,业务需要考虑如何实现 Cancel 才能符合业务实际回滚需求。