MQ消息最终一致性事务

本文我们将学习到一种常见的柔性事务解决方案:消息一致性事务方案。

对于TCC型事务,跨系统的调用均是基于服务间的直接调用,即很大程度上是同步调用。基于TCC方案能够保证主子事务同时成功,同时失败。

但实际开发中,由于多方面的考虑,我们会将服务拆分为异步方式,一般是基于MQ进行服务间的解耦,服务发起方执行完本地业务操作后发送一条消息给到消息中间件(比如:RocketMQ、RabbitMQ、Kafka、ActiveMQ等),被动方服务从MQ中消费该消息并进行业务处理,从而形成业务上的闭环。

这种场景下,我们还是希望异步的多个业务操作同时成功,同时失败,基于TCC的同步型事务解决方案就不可行了,这时就需要祭出可靠消息最终一致性方案。

实现可靠消息服务

首先按照惯例我们先看一下该方案的简略的结构图,如下

核心流程1:上游投递消息

基于上图,我们分析一下如果要实现一个可靠消息一致性的服务,需要实现哪些功能,要走哪些流程。

调用开始,业务主动方(之后称为主动方)预先发送一条消息到消息服务(图中中间的部分)中,消息中包含后续的业务操作所必须的业务参数,消息服务接收到该消息后存储消息到消息存储中,并设置消息状态为 “待确认”

如果消息存储失败则直接返回消息持久化失败,本次业务操作结束。

当主动方接收到消息存储结果后,开始执行本地的业务操作,根据本地事务提交的结果,调用消息服务的接口。这里分为两种状态:

  1. 如果本地事务执行成功,就调用消息服务确认消息状态,更新为 待发送

  2. 如果本地事务执行失败,就调用消息服务删除消息(一般是逻辑删除,更新消息状态为 已回滚

### 如何在消息队列中实现消息最终一致性解决方案 为了保证消息队列中的消息最终一致性,可以通过多种方式实现。以下是几种常见的方法及其具体实现: #### 1. **事务消息** RocketMQ 提供了一种事务消息的功能,用于解决生产端的消息发送与本地事务执行之间的原子性问题[^3]。 - 当 Producer 发送半消息(Prepared 消息)到 Broker 后,Broker 并不会立即将该消息标记为可消费。 - 接下来,Producer 执行本地事务逻辑并根据结果向 Broker 返回确认状态(Commit 或 Rollback)。如果返回 Commit,则 Broker 将消息标记为可消费;如果是 Rollback,则删除该消息。 - 如果 Producer 在一定时间内未响应,Broker 会主动发起回查请求,询问 Producer 的事务状态,并依据反馈更新消息的状态。 这种方式适用于需要强一致性的场景,但由于其实现复杂度较高,仅限于部分 MQ 支持,如 RocketMQ。 #### 2. **可靠消息最终一致性模式** 这种模式基于“本地消息表”的概念,最初由 eBay 提出[^4]。核心思想是将分布式事务分解为多个本地事务来处理: - 生产者在完成业务操作的同时,记录一条消息日志至本地数据库的消息表中。 - 使用定时任务扫描消息表,发现待发送的消息后将其提交到 MQ 中。 - 若消息发送失败,则触发重试机制直至成功或达到最大尝试次数为止。 此方法的优点在于兼容性强,几乎所有的 MQ 都能适配,缺点则是增加了开发工作量以及可能带来性能开销。 #### 3. **幂等性设计** 无论采用哪种方案,都需要确保消费者具备良好的幂等性特性[^2]。这是因为大多数 MQ 都支持至少一次交付语义 (At-Least-Once Delivery),这意味着当网络分区或其他异常状况发生时,可能会导致重复投递同一份数据包给订阅方。因此,在接收端应采取措施防止因多次接收到相同 ID 的事件而导致错误行为的发生。例如,可以在数据库层面建立唯一索引来避免重复写入相同的记录。 #### 示例代码:实现简单的幂等性检查 下面是一个 Python 实现的例子,展示如何通过 Redis 缓存服务来进行基本的幂等校验过程: ```python import redis def process_message(message_id, payload): r = redis.StrictRedis(host='localhost', port=6379, db=0) if not r.exists(f'message:{message_id}'): # Process the message here... # Mark as processed after successful processing. r.setex(f'message:{message_id}', time=86400, value="processed") # Expires in one day. process_message('msg_12345', {'data': 'example'}) ``` 以上介绍了三种主要途径帮助开发者构建具有高度可靠性保障的信息传递管道——无论是借助特定框架所提供的高级功能还是自行定制低级协议细节均可达成目标。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值