zoukankan      html  css  js  c++  java
  • 微服务间保持事务一致性

    问题:

    有一个请求去调用了服务A,A中需要向数据库写入数据,其中A里面又调用了服务B,B中也向服务器写入了一些数据,当A成功调用B之后,B正常执行了,A的操作发生了异常,A操作的数据可以正常回滚,那么问题是B服务的事务如何与A保持一致呢?

    解决方案:

    服务A与服务B属于不同的应用,通过dubbo远程调用,要做到二者写库操作一同提交/一同回滚,服务A和服务B必须参与同一个跨应用的全局事务,并保证二者对应的DB事务必须作为该全局事务的分支事务。这样,事务管理模块在明确了该全局事务的完成方向(commit/rollback)后,再将该全局事务下的所有分支事务逐个提交/回滚。

    这是分布式事务管理的大致逻辑,其中,上述“将所有分支事务逐个提交/回滚”过程是分布式事务处理的关键,需要有相应故障恢复的机制,例如,当服务A的DB事务已经提交(服务B的DB事务尚未提交)时,若服务B所在节点宕机(或其使用的DB宕机)时,如何保证服务B的DB事务仍能正常提交。这个过程的实现机制有很多种,常见的有XA 2PC和TCC。

    XA机制将提交过程分成prepare、commit两个阶段,事务管理模块在prepare服务A的DB事务、服务B的DB事务都成功后,再逐个commit这些DB事务。DB在prepare返回OK后,如果没有收到来自事务管理模块的commit/rollback请求则会一直保留该分支事务的数据。因此,若上述宕机故障出现在prepare阶段,则可以通过将prepare过的分支事务回滚,来达到全局事务回滚;若上述宕机故障出现在commit阶段,后续仍然可以再次commit那些未成功commit的分支事务,最终达到全局事务提交。

    TCC机制下,事务管理模块是在服务A、服务B执行完毕后即刻提交其参与的DB事务。而后,如果全局事务决定提交,则逐个调用服务A和服务B的confirm逻辑;如果全局事务决定回滚,则逐个调用服务A和服务B的cancel逻辑(当然,confirm/cancel逻辑的执行中又会参与相应的DB事务)。若发生上述宕机故障,则只需要根据全局事务当前状态,将服务A、服务B相应的confirm/cancel逻辑重新调用即可。因confirm/cancel逻辑可能会被多次调用,因此,需要保证其幂等性。

    知名的分布式事务管理器主要有atomikos、bitronix、narayana。其中,仅atomikos支持XA和TCC两种机制,bitronix、narayana仅支持XA机制。这三者都不提供对dubbo的开箱即用的支持,需要自行集成。

    目前对dubbo提供开箱即用支持的分布式事务管理器有:ByteJTA(基于XA机制)、ByteTCC(基于TCC机制)。

    目前比较多的解决方案有几个:
    一、结合MQ消息中间件实现的可靠消息最终一致性
    二、TCC补偿性事务解决方案
    三、最大努力通知型方案
    第一种方案:可靠消息最终一致性,需要业务系统结合MQ消息中间件实现,在实现过程中需要保证消息的成功发送及成功消费。即需要通过业务系统控制MQ的消息状态
    第二种方案:TCC补偿性,分为三个阶段TRYING-CONFIRMING-CANCELING。每个阶段做不同的处理。
    TRYING阶段主要是对业务系统进行检测及资源预留
    CONFIRMING阶段是做业务提交,通过TRYING阶段执行成功后,再执行该阶段。默认如果TRYING阶段执行成功,CONFIRMING就一定能成功。
    CANCELING阶段是回对业务做回滚,在TRYING阶段中,如果存在分支事务TRYING失败,则需要调用CANCELING将已预留的资源进行释放。
    第三种方案:最大努力通知xing型,这种方案主要用在与第三方系统通讯时,比如:调用微信或支付宝支付后的支付结果通知。这种方案也是结合MQ进行实现,例如:通过MQ发送http请求,设置最大通知次数。达到通知次数后即不再通知。
    具体的案例你也可以参考下龙果学院这篇博客,它上面有完整的电商系统分布式事务实现案例:龙果社区-微服务架构的分布式事务解决方案
     
    其他解决方案:

           首先,要明确 需不需要保证数据的一致性,有些业务场景 就不需要一致性。

    而你的既然需要,回滚机制,让对方的服务提供回滚接口,调用方假设调用接口出错,本地的东西 通过本地事物 能回滚,而外部系统 你catch了这个Exception,则要调用它的回滚接口。

  • 相关阅读:
    eval()函数的使用
    Ajax的GET,POST方法传输数据和接收返回数据
    使用目录
    安装目录
    c 文件输入和输出
    【C++王桂林】
    【C++】虚函数表vtable理解
    【C++】内存管理内幕阅读笔记
    git提交中的索引错误问题
    pydicom编辑、删除DICOM文件中病人相关信息
  • 原文地址:https://www.cnblogs.com/barrywxx/p/8506512.html
Copyright © 2011-2022 走看看