微服务分布式事务的实现方法及替代方案

微服务–分布式事务的实现方法及替代方案

这两天正在研究微服务架构中分布式事务的处理方案, 作一个小小的总结, 做为备忘. 若有错误, 欢迎指正!算法

概念澄清

  • 事务补偿机制: 在事务链中的任何一个正向事务操做, 都必须存在一个彻底符合回滚规则的可逆事务.
  • CAP理论: CAP(Consistency, Availability, Partition Tolerance), 阐述了一个分布式系统的三个主要方面, 只能同时择其二进行实现. 常见的有CP系统, AP系统.
  • 幂等性: 简单的说, 业务操做支持重试, 不会产生不利影响. 常见的实现方式: 为消息额外增长惟一ID.
  • BASE(Basically avaliable, soft state, eventually consistent): 是分布式事务实现的一种理论标准.

柔性事务 vs. 刚性事务

刚性事务是指严格遵循ACID原则的事务, 例如单机环境下的数据库事务.数据库

柔性事务是指遵循BASE理论的事务, 一般用在分布式环境中, 常见的实现方式有: 两阶段提交(2PC), TCC补偿型提交, 基于消息的异步确保型, 最大努力通知型.安全

一般对本地事务采用刚性事务, 分布式事务使用柔性事务.架构

先上结论, 再分别介绍分布式事务的各类实现方式.异步

  • 若是业务场景须要强一致性, 那么尽可能避免将它们放在不一样服务中, 也就是尽可能使用本地事务, 避免使用强一致性的分布式事务.
  • 若是业务场景可以接受最终一致性, 那么最好是使用基于消息的最终一致性的方案(异步确保型)来解决.
  • 若是业务场景须要强一致性, 而且只可以进行分布式服务部署, 那么最好是使用TCC方案而不是2PC方案来解决.

注意: 如下每种方案都有不一样的适用场合, 须要根据实际业务场景来选择.分布式

 

1、最佳实践型

    尽可能避免将一个事务放在不一样服务中, 也就是尽可能使用本地事务, 避免使用强一致性的分布式事务,每一个微服务理论上只返回结果,这是最优方法。固然避免不了出现事务在不一样的微服务中,请使用下面方法。微服务

2、两阶段提交(2PC)

两阶段提交(Two Phase Commit, 2PC), 具备强一致性, 是CP系统的一种典型实现.性能

两阶段提交, 常见的标准是XA, JTA等. 例如Oracle的数据库支持XA.ui

下图是两阶段提交的示意图:spa

2pc

图的上半是两阶段提交成功的演示, 下半是两阶段提交失败的演示. 关于两阶段提交网上有不少经典的讲解, 这里就不细说了, 能够参考前面的连接.

缺点

  • 两阶段提交中的第二阶段, 协调者须要等待全部参与者发出yes请求, 或者一个参与者发出no请求后, 才能执行提交或者中断操做. 这会形成长时间同时锁住多个资源, 形成性能瓶颈, 若是参与者有一个耗时长的操做, 性能损耗会更明显.
  • 实现复杂, 不利于系统的扩展, 不推荐.

3、补偿性的TCC (Try-Confirm-Cancle)类型

TCC, 是基于补偿型事务的AP系统的一种实现, 具备最终一致性.

TCC流程

下面以客户购买商品时的付款操做为例进行讲解:

  • Try: 
    完成全部的业务检查(一致性),预留必须业务资源(准隔离性); 
    体如今本例中, 就是确认客户帐户余额足够支付(一致性), 锁住客户帐户, 商户帐户(准隔离性).
  • Confirm: 
    使用Try阶段预留的业务资源执行业务(业务操做必须是幂等的), 若是执行出现异常, 要进行重试. 
    在这里就是执行客户帐户扣款, 商户帐户入帐操做.
  • Cancle: 
    释放Try阶段预留的业务资源, 在这里就是释放客户帐户和商户帐户的锁; 
    若是任一子业务在Confirm阶段有操做没法执行成功, 会形成对业务活动管理器的响应超时, 此时要对其余业务执行补偿性事务. 若是补偿操做执行也出现异常, 必须进行重试, 若实在没法执行成功, 则事务管理器必须可以感知到失败的操做, 进行log(用于过后人工进行补偿性事务操做或者交由中间件接管在以后进行补偿性事务操做).

优势

对比与前面提到的两阶段提交法, 有两大优点:

  • TCC可以对分布式事务中的各个资源进行分别锁定, 分别提交与释放, 例如, 假设有AB两个操做, 假设A操做耗时短, 那么A就能较快的完成自身的try-confirm-cancel流程, 释放资源. 无需等待B操做. 若是过后出现问题, 追加执行补偿性事务便可.
  • TCC是绑定在各个子业务上的(除了cancle中的全局回滚操做), 也就是各服务之间能够在必定程度上”异步并行”执行.

注意事项

  • 事务管理器(协调器)这个节点必须以带同步复制语义的高可用集群(HAC)方式部署.
  • 事务管理器(协调器)还须要使用多数派算法来避免集群发生脑裂问题.

适用场景

  • 严格一致性
  • 执行时间短
  • 实时性要求高

举例: 红包, 收付款业务.

4、异步确保型(消息事务+最终一致性)

经过将一系列同步的事务操做变为基于消息执行的异步操做, 避免了分布式事务中的同步阻塞操做的影响.

这个方案真正实现了两个服务的解耦, 解耦的关键就是异步消息和补偿性事务.

这里以一个例子做为讲解:

异步确保型

执行步骤以下:

  1. MQ发送方发送远程事务消息到MQ Server;
  2. MQ Server给予响应, 代表事务消息已成功到达MQ Server.
  3. MQ发送方Commit本地事务.
  4. 若本地事务Commit成功, 则通知MQ Server容许对应事务消息被消费; 若本地事务失败, 则通知MQ Server对应事务消息应被丢弃.
  5. 若MQ发送方超时未对MQ Server做出本地事务执行状态的反馈, 那么须要MQ Servfer向MQ发送方主动回查事务状态, 以决定事务消息是否能被消费.
  6. 当得知本地事务执行成功时, MQ Server容许MQ订阅方消费本条事务消息.

须要额外说明的一点, 就是事务消息投递到MQ订阅方后, 并不必定可以成功执行. 须要MQ订阅方主动给予消费反馈(ack)

  • 若是MQ订阅方执行远程事务成功, 则给予消费成功的ack, 那么MQ Server能够安全将事务消息移除;
  • 若是执行失败, MQ Server须要对消息从新投递, 直至消费成功.

注意事项

  • 消息中间件在系统中扮演一个重要的角色, 全部的事务消息都须要经过它来传达, 因此消息中间件也须要支持 HAC 来确保事务消息不丢失.
  • 根据业务逻辑的具体实现不一样,还可能须要对消息中间件增长消息不重复, 不乱序等其它要求.

适用场景

  • 执行周期较长
  • 实时性要求不高

例如:

  • 跨行转帐/汇款业务(两个服务分别在不一样的银行中)
  • 退货/退款业务
  • 财务, 帐单统计业务(先发送到消息中间件, 而后进行批量记帐)

5、最大努力通知型

这是分布式事务中要求最低的一种, 也能够经过消息中间件实现, 与前面异步确保型操做不一样的一点是, 在消息由MQ Server投递到消费者以后, 容许在达到最大重试次数以后正常结束事务.

适用场景

交易结果消息的通知等.

小结

不论是同步事务中的事务管理器(协调者), 仍是异步事务中使用的消息中间件,若要达到一致性保证,都须要使用带有同步复制语义的 HAC 提供的高可用和高可靠特性,这些都是以性能为代价的,无疑成为了SOA 架构中的典型性能瓶颈之一.

相关文章
相关标签/搜索