基于消息的分布式事务的概念学习

Posted FserSuN

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于消息的分布式事务的概念学习相关的知识,希望对你有一定的参考价值。

1.背景

在日常业务中存在本地事务操作和MQ共同使用的场景,可能出现任意一个失败,导致数据不一致的问题。

常见教程中一个例子:

对于订单系统来说,它创建订单的过程中实际上执行了2个步骤的操作:
1在订单库中插入一条订单数据,创建订单;
1.1 发消息给消息队列,消息的内容就是刚刚创建的订单。
1.2 发消息给消息队列,消息的内容就是刚刚创建的订单。
2 购物车系统订阅相应的主题,接收订单创建的消息,然后清理购物车,在购物车中删除订单中的商品。

上述过程可能总结为:

  1. 处理业务逻辑
  2. 发送MQ、RPC调用等非本地事务操作

1、2失败最终出现导致数据不一致的问题。

业务逻辑处理完,下一步为发送消息。如果MQ支持事务消息,那么基于事务消息,发送MQ前,数据库操作成功,随后发送MQ失败,这时就进行重试,直到成功。

业务处理完逻辑,下一步通知为RPC调用或其它非MQ的远程调用。或MQ不支持事务,那么基于本地消息表(本地消息日志)保证最终事务的执行成功。

2 事务消息机制

支持事务消息的MQ常见处理逻辑如下:

  1. 消息中间件支持一种中间状态的消息,例如Half状态。这种状态消息不会被消费端消费。
  2. 客户端先发送Half消息,成功后执行本地事务。本地事务执行成功后,提交Half消息。随后MQ服务端会把消息状态从Half转拜年为正常状态,然后投递给消费者。 在这个过程中如果本地事务执行失败,则回滚消息。服务端删除Half状态消息,不会投递给消费者。
  3. MQ服务端同时通过定时查询未明确状态的消息,根据本地事务的执行状态决定是提交还是回滚。

基于事务消息处理1中问题特点如下:

1.业务侧实现一个事务状态回查接口
2.发送一条消息MQ生产者和服务端需要两次远程调用。
3.适用于发送MQ同时成功的场景,RPC或者其分布式事务场景的不支持。

3. 本地消息表

2中介绍的处理以来MQ事务的支持,如果是RPC调用或MQ不支持事务消息,则可基于本地消息表的模式[1]。

系统维护一个本地消息表。这个本地消息表和业务数据表的操作同一个事务中进行。如果我们的本地业务和消息表(写消息日志)操作成功。我们在本地消息表中记录一条日志,其状态为待发送。系统通过定时任务扫描本地消息表中待发送的消息。随后执行MQ发送操作或RPC调用操作。通过一些重试策略控制,当操作调用失败,那么根据重试策略重试,直到成功。兜底情况下引入人工介入通知。防止因系统bug导致重试一致失败,方便人工排查。执行完毕后,本地消息记录将被删除。

因此基于这种模式需要在业务库中增加一张表,可能用到的字段如下:

    全局事务id
    全局事务名称
    事务状态
    事务最大重试超时时间
    事务最大重试次数
    下次重试执行时间
 	创建时间
 	更新时间
 	回调参数

4. 远程调用支持扩展

基于2、3的介绍,框架支持上,通过3的形式扩展。统一支持业务操作、MQ\\RPC\\其它调用的场景。RPC的扩展也要保证幂等。

5. ACID特性分析

基于消息的分布式事务对ACID的支持情况如下:

  • 原子性:分支事务要么全部执行,要么全部取消
  • 一致性:会保证最终一致性,轮训状态重试保证
  • 隔离性:不支持,从概念分析可得
  • 持久性:本地事务来保证持久性

基于消息的分布式事务,解偶系统。但限于最终一致性的场景使用。

6.参考

[1] 分布式事务深度分析, https://www.alibabacloud.com/blog/an-in-depth-analysis-of-distributed-transaction-solutions_597232

以上是关于基于消息的分布式事务的概念学习的主要内容,如果未能解决你的问题,请参考以下文章

基于可靠消息方案的分布式事务:Lottor介绍

基于2PC和延迟更新完成分布式消息队列多条事务Golang版本

基于本地消息表的分布式事务解决方案总结

分布式事务之 RocketMQ 事务消息详解

REST微服务的分布式事务实现-基于消息中间件

分布式事务介绍