2PC 3PC TCC等多种分布式事务解决方案分析对比

前言

本文分析多种分布式事务的解决方案2PC、3PC TCC、可靠消息服务、最大努力通知,事务消息等。讲述其执行流程、优缺点、适用场景以及引文具体实战例子。

名词解释

  • TM(transaction manager) 事务协调者
  • RM(resource manager) 资源管理者/事务参与者/业务服务

2PC(Two Phase Commit)

原理

  • 未加入分布式事务时,正常流程是 Client 调用 RM-A 接口开始事务,RM-A 调用 RM-B 后返回结果给 Client。如果 RM-B 异常自己本地事务可以回滚,RM-A 也可以回滚,因为它是调用方,可以捕获到远程调用的异常。
  • 问题在于 RM-A 里在调用 RM-B 之后如果出错了,RM-A 本地事务可以回滚,但是 RM-B 回滚不了,因为对方已经提交。
  • 2PC 加入了事务协调者服务 TM,参与者 RM 先执行本地事务但不提交,并通知 TM。如果都成功,再通知所有参与者提交,否则通知它们回滚。

在这里插入图片描述

特点

  • 需要参与者本身支持事务操作,具有 ACID 特性,通过事务回滚操作,比如数据库。
  • 准备提交阶段一般 RM 通过劫持与数据库的连接,先执行事务不提交,待 TM 通知后在执行提交操作。
  • 缺点:
    在准备提交阶段,正式提交前,RM 一直占用了资源比如线程,数据库连接。
    在 TM 等待 RM 准备提交的反馈时,有 RM 宕机会一直等待。
    如果 TM 在通知 RM 前宕机,则所有 RM 会一直等待。

实现

  • Txlcn 框架的 lcn 方式就是参考这一方案实现的,实现见 分布式事务-TX-LCN
  • Seata 框架则进行了改进,参与者直接先提交,在 undo_log 记录回滚信息,如果都成功则删掉记录,否则根据 undo_log 记录回滚。这种方式解决了准备提交占用资源问题。实现见 分布式事务-Seata

3PC(Three Phase Commit)

原理

  • 3PC 在 2PC 的基础上加入了询问(canCommit) 和超时机制,降低锁定资源概率,解决 TM/RM 宕机超时不响应导致等待问题。
  • canCommit:TM 先询问参与者 RM 是否可以开始事务,RM 自我检测,判断、反馈是否具有开始事务条件。
  • preCommit:TM 通知 RM 准备提交,RM 执行本地事务但不提交,并反馈给 TM。
  • doCommit:TM 通知 RM 提交,RM 提交本地事务完成整个事务流程。到了这一阶段,TM 通知超时也提交事务。

在这里插入图片描述

特点

  • 3PC 是在 2PC 基础上进行改进,同样要求事务参与者本身支持事务操作。准备提交阶段也会占用资源。
  • 通过 canCommit 确认 RM 具备事务条件,提高事务成功率从而降低资源占用概率。
  • 通过超时机制解决 TM / RM 宕机导致的等待问题。

TCC(Try Confirm Cancel)

原理

  • 将整个事务分为 try confirm cancel 三部操作,都执行 try 成功则执行 confirm 返回,否则执行 cancel 逆操作回滚 try 的执行结果后返回。各个步骤本地事务直接提交。
  • try 和 confirm 具体操作,可以根据情况而定,看后面扣款例子。

在这里插入图片描述

  • 在 try 中执行扣款完整逻辑,如果整体失败 concel 将金额返还。一般的业务这样做可以,但是在事务失败的情况下,用户会看到金额先扣掉了,然后又退回来了,感觉会有点疑惑。后面另一种处理方式会更好一点。

在这里插入图片描述

  • 在 try 中将金额扣除,写入到冻结资金中,这样展示给用户是冻结状态,成功则在 confirm 中真正扣除金额,而失败则在 cancel 中解冻金额。事务失败在 try cancel 之间展示给用户冻结状态,更为友好。

在这里插入图片描述

特点

  • 对比 2PC 和 3PC 这种方式直接提交事务不需要一直占用资源。
  • 通过 cancel 逆操作回滚,不要求参与者本身支持事务,适用混合了本身不支持事务的服务,比如 Redis
  • 缺点是有中间状态,每个事务操作都必须写 3 个处理方法。

实现

分布式事务-TX-LCN分布式事务-Seata

可靠消息服务

原理

  • 这种方式需要自己开发一个管理分布式事务状态的可靠消息服务,将事务分为待确认、已确认、已取消、已完成状态。
  • 上游服务先发起事务,向可靠消息服务写入【待确认】事务消息;本地事务执行成功或者失败后请求可靠消息服务将事务消息更改成【已确认】或者【已取消】。
  • 如果是【已确认】则可靠消息服务发送消息到消息队列,让下游服务消费。如果上游服务一直未修改【待确认】的消息状态,则定时向上游服务回查并修改。
  • 下游服务则消费消息队列中的消息,成功则最终发送【已完成】给可靠消息服务,如果下游服务不反馈消息消费状态,可靠消息服务同样会向下游服务定时回查状态。

在这里插入图片描述

特点

  • 各个事务参与者之间通过消息服务来保证消息最终一致性,达到了解耦的效果。
  • 从单个事务参与者角度看,事务变简单了;整体看分布式事务更复杂,需要开发单独可靠消息服务
  • 自己逻辑处理完就返回,比较适合高并发的场景。
  • 下游服务更新不一定立即处理,需要业务能容忍这点,比如购买商品后增加积分这种就可以。

最大努力通知

  • 这种适合向下游推送消息的场景,比如支付服务通知其他服务支付状态。下游服务需要给上游服务确认消费反馈,否则上游服务会尽可能的重复推送,尽量确保下游服务收到。
  • 比如 RocketMQ 可以配置未收到 ACK 逐步拉大重复推送的消息间隔 1min、5min、10min、30min、1h、2h、5h、10h,直到达到通知要求的时间窗口上限。

在这里插入图片描述

事务消息

  • 利用 RocketMQ 事务消息来实现分布式事务,执行本地事务前先向 RocketMQ 发送 haf msg,此时下游服务还消费不到,要向 RocketMQ 确认之后才可以被消费。
  • 可以执行本地事务后主动通知 RocketMQ 确认/回滚消息,也可以利用回查机制,被动反馈。

在这里插入图片描述

总结

2PC、3PC、TCC 保证整个事务都完成后才会返回,用户需要等待,但是能得到最终结果。2PC、3PC 要求参与者自己具备事务功能,一般指操作数据库的服务。如果有参与者不具备事务功能,则 TCC 更合适,但是开发工作量会大些。

可靠消息服务、最大努力通知和事务消息适合高并发的场景。用户能很快得到反馈,它们保证最终一致性,但是整个时间相对长一点,需要考虑业务场景是否合适。一般在实时性要求不是那么强的场景,比如购物后,通知积分服务、推送物流通知等。

以上方案细究其实还有很多漏洞并未解决,但是没有银弹,这些方案基本足够了,其他极端情况可以采用鸵鸟算法,在极低概率下出现问题的时候再人工处理。一般 2PC、事务消息这种相对简单的方案反而用得更多。

参考链接

分布式事务-TX-LCN

分布式事务-Seata

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我有八千部下

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值