分布式事务概论

分布式事务

  在分布式系统中,每个节点都是独立的,当一个请求需要多节点同时修改,本地事务ACID就无法保证数据的保证数据的一致性的,此时就需要分布式事务来分布式系统数据一致性了

1.本地事务和分布式事务介绍

 

  1.1本地事务

  单体服务中的事务称为本地事务,本地事务有4个特征AICD(原子性,持久性,隔离性,一致性)

  • 原子性(Atomicity):原子性即把一个代码单元操作看做成一个整体(事务),要么一起成功,要么一起失败
  • 一致性(Consistency):一个事务的数据一致性状态,变换成另一个一致性状态
  • 隔离性(Isolation):多个事务操作,保证每个事务不被其他事务所破坏,每一个事务都存在一个事务空间的概念,事务相互之间不被干扰。
  • 持久性(Durability):当事务操作提交后,事务数据会持久化.不受服务影响了

 

   单体服务一个事务下当一个操作异常,被事务管理器捕捉到,调用mysql的回滚,就可保证事务数据一致性

  1.2分布式事务

   当单体应用务日益不满足需求,由此扩展成分布式系统时,多节点应用的本地事务无法保证数据的一致性,由此就需要分布式事务 

   分布式事务处理方案具体可以归结为两大类,最终一致性和强一致性

   

   当服务A区调用服务B进行修改,无异常,事务提交,服务A在调用服务C进行修改,却异常,事务回滚,因为服务的独立性无法传播给服务B,就产生了脏数据了

  

2.强一致性,弱一致性,最终一致性

  2.1强一致性:

  强一致性指主节点收到数据变更后,在同步给其他副节点,当副节点数据也变更完成后,主节点在返回执行成功(提交事务),其他事务才能操作

  当A服务成功,B服务失败,则A服务也会失败(回滚A服务事务),A和B服务都成功才会提交事务

  优点:

    保证数据实时的一致性

  缺点:

    可用性差,副节点因为异常情况没有返回ACK,给主节点,主节点不会返回结果(提交事务)

    保证数据的绝对一致性是优点也是缺点,缺点则是性能并不是很好

 

  2.2:弱一致性

   当在主节点写入数据a后,其他从节点读取数据a可能读不出来,也有可能读取出来,也不能保证从节点多长时间之后,数据就变得一致  

   能容忍部分节点或全部接节点都看不到最新数据

 

  3.3.最终一致性

  最终一致性指的是,同一时间多节点服务对数据的操作,允许有节点可以失败,可以通过消息的补偿,分布式事务本地化,重试,定时器实现对分布式事务的最终一致

  当A服务成功,B服务失败,A服务可直接提交事务,B服务失败,通过消息的补偿,分布式事务本地化,重试,定时器,人工来让A服务的数据事务实现最终一致

  优点:

    对比强一致性,性能较高

    可预测控制事务最终一致性处理的时间

  缺点:

    需要写很多代码去处理事务(很重)   

  弱一致性和最终一致性是相似的,处理方式不一样,最终一致性是能知道最终数据一致性的时间

 

3.分布式事务协议方案

  1.XA事务协议

    由X/Open组织定义了分布式事务的模型,目的是允许多个资源(如数据库,应用服务器,消息队列,等等)在同一事务中访问,这样可以使ACID属性跨越应用程序而保持有效,定义了如下几个角色:

    AP(Application):应用程序 说白了就是我们的系统,负责开启事务

    TM (ransaction Manager):事务管理器,定义全局事务开启范围,开启全局事务,提交和回滚事务
    RM(Resource Manager):资源管理器 数据库(比如MySQL)

    基于XA协议实现分布式事务对业务侵入很小,都是由数据库厂商集成处理,XA可以使分布式事务像使用本地事务一样使用,XA协议能够严格保障事务ACID的特性

 

    

    1.1:两阶段提交(2pc)

      两阶段提交协议(Two Phase Commitment Protocol)中,基于数据库XA协议(mysql5.0.3支持此协议,InnoDB),特点是对代码无侵害,缺点数据库必须支持XA协议,且XA协议自身的特点,会对事物资源照长时间不释放(同步堵塞),锁定周期比较长,其他事务必须等待释放资源,才能操作数据,因此它的性能很差属于分布式事务强一致类型

  2PC具体是指两阶段提交, prepare准备提交为一阶段,submit 提交为二阶段(成功和回滚)

      两阶段

      (1):阶段一(prepare)

        由事务管理器定义事务范围,开启多少个事务分支(RM),当业务SQL执行完毕后,事务管理器发送准备提交命令给资源管理器(RM)

        

 

 

 

 

       (2)阶段(Commit):

         二阶段为Commit最终提交,commit提交和rollback回滚提交两种方式,选择那种方式提交,是由TM告诉RM是提交还是回滚,TM根据一阶段prepare的ACK机制知道哪些RM失败或成功

        ,全部成功commit,有异常RM(分支)则全局事务回滚

          二阶段成功:

             当全局事务下的资源管理器返回都是成功,则可提交事务

         二阶段失败:

             有RM告知TM自己无法提交,则通过TM向全部的RM发送事务回滚的请求

          

 

 

 

 

         两阶段前事务已经开启,业务SQL也已经执行完毕了,只不过事务还未提交

 

      2PC的优点:对代码入侵较少,可以先开发业务代码,不关注分布式事务,后期可以集成进去,不需要改动太多代码

      2PC的缺点:

          1.同步堵塞:事务强一致性,分支事务的资源都会被锁定,只有提交全局事务后其他事务才能抢到资源

           2.单点问题: 事务管理器在二阶段提交时,如有资源管理器无法响应,整个全局事务都将无法进行进行下去,且资源都会被锁定
          3.数据不一致:事务管理器发送commit请求给资源管理器时,资源管理器突然岩机,网络问题,无法正常接收提交请求,会导致数据不一致
 
 
    1.2:三阶段提交(3PC)
    由于2PC存在的一些问题,如单点故障,commit超时,容错机制,从而产生3PC(三阶段提交),引入了超时机制
    三阶段将2PC的一阶段准备提交,插入了一个preCommit阶段,使得原先在二阶段提交中,参与者(RM)在准备提交之后,由于协调者(TM)发生崩溃或岩机,从而导致参与者(RM)处于无法知晓提交或者回滚的状态中,所以可能产生长时间的延时
 
      
 
     

 

 

    优点:减小了参与者阻塞的范围;出现单点问题后,仍然可以提交

    缺点:数据不一致


 

 

  2.TCC方案

  TCC三段式提交(Try-confirm-Cancel),又称为补偿事务,实现事务的最终一致性,类似于2PC解决方案,只不过TCC是基于应用层实现,事务控制交由业务实现,业务中的子模块都需要使用Try,Confirm,Cancel三个接口, 使用缺点业务会变得非常臃肿,维护成本高,但是TCC让应用程序自己定义数据库的粒度,使降低锁冲突,提高性能

  T(Try):完成业务方面的检查,预留相关的资源,是否能成功
  C(Confirm):try成功预占资源,释放预留资源
  C(Cancel):try预占资源执行失败,释放Try阶段资源

     Try,Confirm,Cancel 可以理解为 SQL 事务中的 Lock、Commit、Rollback。

   使用TCC相当于一个接口需要拆分成三个接口try,confirm,Cancel来保证数据一致性,三个接口具体实现由自己定义

 

  下面三阶段以电商下单为例进行方案解析,这里把整个过程简单分为扣减库存,订单创建 2 个步骤,库存服务和订单服务分别在不同的服务器节点上

    1.try阶段

    try是TCC的中心,confirm,Cancel都是根据try执行结果来执行

    try阶段里面主要也是代码逻辑扣减库存和订单创建,乍一看,这不是和原来单个接口实现一样的吗,NO,其实不是这样的,在try里面引入了冻结和状态的概念

    在try实现的思想就是预留相关资源,怎么预留,就得有冻结和状态的概念,把扣减的库存的先冻结,订单的状态变为变为待确认

    

     可能有人会问了,我在try里面不做事务的提交,只做校验,confirm阶段做事务的提交可以吗.答案显然是不行的,在高并发下无法保证事务占的资源不被抢占

  2.Confirm / Cancel 阶段
  
  根据 服务try阶段是否全部成功或者有预留资源失败,去执行Confirm 阶段和Cancel 阶段,这两个阶段可以算事务的提交和回滚
 
    confirm
    事务try全部预留资源成功后,由confirm来最终提交,try和confirm组成一个完整业务流程,把库存冻结数减去,订单状态改成成功,是否预留资源
 
  

 

 

     Cancel

     有服务try失败,cance提交把冻结库存资源,创建订单数据回滚,释放资源

  

  try能的成功或失败能,下一阶段有confirm和Cancel,但是如果confirm和cancel里失败了呢,confirm个cancel则会一直重试(补偿 ),在重试时如果没做幂等,就会产生脏数据

  TCC的优缺点

    缺点:

      使用TTC方案的接口,都要一分为三,需要写大量的业务代码保证事务最终一致性,耦合度较大

    优点:

      性能较好:事务颗粒度小,各个服务事务都是自己控制,不会同时锁住订单资源和库存资源

      可靠性:解决了XA协议的单点故障,单点故障了只是延缓了最终事务一致性的时间

        数据最终一致:confirm和Cancel以补偿形式处理数据

 

  3.本地消息表

  本地消息表即把分布式事务拆分本地事务进行处理,通过消息补偿机制实现,分布式事务的最终一致,拆分本地事务需要在服务中加入一个本地消息表,用来记录本地事务的状态

    本地消息表的状态维护通过消息中间件和定时器,息中间件通知下级服务执行业务(子事务),定时器轮询本地消息表处理未完成消息(无法成功的消息,消息中间件消息丢失)

 

  本地消息表的流程用下单和扣库存流程讲解

  1.用户生成订单请求进入到订单服务,订单服务生成一个准备中状态的订单,并且生成记录在本地事务表里

  2.通过消息中间件发送消息给下游服务库存服务

  3.库存覅我处理订单的消息开始扣库存

  4.库存服务处理成功,发送消息通知,单服务,订单服务把订单数据状态改为成功,消息本地表的数据也更新

  5.库存服务处理失败,发送消息通知订单服务,单服务把订单数据状态改为失败,消息本地表的数据也更新,也可删除数据

  6.库存服务岩机异常,消息中间件会投递给正常库存服务器,如果都岩机了,会等待服务器恢复正常,消息中间件可以在投递,也避免单价故障问题

  7.轮询本地消息表,把未完成消息处理了, 可以重试,手动处理,消息设置为失败

   本地消息表优缺点:

    优点:

      实现逻辑简单,事务颗粒度小,事务最终一致性性能高

    缺点:

      不可公用:本地消息表的业务代码无法复用,处理不同分布事务都写新业务代码

      高耦合:和业务场景绑定,高耦合

      

 

 

 

 

 

 

 

 

posted @   梨瓜  阅读(123)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
点击右上角即可分享
微信分享提示