Skip to main content

分布式事务

方案

  • XA(两段式提交)
  • TCC
  • 本地消息表
  • 可靠消息最终一致性方案
  • 最大努力通知方案

比较

两段式提交

适合单块应用里,跨多个库的分布式事务,严重依赖数据库,效率很低

不适合高并发

TCC

适合严格保证分布式事务,但需要手写回滚逻辑,业务难以维护。

本地消息表

严重依赖数据库的消息表管理事务,不适合高并发,难以拓展。

可靠消息最终一致性

借助MQ的消息事务

最大努力通知

通信使用MQ,借助最大努力通知服务记录事务并协调事务

详细方案

Try ,Confirm,Cancel

try阶段:这个阶段指的是对各个服务的资源检测以及对资源进行锁定或者预留。

confirm阶段:这个阶段说的是在各个服务中执行的实际操作

cancel阶段:如果任何一个服务的业务方法执行出错,那么这些就需要进行补偿,执行回滚操作

适用于严格事务的场景,并且最好是各个业务的执行时间较短。

一般不这么搞,需要自己手写回滚/补偿逻辑,难以维护业务代码。

可靠消息最终一致性

基于MQ实现事务,比如RocketMQ就可以支持消息事务。

  1. A系统先发送prepared消息到MQ,如果这个消息发送失败就直接取消操作
  2. 如果消息发送成功了,就执行本地事务,如果成功就告诉mq发送确认消息,如果失败就发送回滚消息
  3. 如果发送了确认消息,B系统会接收到确认消息,然后执行本地事务。
  4. MQ会定时轮询所有的prepared消息回调接口,请求没发送确认消息的本地事务处理状态(成功/失败),是继续重试还是回滚,一般来说,可以查看之前的本地事务是否执行,如果已经回滚了,那么就告知回滚。这个是避免本地事务执行成功了,而确认消息发送失败了。
  5. B系统事务失败,尝试重试,到达阈值后就想办法通知A回滚,或者人工介入。

这种方式适用大多场景,思路是这个样子。

最大努力通知方案

  1. 系统A本地事务执行完之后,发送消息到MQ
  2. 最大努力通知服务消费MQ消息,把操作记下来,放到数据库/内存队列,接着调用B系统
  3. B系统如果执行成功就ok,否则 最大努力通知服务就定时尝试重新调用系统B,到达阈值后就放弃。

ref: http://icyfenix.cn/architect-perspective/general-architecture/transaction/distributed.html