分布式事务-通过本地消息表实现最终一致性

本地消息表步骤

通过本地消息表(也称为可靠消息表)实现分布式事务是一种常见的做法,用于保证在分布式环境中消息的可靠传递和事务的一致性。以下是使用本地消息表实现分布式事务的一般步骤:

消息生产方(也就是发起方),需要额外建一个消息表,并记录消息发送状态。消息表和业务数据要在一个事务里提交,也就是说他们要在一个数据库里面。然后消息会经过MQ发送到消息的消费方。如果消息发送失败,会进行重试发送。

消息消费方(也就是发起方的依赖方),需要处理这个消息,并完成自己的业务逻辑。此时如果本地事务处理成功,表明已经处理成功了,如果处理失败,那么就会重试执行。如果是业务上面的失败,可以给生产方发送一个业务补偿消息,通知生产方进行回滚等操作。

生产方和消费方定时扫描本地消息表,把还没处理完成的消息或者失败的消息再发送一遍。

以下是具体步骤:

0. 创建本地消息表:

在数据库中创建一个本地消息表,用于存储待发送的消息以及消息的发送状态和相关信息。表结构可以包含字段如下:

  • message_id:消息的唯一标识。
  • message_body:消息内容。
  • status:消息状态,如待发送、已发送等。
  • create_time:消息创建时间。
  • 其他字段,如重试次数、发送时间等。

1. 业务处理: 业务处理时通常进行db变更

2. 将业务变更信息插入记录表:在业务逻辑中,当需要发送消息时,首先将消息插入到本地消息表中,设置状态为待发送。

3. 发送消息,1、2、3步骤在同一个本地事务中。如果本地事务执行成功,提交本地事务和消息表的记录;如果本地事务失败,回滚本地事务和消息表的记录。

3.1,3.2. 消息确认机制:

单独创建一个后台线程或定时任务,定时扫描本地消息表中状态为待发送的消息,并将这些消息发送到消息队列。在成功发送到消息队列后,将消息表中对应的状态修改为已发送。此外,可以根据需要实现消息发送失败后的重试机制。

4. B系统消费消息:

消费者监听消息队列,解析消息内容。

5. B系统进行业务逻辑处理:

进行业务逻辑处理,更改DB。此步骤必须要保证幂等性

4、5 如果失败依赖3.1、3.2的定时投放

6. 确认消费完成:

当消息消费完成后,调用A系统进行状态变更

6、7如果失败相当于两个分布式系统的数据已经一致了,但是本地消息表的状态还是错的。这种情况下借助3.1、3.2的重新投放策略,让下游幂等处理再更改消息表的状态也能解决。或者A系统也可以查询B系统的处理状态,如果成功直接更改状态

注意事项

使用本地消息表实现分布式事务可以确保消息在分布式环境中的可靠传递和一致性。然而,需要注意以下几点:

  • 消息的幂等性: 消费者一定需要保证接口的幂等性,消息的幂等性非常重要,以防止消息重复处理导致的数据不一致。
  • 本地消息表的设计: 本地消息表的设计需要考虑到消息状态、重试次数、创建时间等字段,以便实现消息的跟踪和管理。
  • 定时任务和重试机制: 需要实现定时任务或者重试机制来确保消息的可靠发送和处理。

本地消息表实现分布式事务缺点及解决方式

  • 数据大时,消息堆积,扫表效率慢
  • 定时扫表存在延迟问题

消息堆积、扫表效率慢

  • 索引优化:在消息表中对状态字段增加索引,以加速扫表操作。索引可以加速消息的检索和筛选,从而提高操作效率。
  • 分页查询:将扫表操作划分为多次分页查询,避免一次性查询大量数据造成的性能问题。
  • 表较大时进行分库分表:如果表较大可以进行分库分表操作。
  • 多线程分段查询:
    • 如果有业务标识,可以通过业务标识进行多线程分段扫表查询。
    • 如果没有业务标识可以按区间查询比如线程1查询0-1000的数据,线程2查询1001-2000的数据。

定时任务扫表延迟问题

定时任务可能由于各种原因导致扫表延迟,进而影响事务处理的实时性。以下是一些应对方法:

  • 异步发送MQ改为同步调用接口:异步改为同步调用B系统接口,如果失败了再进行异步发送MQ消息。
  • 发送MQ延迟消息,去掉定时任务,避免大量扫表处理。
  • 分布式定时任务: 使用分布式定时任务框架,将定时任务分散到多个节点上执行,以减少单个节点的压力,同时提高定时任务的稳定性和准确性。
  • 增加资源: 增加定时任务执行节点的数量,以提高并发处理能力,减少延迟。
相关推荐
sir76113 分钟前
Redisson分布式锁实现原理
后端
永亮同学15 分钟前
【探索实战】从零开始搭建Kurator分布式云原生平台:详细入门体验与功能实战分享!
分布式·云原生·交互
大学生资源网34 分钟前
基于springboot的万亩助农网站的设计与实现源代码(源码+文档)
java·spring boot·后端·mysql·毕业设计·源码
苏三的开发日记43 分钟前
linux端进行kafka集群服务的搭建
后端
苏三的开发日记1 小时前
windows系统搭建kafka环境
后端
爬山算法1 小时前
Netty(19)Netty的性能优化手段有哪些?
java·后端
Tony Bai1 小时前
Cloudflare 2025 年度报告发布——Go 语言再次“屠榜”API 领域,AI 流量激增!
开发语言·人工智能·后端·golang
想用offer打牌1 小时前
虚拟内存与寻址方式解析(面试版)
java·后端·面试·系统架构
無量1 小时前
AQS抽象队列同步器原理与应用
后端
2 小时前
TIDB——TIKV——读写与coprocessor
数据库·分布式·tidb·