XA规范

包含角色

  • Application:应用程序
  • TM:Transaction Manager,事务管理器
  • RM:Resource Manager,资源管理器
  • CRM:Communication Resource Manager,通信资源管理器

    XA分布式事务架构

  • XA:接口规范

    • TM和RM通信的规范:怎么提交事务、怎么会滚事务

分布式事务理论 - 图1

2PC理论

  • 基于XA规范落地的分布式事务,定义了更多的细节
  • 两阶段提交

    事务执行流程

    阶段一(prepared)

  • TM接收到应用程序发过来的事务后,将事务中的多个SQL发送给对应RM,即prepared消息

  • RM在此阶段只去执行sql,不提交事务
  • 将执行成功/失败通知给TM

    阶段二(committed)

  • 如果所有的RM都返回成功,则通知RM提交事务

  • 如果有RM返回失败,则通知所欲RM会滚

    使用场景

  • 适合单块系统跨多库的场景

  • 依赖数据库层的事务,效率低

    缺陷

    同步阻塞

  • 在阶段一里执行prepared操作会占用资源,一直到整个分布式事务完成才会释放

  • 如果这个过程中有其他线程访问资源,则会被阻塞

    单点故障

  • TM是单点的,挂掉的话整个分布式事务就挂了

    事务状态丢失

  • 假如把TM做成双机热备,一个挂了,使用另外一个,但新进来的并不知道当前的事务状态,不知道哪个库committed哪个没有

    3PC

    事务执行流程

    阶段一:canCommitted

  • TM发送canCommitted消息给RM,次阶段主要是网络和各数据库状态是否正常

阶段二:preCommitted

  • 同2PC的阶段一
  • 如果一个库收到了preCommitted,则说明其他库也都收到了,这正是因为canCommitted阶段成功了

阶段三:doCommitted

  • 同2PC的阶段二
  • 如果某个库preCommitted响应成功后,超时未收到doCommitted,则也会执行本地committed操作

    缺陷

  • 如果阶段二中一个库资源所动失败,返回失败给TM,则TM会发送abort给所有TM,通知其释放资源

  • 但如果一个TM因为网络原因没有收到abort,则会超时执行本地committed操作,导致数据异常

    TCC

    阶段

    try

    confirm

    cancel

  • 补偿

    问题

  • 强业务相关,要写大量代码

    场景

  • 资金相关的场景等核心场景

  • 短事务场景,因为一个TCC事务中包含了很多同步调用,如果有的调用耗时比较长,则会影响性能

    通用型方案

    分布式事务理论 - 图2

    角色

  • 主业务服务

    • TCC事务的主控服务,负责整个事务的执行、提交、会滚
  • 从业务服务
    • 11.png
    • 提供try(锁定资源)
      • 比如是A用户给B用户转账100,此阶段就先从用户A的账户扣掉100,在一张临时表里插入这100的记录,状态为锁定状态或扣款中
    • confirm(执行业务逻辑)
      • B用户账户加上100,临时表里的100元状态为结束/完成状态
    • cancel(回滚)接口
      • 就A用户账户再加上100元,临时表中的100元记录状态为取消/失败状态
  • 业务管理器

    • 分布式事务状态管理包括主业务服务、从业务服务
    • 负责触法从业务服务的confirm、cancel接口

      流程

  • 主业务服务执行本地事务,但事务未提交

  • 主业务服务相业务管理器,申请创建分布式事务
  • 主业务服务向业务管理器,注册各个从业务服务
  • 主业务服务调用从业务服务的try接口
    • 如果try接口调用失败,主业务服务会滚本地事务
    • 通知主业务管理器调用从业务的cancel接口
  • 主业务服务提交本地事务,接着通知业务管理器调用从业务的confirm接口

    注意事项

  • 要把绝大多数的业务逻辑在 Try 阶段完成,在 Try 阶段做尽可能多的事情;Confirm/Cancel只通过最简单的代码释放冻结资源

  • 空回滚:try阶段可能网络问题失败了,没有执行资源锁定,这时候如果执行cancel接口,要注意不能瞎搞
  • try回滚/confirm回滚:根据当前从业务分布式事务状态,进行对应的回滚
  • 倒置请求(超时处理):如果一个从业务的ty调用超时,结果执行了cancel,但过了一会try请求来了,此时应该不允许处理;confirm超时同理
  • 接口幂等性:try- confirm- cancel接口可能会被重试调用
  • confirm或cancel多次重试失败:需要开发额外的数据完整性校验程序补救;人工补救

    TCC分布式事务框架

  • ByteTCC

  • seata的TCC模式

    异步确保型TCC方案

  • 对上述的通用型方案进行改造

  • 在主业务服务和从业务服务中间,添加一个可靠消息服务

    可靠消息服务

  • try:在本地数据库插入一条消息记录

  • confirm:根据本地记录,调用从业务的接口
  • cancel:删除本地的记录

    优点

  • 相比较通用型技术方案,从业务服务可以少写两个接口

    缺点

  • confirm失败的处理逻辑,会导致数据不一致

    补偿性TCC方案

    从业务接口

  • do接口

    • 从业务本地业务逻辑
  • compensate接口

    • 补偿,进行数据会滚

      seata的TCC模式

  • AT模式的“手动版”

seata_tcc.png

代码实现

  • TM端开启全局事务

    1. @GlobalTransactional
    2. public void sale(){ //商城业务中销售商品方法
    3. orderAction.prepare("张三",30);
    4. storageAction.prepare("可乐",10);
    5. }
  • RM的锁定资源方法上(如上的prepare方法)添加@TwoPhaseBusinessAction注解: @TwoPhaseBusinessAction 注解,声明 prepare 方法执行成功或失败后由哪个方法进行后续的提交或回滚,这个注解有三个参数:

    • name 代表分支事务的注册名称;
    • commitMethod 代表二阶段 TC 发来提交消息时执行哪个方法;
    • rollbackMethod 代表二阶段 TC 发来回滚消息时执行哪个方法。

      public interface OrderAction {
      @TwoPhaseBusinessAction(name="TccOrderAction",commitMethod = "commit" , rollbackMethod = "rollback")
      //prepare对应TCC阶段一,用于锁定资源。
      public boolean prepare(BusinessActionContext actionContext,
                            @BusinessActionContextParameter(paramName = "customer") String customer,
                            @BusinessActionContextParameter(paramName = "amount") float amount
      );
      //提交方法定义
      public boolean commit(BusinessActionContext actionContext);
      //回滚方法定义
      public boolean rollback(BusinessActionContext actionContext);
      }
      
    • BusinessActionContext:TCC事务的上下文对象

    • BusinessActionContextParameter:注解标记的参数会在上下文中传播,即能通过BusinessActionContext对象在commit方法及cancle方法中取到该参数值
      • String orderCode = (String)actionContext.getActionContext(“orderCode”);