分布式事务-本地消息表学习与落地方案
本文参考:
数据库事务系列04-本地消息表实现分布式事务
基础概念
本地消息表实现分布式事务最终一致性的核心:是通过上游本地事务的原子性+持久性,配合中间件的重试机制,从而实现调用下游的最终一致性。
这里有几个要点可以解析一下:
-
上游本地事务的原子性
通常上游会专门维护一张本地消息表,存放调用下游的消息,作为调用下游的依据。并且写消息表的动作和上游的业务逻辑都放在同一个本地事务中,位于同一个数据库中,借助本地事务的 ACID 特性,实现写业务逻辑 + 写下游消息的一致。 -
中间件的重试机制
会有中间件异步地去读取上面写的消息表,通常是定时任务去异步地扫表,读取出其中没有被确认调用过下游的消息,再次对下游发起调用。这里对下游发起调用也有多种方式,
- 在定时任务中按照消息表中记录的结构体直接调用下游 RPC,当有多个下游要接入的时候,上游需要配合改代码,代码耦合度较高,但是逻辑简单,不需要接入其他中间件,时效性最快。
- 定时任务将消息投递至消息中间件 MQ,由下游消费 MQ,当有多个下游要接入的时候,上游不需要感知,实现了逻辑解耦,但是架构较复杂,需要上下游同时接入中间件 MQ,并且时效性也没有很快,因为定时任务 -> MQ -> 调用下游 会有额外的网络开销。
-
调用下游的一致性
由于可能存在中间件的重试调用,所以下游需要自己保证调用接口的幂等性,否则会存在重复脏数据。
具体实现
来看看网上常见的两种本地消息表实现方案,之前我对这些方案也容易产生混淆,想着这种常见的分布式事务一致性手段,为什么连方案都不能实现统一?但是后来发现各种方案都是基于特定的场景衍生出来的,都有其应用场景,需要具体情况具体分析。先提前总结下,核心区别在于:修改消息表消息状态是由上游控制还是由下游控制的
本地消息表结构
| Name | Type | Comment |
|---|---|---|
| Id | Long | 唯一 id |
| Content | Text | 消息表内容JSON |
| Biz_Type | Integer | 消息类型 |
| Status | Integer | 消息状态(0未确认,1已确认) |
| Create_time | Datetime | 创建时间 |
| Modify_time | Datetime | 修改时间 |
| Ext_field | Text | 拓展字段 |
方案 1
核心流程如下所示:
- 上游 Service 执行业务逻辑,写入业务数据表
- 上游 Service 插入本地消息表,status = 0 未确认
- 定时任务扫描消息表中 status = 0 的记录
- 定时任务投递 status = 0 的记录至 MQ
- 下游 Service 接入并读取 MQ 消息
- 下游 Service 幂等消费并执行自己的业务逻辑
- 下游 Service 业务逻辑执行成功,回调 上游 Service 的接口通知成功
- 上游 Service 被回调以后,更新本地消息表状态为 status = 1 确认

其中 7, 8 需要上游业务提供回调接口,由下游调用,告知上游消息已经被正确地调用了,通过这一次 RPC 调用保证了上下游服务的最终一致性
方案 2
整体业务架构和上面的方案一致,但流程上有些不一样
- 上游 Service 执行业务逻辑,写入业务数据表
- 上游 Service 插入本地消息表,status = 0 未确认
- 定时任务扫描消息表中 status = 0 的记录
- 定时任务投递 status = 0 的记录至 MQ
- 定时任务直接将 status 改为 1 已发送
- 下游 Service 接入并读取 MQ 消息
- 下游 Service 幂等消费并执行自己的业务逻辑

其中 4,5 是定时任务投递了 MQ 消息过后,就直接将消息表中的状态 status = 1,上游的职责就是最大努力通知,上游将 status = 0 努力通知到下游,通知到下游就与它无关了。后续依赖 MQ 的持久化机制,并且完全信赖下游读取 MQ 消息并且能够成功消费的。
方案 1-2
这算是方案1在架构上的一种变式吧,就是不依赖 MQ,直接 RPC 调用下游,实现起来相对简单,耦合度会比较高,业务上下游针对不同的业务逻辑都需要单独开发一次

相关文章:
分布式事务-本地消息表学习与落地方案
本文参考: 数据库事务系列04-本地消息表实现分布式事务 基础概念 本地消息表实现分布式事务最终一致性的核心:是通过上游本地事务的原子性持久性,配合中间件的重试机制,从而实现调用下游的最终一致性。 这里有几个要点可以解析一…...
Debezium系列之:记录一次源头数据库刷数据,造成数据丢失的原因
Debezium系列之:记录一次源头数据库刷数据,造成数据丢失的原因 一、背景二、查看topic日志信息三、结论四、解决方法一、背景 源头数据库在很短的时间内刷了大量的数据,部分数据在hdfs丢失了 理论上debezium数据采集不会丢失,就需要排查数据链路某个节点是否有数据丢失。 …...
PHP约课健身管理系统小程序源码
🏋️♂️ 约课健身管理系统小程序:重塑健身预约体验,引领数字化健身新时代 一款基于ThinkPHPUniapp框架,由米扬精心雕琢的约课健身管理系统小程序,专为健身房、健身工作室、运动会所、运动场馆、瑜伽馆、拳馆等泛健…...
Java之泛型
文章目录 首先接着上一篇(集合)文章,来个非常牛逼的易错题传统集合问题分析泛型快速入门案例泛型介绍泛型的好处泛型的语法泛型的声明泛型的实例化泛型使用举例泛型使用的注意事项和细节 自定义泛型自定义泛型方法 自定义泛型接口自定义泛型方…...
图论 之 最小生成树
文章目录 题目1584.连接所有点的最小费用 最小生成树MST,有两种算法进行求解,分别是Kruskal算法和Prim算法Kruskal算法从边出发,适合用于稀疏图Prim算法从顶点出发,适合用于稠密图:基本思想是从一个起始顶点开始&#…...
STM32-有关内存堆栈、map文件
STM32堆栈空间大小设置_stm32堆栈分配大小-CSDN博客 STM32堆栈的大小及内存四(五)区的分析 - 天街小雨润地狠 - 博客园 .map文件的位置...
Linux系统中常见的词GNU是什么意思?
GNU 是 “GNU’s Not Unix” 的递归缩写,它是一个自由软件项目,旨在创建一个完全自由的操作系统。这个名字反映了GNU项目的核心理念:它试图创建一个类Unix的系统,但不是Unix本身。 GNU 项目由 理查德斯托曼(Richard S…...
【个人开源】——从零开始在高通手机上部署sd(二)
代码:https://github.com/chenjun2hao/qualcomm.ai 推理耗时统计 单位/ms 硬件qnncpu_clipqnncpu_unetqnncpu_vaehtp_cliphtp_unethtp_vae骁龙8 gen124716.994133440.39723.215411.097696.327 1. 下载依赖 下载opencv_x64.tar,提取码: rrbp下载opencv_aarch64.t…...
【MCU驱动开发概述】
MCU驱动开发概述 目录 MCU驱动开发概述二、驱动开发的目的三、驱动开发的关键组成部分四、示例 - LED 控制驱动 一、引言 MCU(Microcontroller Unit),即微控制器单元,是一种集成在单个芯片上的计算机系统,通常用于控制…...
PC端Linux之虚拟CAN
在调试QT程序时候需要用到虚拟CAN进行发送和接收的操作,以此记录方法。 在调试QT程序时候需要用到虚拟CAN进行发送和接收的操作,以此记录方法。 1、安装can-utils sudo apt install can-utils ifconig -a【查看是否安装成功,是否有can0网络…...
C++:std::thread、条件变量与信号量
介绍 在多线程编程的世界里,协调不同线程之间的工作是一项极具挑战性的任务。线程可能需要等待特定条件的满足,或者对共享资源的访问进行限制。C 标准库为我们提供了强大的工具,如 std::thread 用于创建和管理线程,条件变量用于线…...
POI pptx转图片
前言 ppt页面预览一直是个问题,office本身虽然有预览功能但是收费,一些开源的项目的预览又不太好用,例如开源的:kkfileview pptx转图片 1. 引入pom依赖 我这个项目比较老,使用版本较旧 <dependency><gro…...
Java File 类
File 类是 Java 中用于处理文件和目录的基本类之一,位于 java.io 包中。它提供了多种方法来创建、删除、检查、修改文件或目录的属性,以及列出文件夹中的内容。虽然 File 类本身不提供直接的读取或写入文件内容的方法(这些操作通常由 FileInp…...
工业通信协议 EtherNet/IP 全面解析
工业通信协议 EtherNet/IP 全面解析 EtherNet/IP(以太网工业协议)是一种基于标准以太网的工业自动化通信协议,由 ODVA(开放设备网供应商协会) 管理。它融合了 CIP(通用工业协议) 和以太网技术&…...
使用docker配置PostgreSQL
配置docker阿里云镜像仓库 国内使用docker hub拉取镜像比较慢,所以首先配置个人的镜像仓库。 阿里云的个人镜像仓库是免费的,对个人来说足够用。 具体操作参考阿里云官方链接 。 关于个人镜像仓库的使用参考链接。 配置完个人镜像仓库后将公网配置到doc…...
UITextView删除原有字符串时,光标会上移并且光标会变高
代码运行效果如图: import Foundationclass TestVC: UIViewController {override func viewDidLoad() {super.viewDidLoad()let testV MyCustomTextView(frame: CGRect(x: 0, y: 130, width: SCREEN_WIDTH - 50, height: 170))self.view.addSubview(testV)testV.ba…...
python入门 介绍及变量的使用
1.python介绍 python 是一门计算机语言 常见的计算机语言:python、java、C语言。。。 什么是计算机语言:就是让计算机知道你想干什么,把你的需求使用它能听懂的语言说出来 中国也有一门计算机语言:易语言 能认为是语言的本质上…...
51单片机-按键
1、独立按键 1.1、按键介绍 轻触开关是一种电子开关,使用时,轻轻按开关按钮就可使开关接通,当松开手时,开关断开。 1.2、独立按键原理 按键在闭合和断开时,触点会存在抖动现象。P2\P3\P1都是准双向IO口,…...
Java 8 至 Java 23 版本特性对比表
Java现在发布的版本很快,每年两个,但是真正会被大规模使用的是三年一个的TLS版本。 版本年份LTS关键特性影响力等级Java 82014✅Lambda 表达式、Stream API、方法引用、接口默认方法、Optional 类⭐⭐⭐⭐⭐Java 92017❌模块化系统(JPMS&…...
在wsl环境中配置和开发verilog(一种比较新颖的verilog开发指南)
WSL是windows中自带的linux子系统,笔者在若干月前首次接触其便爱不释手,verilog作为一种硬件解释语言,可否像c语言那样被游刃有余的编译和运行呢,笔者这次大胆的尝试在WSL环境VSCODEIverilog开发verilog。 首先默认按照了WSL和VS…...
C++_核心编程_多态案例二-制作饮品
#include <iostream> #include <string> using namespace std;/*制作饮品的大致流程为:煮水 - 冲泡 - 倒入杯中 - 加入辅料 利用多态技术实现本案例,提供抽象制作饮品基类,提供子类制作咖啡和茶叶*//*基类*/ class AbstractDr…...
python/java环境配置
环境变量放一起 python: 1.首先下载Python Python下载地址:Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个,然后自定义,全选 可以把前4个选上 3.环境配置 1)搜高级系统设置 2…...
vscode(仍待补充)
写于2025 6.9 主包将加入vscode这个更权威的圈子 vscode的基本使用 侧边栏 vscode还能连接ssh? debug时使用的launch文件 1.task.json {"tasks": [{"type": "cppbuild","label": "C/C: gcc.exe 生成活动文件"…...
Qwen3-Embedding-0.6B深度解析:多语言语义检索的轻量级利器
第一章 引言:语义表示的新时代挑战与Qwen3的破局之路 1.1 文本嵌入的核心价值与技术演进 在人工智能领域,文本嵌入技术如同连接自然语言与机器理解的“神经突触”——它将人类语言转化为计算机可计算的语义向量,支撑着搜索引擎、推荐系统、…...
SpringBoot+uniapp 的 Champion 俱乐部微信小程序设计与实现,论文初版实现
摘要 本论文旨在设计并实现基于 SpringBoot 和 uniapp 的 Champion 俱乐部微信小程序,以满足俱乐部线上活动推广、会员管理、社交互动等需求。通过 SpringBoot 搭建后端服务,提供稳定高效的数据处理与业务逻辑支持;利用 uniapp 实现跨平台前…...
解决本地部署 SmolVLM2 大语言模型运行 flash-attn 报错
出现的问题 安装 flash-attn 会一直卡在 build 那一步或者运行报错 解决办法 是因为你安装的 flash-attn 版本没有对应上,所以报错,到 https://github.com/Dao-AILab/flash-attention/releases 下载对应版本,cu、torch、cp 的版本一定要对…...
【python异步多线程】异步多线程爬虫代码示例
claude生成的python多线程、异步代码示例,模拟20个网页的爬取,每个网页假设要0.5-2秒完成。 代码 Python多线程爬虫教程 核心概念 多线程:允许程序同时执行多个任务,提高IO密集型任务(如网络请求)的效率…...
【HTTP三个基础问题】
面试官您好!HTTP是超文本传输协议,是互联网上客户端和服务器之间传输超文本数据(比如文字、图片、音频、视频等)的核心协议,当前互联网应用最广泛的版本是HTTP1.1,它基于经典的C/S模型,也就是客…...
视觉slam十四讲实践部分记录——ch2、ch3
ch2 一、使用g++编译.cpp为可执行文件并运行(P30) g++ helloSLAM.cpp ./a.out运行 二、使用cmake编译 mkdir build cd build cmake .. makeCMakeCache.txt 文件仍然指向旧的目录。这表明在源代码目录中可能还存在旧的 CMakeCache.txt 文件,或者在构建过程中仍然引用了旧的路…...
CVE-2020-17519源码分析与漏洞复现(Flink 任意文件读取)
漏洞概览 漏洞名称:Apache Flink REST API 任意文件读取漏洞CVE编号:CVE-2020-17519CVSS评分:7.5影响版本:Apache Flink 1.11.0、1.11.1、1.11.2修复版本:≥ 1.11.3 或 ≥ 1.12.0漏洞类型:路径遍历&#x…...
