您当前的位置:首页 > 电脑百科 > 程序开发 > 框架

微服务架构下分布式事务处理方案选择和对比

时间:2020-08-18 11:55:52  来源:  作者:
微服务架构下分布式事务处理方案选择和对比

 

作者:人月神话,新浪博客同名

简介:多年SOA规划建设,私有云PaaS平台架构设计经验,长期从事一线项目实践

在微服务架构下,我们最容易遇到的一个问题就是分布式事务处理问题,当你微服务模块拆分的越细,那么遇到分布式事务处理的场景就越多。即使是同一个微服务模块,对应一个业务数据库,但是你某个业务逻辑的实现是调用两个Service接口服务来完成的,同样也是分布式事务问题。

因此有必要对分布式事务整体解决思路总下总结。

分布式事务概述

微服务架构下分布式事务处理方案选择和对比

 

分布式事务就是指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于不同的分布式系统的不同节点之上。简单的说,就是一次大的操作由不同的小操作组成,这些小的操作分布在不同的服务器上,且属于不同的应用,分布式事务需要保证这些小操作要么全部成功,要么全部失败。本质上来说,分布式事务就是为了保证不同数据库的数据一致性。

一个分布式事务包含一组操作序列,由两个或两个以上的网络主机参与。通常主机提供事务性资源,而事务管理器负责创建和管理全局事务,由事务管理器协调事务参与的资源。分布式事务和本地事务并无太大不同,也需保证事务的四个属性(原子性、一致性、隔离性、持久性)。

对于分布式事务的潜在场景,可以简单的分为三类:

1.跨资源

一个完整业务需要操作两个独立数据库,比如需要在A数据库插入一条订单记录,同时更新B数据库中的库存状态,两个操作跨数据库,但是需要控制在一个完整事务里面。

2.资源+服务组合

在和工作流集成场景中出现,业务用户在提交单据的时候需要后台执行两个操作,首先是调用本地API将单据数据保存到本地数据库,其次是调用启动流程WebService服务。

3.跨服务

由于Web Service服务本身无状态,即使是同一个数据库提供给处理的两个WebService服务,在进行调用和组合的时候也属于分布式事务控制。

对于分布式事务的主流解决方法,主要包括了XA两阶段提交,事务补偿和基于BASE的最终一致性(可靠消息传输),首先再对这三种方法做下简单描述。

强一致性-两阶段提交模型

 

微服务架构下分布式事务处理方案选择和对比

 

两阶段提交,因为它是实现XA分布式事务的关键(确切地说:两阶段提交主要保证了分布式事务的原子性:即所有结点要么全做要么全不做)。所谓的两个阶段是指:第一阶段:准备阶段和第二阶段:提交阶段。具体过程如下:

阶段一:开始向事务涉及到的全部资源发送提交前信息

 

此时,事务涉及到的资源还有最后一次机会来异常结束事务。如果任意一个资源决定异常结束事务,则整个事务取消,不会进行资源的更新。否则,事务将正常执行,除非发生灾难性的失败。为了防止会发生灾难性的失败,所有资源的更新都会写入到日志中。这些日志是永久性的,因此,这些日志会幸免于难并且在失败之后可以重新对所有资源进行更新。

阶段二:只在阶段一没有异常结束的时候才会发生

 

此时,所有能被定位和单独控制的资源管理器都将开始执行真正的数据更新。事务管理器将基于第一个阶段的投票结果进行决策:提交或取消。当且仅当所有的参与者同意提交事务协调者才通知所有的参与者提交事务,否则协调者将通知所有的参与者取消事务。

从以上工作过程可以看出,两阶段提交协议正确工作的前提假设是每个节点都会记录写前日志(write-ahead log)并持久性存储,即使节点发生故障日志也不会丢失。同时假设节点不会发生永久性故障而且任意两个节点都可以互相通信。

两阶段提交优缺点分析

两阶段提交协议最大的劣势是其通过阻塞完成的协议,在事务参与者等待消息的时候处于阻塞状态,事务参与者中其他进程则需要等待阻塞进程释放资源才能使用。如果事务管理器发生了故障,那么事务参与者将无法完成事务则一直等待下去。同时两阶段提交协议没有容错机制,一个节点发生故障整个事务都要回滚,代价比较大。

两阶段提交协议仅在一种情况下可能导致数据不一致,所有或部分参与者都响应了Prepare阶段,在任何参与者收到事务管理器提交或回滚决定之前事务管理器宕机死亡,此时所有参与者都必须等待事务管理器恢复。而可能事务管理器此时已经丢失了事务上下文,这时需人工介入参与数据恢复。

两阶段提交协议仅仅是提供了分布式事务中的原子性属性,保证一个事务在全局要么全部提交,要么全部回滚,但是在并发控制上(隔离性),仍然需要封锁协议,为了达到分布式环境下全局串行和避免一个事务的失败可能引起一连串事务的回滚,通常使用强两阶段封锁协议(SS2PL)。

两阶段封锁协议并不保证不会发生死锁,数据库系统必须采取其他的措施,预防和解决死锁问题。但常见的数据库系统通常都实现了隔离级别,不同的隔离级别对于不同的锁机制,下表列出他们的对应关系。值得一提的是,两阶段封锁协议并不保证不会发生死锁,数据库系统必须采取其他的措施,预防和解决死锁问题。所以说,如果两阶段提交协议中事务时间越长,那么锁等待的时间和死锁的概率也会变大。

弱一致性-事务补偿模型

微服务架构下分布式事务处理方案选择和对比

 

事务补偿机制是指在事务链中的任何一个正向事务操作,都必须存在一个完全符合回滚规则的可逆事务。例如存款操作通过取款操作来补偿、买入通过卖出来补偿。

工作方式和限制

 

这里的“补偿”与数据库事务中的“回滚”是有区别的,“回滚”是指操作的取消,“回滚”前后对外界来讲,数据是一致的。而“补偿”则是独立的逆向操作,如果事务执行了“补偿操作”,外界可能会看到数据的两种状态。从这个角度讲,“回滚”需要锁定资源。从数据库操作上来“补偿操作”其实也是一次短事务。而“回滚”是一个事务内的操作。

事务补偿通常在实现时采取嵌套事务的方式,即把一个主事务拆分成多个从业务操作,事务的发起和结束由主事务完成。从业务服务提供的业务操作提供补偿操作,补偿操作可以抵销(或部分抵销)正向业务操作的业务结果。业务活动管理器控制业务活动的一致性,它登记业务活动中的操作,并在业务活动取消时调用补偿操作。具体回滚整个事务还是回退到某个事务点,可以依据具体业务来处理。

在上面方式中可以看到需要手工编写大量的代码来处理以保证事务的完整性,我们可以考虑实现一个通用的事务管理器,实现事务链和事务上下文的管理。对于事务链上的任何一个服务正向和逆向操作均在事务管理和协同器上注册,由事务管理器接管所有的事务补偿和回滚操作。

补偿机制能正确工作是基于事务是可以补偿这一前提,如果这一前提无法满足,那么就无法使用这一机制。现实业务场景中,确实存在这样的业务,例如证券交易,因为对时效性特别敏感,不能简单地使用卖出(买入)来补偿买入(卖出),因为不同时间交易的价格可能差距很大。

另外,补偿操作也是一次事务操作,考虑到补偿操作也是有可能失败的,所以,补偿操作应该支持重试,这就要求补偿操作满足幂等性。即重复调用多次产生的业务结果与调用一次产生的业务结果相同。

事务补偿场景举例

在前面已经强调了,对于事务补偿必须满足幂等性要求,而且不能对时效性太敏感。

场景:采购订单在提交时候调用预算检查和扣减,但是如果单据保存失败需要再次调用预算检查和调整,将扣减预算退回。

那么基于以上场景事务补偿的核心实现逻辑如下:

微服务架构下分布式事务处理方案选择和对比

 

  • 正常情况,调用预算扣减服务后,保存采购订单,两者需要同时成功
  • 如果调用采购订单保存服务出现失败,那么就需要对已经扣减的预算进行补偿和返还
  • 即调用和扣减预算完全对等的一个逆向操作,将扣减服务造成的影响全部回退

以上即是对事务补偿机制的关键说明。

BASE最终一致性-可靠消息队列

CAP理论概述

微服务架构下分布式事务处理方案选择和对比

 

由于对系统或者数据进行了拆分,我们的系统不再是单机系统,而是分布式系统,针对分布式系统的CAP原理包含如下三个元素。

  • C:Consistency,一致性。在分布式系统中的所有数据 备份,在同一时刻具有同样的值,所有节点在同一时刻读取的数据都是最新的数据副本。
  • A:Availability,可用性,好的响应性能。完全的可用性指的是在任何故障模型下,服务都会在有限的时间内处理完成并进行响应。
  • P: Partition tolerance,分区容忍性。尽管网络上有部分消息丢失,但系统仍然可继续工作。

CAP原理指的是,这三个要素最多只能同时实现两点,不可能三者兼顾。因此在进行分布式架构设计时,必须做出取舍。而对于分布式数据系统,分区容忍性是基本要求,否则就失去了价值。因此设计分布式数据系统,就是在一致性和可用性之间取一个平衡。

当然,牺牲一致性,并不是完全不管数据的一致性,否则数据是混乱的,那么系统可用性再高分布式再好也没有了价值。牺牲一致性,只是不再要求关系型数据库中的强一致性,而是只要系统能达到最终一致性即可。

从CAP理论到BASE理论

BASE 是 Basically Available(基本可用)、Soft state(软状态)和 Eventually consistent(最终一致性)三个短语的简写,由 eBay 架构师 Dan Pritchett 于 2008 年在《BASE: An Acid Alternative》论文中首次提出。

BASE 思想与 ACID 原理截然不同,它满足 CAP 原理,通过牺牲强一致性获得可用性, 一般应用于服务化系统的应用层或者大数据处理系统中,通过达到最终一致性来尽量满足业务的绝大多数需求。BASE 模型包含如下三个元素:

  • BA:(Basically Available ),基本可用。
  • S:( Soft State),软状态,状态可以在一段时间内不同步。
  • E:(Eventually Consistent ),最终一致,在一定的时间窗口内, 最终达成一致即可。

BASE理论是基于CAP定理演化而来,是对CAP中一致性和可用性权衡的结果。核心思想:即使无法做到强一致性,但每个业务根据自身的特点,采用适当的方式来使系统达到最终一致性。

1、基本可用:指分布式系统在出现故障的时候,允许损失部分可用性,保证核心可用。但不等价于不可用。比如:搜索引擎0.5秒返回查询结果,但由于故障,2秒响应查询结果;网页访问过大时,部分用户提供降级服务,等。

2、软状态:软状态是指允许系统存在中间状态,并且该中间状态不会影响系统整体可用性。即允许系统在不同节点间副本同步的时候存在延时。

3、最终一致性:系统中的所有数据副本经过一定时间后,最终能够达到一致的状态,不需要实时保证系统数据的强一致性。最终一致性是弱一致性的一种特殊情况。

BASE理论面向的是大型高可用可扩展的分布式系统,通过牺牲强一致性来获得可用性。ACID是传统数据库常用的概念设计,追求强一致性模型。

基于可靠消息队列实现最终一致性

微服务架构下分布式事务处理方案选择和对比

 

基于消息的最终一致性是消除了分布式事务,是一种在BASE思想指导下比较好的方案。这种方案实现了两个服务之间的解耦,解耦的关键就是异步消息和消息持久化机制。在两个服务调用之间,会存在一个真空期,这段时间相关数据不一致,而只是在一个事务的中间状态。

事务主动方的业务服务事务提交和消息发送之间必须通过事务同步,可以通过事务管理器进行管理,如两阶段提交。事务主动方在完成事务提交和消息发送之后,它的最终处理结果不再受到事务被动方的影响。即发送到事务被动方的事务要么成功,要么重试。

所以,消息同样需要满足幂等性。实际情况下,消息很难具有幂等性,解决这一问题的方法是使用另一个表记录已经被成功应用的消息,这样就可以通过避免消息多次被应用,从而达到幂等性。

在实际应用中,如果消息接收端的服务出现失败,可能需要人工干预。

场景举例说明

场景:在采购系统中拟制采购订单,在提交单据申请的时候既需要将单据成功保存到本地,同时又需要启动远程流程平台提供的流程启动服务。在该场景中,第二个步骤属于必须要最终完成的操作,同时业务上也允许最终一致(不要因为流程平台本身问题导致单据提交不成功,启流程失败如何重试是系统内部的事情)

对于该场景,基于消息实现最终一致性逻辑如下:

微服务架构下分布式事务处理方案选择和对比

 

三种事务处理方案的比较和选择

对于上面谈到的三种事务处理方案,我们列个表格比较如下:

微服务架构下分布式事务处理方案选择和对比

 

当前主流的方法仍然是事务补偿和BASE最终一致性,同时可以看到,基于消息中间件实现的事务最终一致性由于本身具备高可靠,高性能,并满足大并发的高吞吐量,因此在互联网应用往往采用的更加多。在企业内部的基于SOA服务的分布式事务控制,

微服务架构下分布式事务处理方案选择和对比

 

场景:业务操作需要同时调用 ServiceA-》ServiceB 两个服务,并控制到一个分布式事务里面。

两种方法选择思路为:

If ( 服务A是否可以完整设计出 –A补偿服务)
{
  //-A补偿服务能够保证A服务影响完整回退
  //在调用-A前,A服务调用影响不会波及到后续操作
  if(服务A成功 则 服务B调用必须成功
        and B只要最终成功即可)
  {
       //在服务A成功的情况下服务B不存在因业务逻辑处理和校验导致的不成功。
       Choose 最终一致性方案;(优选方案)
  }
  Else
  {
      Choose 事务补偿方案;
  }
}
Else
{
     Choose 最终一致性方案;
}

整体思路也就是说能够采用最终一致性的地方尽量采用最终一致性来解决问题。

对于不能采用BASE事务最终一致性的地方,特别是在ServiceB在调用的时候存在较多的业务逻辑校验,因此ServiceA即使调用成功也会经常出现由于逻辑校验导致ServiceB调用不成功,那么这种情况下就很难用BASE方案,否则就会导致大量的人工补偿操作和处理。

对于ServiceB的调用如果需求都是最终一致,同时ServiceB的调用不存在由于业务原因导致的调用失败,那么都建议采用BASE事务最终一致性方案。由于BASE方案基于消息中间件来实现,通过消息中间件既可以实现大并发下的吞吐量,同时也可以实现两个服务调用间的彻底解耦。



Tags:微服务架构   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
前言要理解微服务,首先要先理解不是微服务的那些。通常跟微服务相对的是单体应用,即将所有功能都打包成在一个独立单元的应用程序。从单体应用到微服务并不是一蹴而就的,这是一...【详细内容】
2021-07-09  Tags: 微服务架构  点击:(112)  评论:(0)  加入收藏
一、Zuul简介Zuul相当于是第三方调用和服务提供方之间的防护门,其中最大的亮点就是可动态发布过滤器二、Zuul可以为我们提供什么1、权限控制2、预警和监控3、红绿部署、(粘...【详细内容】
2021-04-21  Tags: 微服务架构  点击:(229)  评论:(0)  加入收藏
前不久作为架构师完成了某知名快消企业的一个业务中台建设。系统上线后,经历了双十一活动的流量高峰,整体运行稳定。最近有空,便将此次架构的思路,心得稍作整理在这篇博客中分享...【详细内容】
2021-02-07  Tags: 微服务架构  点击:(181)  评论:(0)  加入收藏
文章简介:作者结合自身微服务架构研发经验进行回顾、总结,本文将介绍微服务架构中,在技术选型时需要注意哪些选型原则,会遇到哪些开源框架,又该如何选择, 进行了全面的归纳、对比,希望能够为大家提供一些思路、方向,少走一些...【详细内容】
2021-02-05  Tags: 微服务架构  点击:(160)  评论:(0)  加入收藏
思维导图 文章已收录Github精选,欢迎Star:https://github.com/yehongzhi/learningSummary一、前言伴随着Eurka2.0版本已停止维护,开始要考虑使用微服务新一代的开源的注册中心...【详细内容】
2020-11-13  Tags: 微服务架构  点击:(159)  评论:(0)  加入收藏
消息总线的定义前面在1.4.2节中强调过,在微服务架构中,经常会使用REST 服务或基于消息的通信机制。在3.6节中也详细介绍了消息通信的实现方式。消息总线就是一种基于消息的通...【详细内容】
2020-09-29  Tags: 微服务架构  点击:(140)  评论:(0)  加入收藏
微服务的高级主题一自动扩展Spring Cloud 提供了大规模部署微服务所必需的支持。为了获得像云服务环境一样的能力, 微服务实例也应该能够根据流量的规模来自动扩展,也称自动缩...【详细内容】
2020-09-23  Tags: 微服务架构  点击:(96)  评论:(0)  加入收藏
Spring Cloud 微服务总体架构图Spring cloud作为当下主流的微服务框架,让我们实现微服务架构简单快捷,Spring cloud中各个组件在微服务架构中扮演的角色如图所示。spring-cl...【详细内容】
2020-09-20  Tags: 微服务架构  点击:(133)  评论:(0)  加入收藏
常见微服务的消费者本节就常见的微服务的消费者进行介绍。在Java领域比较常用的消费者框架主要有HttpClient、Ribbon、Feign 等。 Apache HttpClientApache HttpClient是Apa...【详细内容】
2020-09-11  Tags: 微服务架构  点击:(129)  评论:(0)  加入收藏
什么是微服务模式随着网络基础设施的高速发展,以及越来越多的个体接入互联网,在考虑构建支持海量请求以及多变业务的软件平台时,微服务架构成为多数人的首选。微服务架构的出现...【详细内容】
2020-09-09  Tags: 微服务架构  点击:(95)  评论:(0)  加入收藏
▌简易百科推荐
近日只是为了想尽办法为 Flask 实现 Swagger UI 文档功能,基本上要让 Flask 配合 Flasgger, 所以写了篇 Flask 应用集成 Swagger UI 。然而不断的 Google 过程中偶然间发现了...【详细内容】
2021-12-23  Python阿杰    Tags:FastAPI   点击:(6)  评论:(0)  加入收藏
文章目录1、Quartz1.1 引入依赖<dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz</artifactId> <version>2.3.2</version></dependency>...【详细内容】
2021-12-22  java老人头    Tags:框架   点击:(11)  评论:(0)  加入收藏
今天来梳理下 Spring 的整体脉络啦,为后面的文章做个铺垫~后面几篇文章应该会讲讲这些内容啦 Spring AOP 插件 (了好久都忘了 ) 分享下 4ye 在项目中利用 AOP + MybatisPlus 对...【详细内容】
2021-12-07  Java4ye    Tags:Spring   点击:(14)  评论:(0)  加入收藏
&emsp;前面通过入门案例介绍,我们发现在SpringSecurity中如果我们没有使用自定义的登录界面,那么SpringSecurity会给我们提供一个系统登录界面。但真实项目中我们一般都会使用...【详细内容】
2021-12-06  波哥带你学Java    Tags:SpringSecurity   点击:(18)  评论:(0)  加入收藏
React 简介 React 基本使用<div id="test"></div><script type="text/javascript" src="../js/react.development.js"></script><script type="text/javascript" src="../js...【详细内容】
2021-11-30  清闲的帆船先生    Tags:框架   点击:(19)  评论:(0)  加入收藏
流水线(Pipeline)是把一个重复的过程分解为若干个子过程,使每个子过程与其他子过程并行进行的技术。本文主要介绍了诞生于云原生时代的流水线框架 Argo。 什么是流水线?在计算机...【详细内容】
2021-11-30  叼着猫的鱼    Tags:框架   点击:(21)  评论:(0)  加入收藏
TKinterThinter 是标准的python包,你可以在linx,macos,windows上使用它,你不需要安装它,因为它是python自带的扩展包。 它采用TCL的控制接口,你可以非常方便地写出图形界面,如...【详细内容】
2021-11-30    梦回故里归来  Tags:框架   点击:(26)  评论:(0)  加入收藏
前言项目中的配置文件会有密码的存在,例如数据库的密码、邮箱的密码、FTP的密码等。配置的密码以明文的方式暴露,并不是一种安全的方式,特别是大型项目的生产环境中,因为配置文...【详细内容】
2021-11-17  充满元气的java爱好者  博客园  Tags:SpringBoot   点击:(25)  评论:(0)  加入收藏
一、搭建环境1、创建数据库表和表结构create table account(id INT identity(1,1) primary key,name varchar(20),[money] DECIMAL2、创建maven的工程SSM,在pom.xml文件引入...【详细内容】
2021-11-11  AT小白在线中  搜狐号  Tags:开发框架   点击:(29)  评论:(0)  加入收藏
SpringBoot开发的物联网通信平台系统项目功能模块 功能 说明 MQTT 1.SSL支持 2.集群化部署时暂不支持retain&will类型消 UDP ...【详细内容】
2021-11-05  小程序建站    Tags:SpringBoot   点击:(55)  评论:(0)  加入收藏
最新更新
栏目热门
栏目头条