当前位置: 首页 > news >正文

基于本地消息表实现分布式事务(最终一致性)

前言

传统单体架构下,所有的功能模块都在一个应用下,所有的代码和业务逻辑都在同一个应用下实现,所以保证数据的一致性就很简单,保证相关操作都在同一个本地事务下就可以了。

但是在微服务架构下,将一个应用拆分成了多个独立的服务,每个服务都能有自己的数据库,服务间通信都是通过远程调用实现,实现一个功能可能需要由几个不同的服务来共同实现。这就会带来一个问题,不同的服务之间无法做到使用同一个事务,这就无法保证数据的一致性了。

解决分布式事务的问题,一劳永逸的方式就是直接使用 Seata,Seata 是一个开源的分布式事务解决方案,用于解决分布式系统中的数据一致性问题。但是,引入 Seata 实在是太重了,在实际工作中接触过的系统,并没有那么多的业务需要使用到分布式事务,为了解决那么一两个业务的问题却要为整个系统引入分布式事务服务,代价实在是太大了。而且,相关的业务实际上只需要保证数据的最终一致性,不用保证强一致性,所以在实践可以使用本地消息表的方案来解决分布式事务问题。

本地消息表方案

如果系统中只有少数服务需要用到分布式事务,那么直接在该服务下创建一张本地消息表,结合消息队列,就能够实现数据的最终一致性了。

表设计

本地消息表的设计如下

字段类型注释
idlongid
msg_typevarchar消息类型
biz_idvarchar业务唯一标志
contenttext消息体
statevarchar状态(待发送,已消费)
create_timedatetime创建时间
update_timedatetime更新时间

时序图

plantuml

@startuml
'https://plantuml.com/sequence-diagramautonumberparticipant Scheduled_Task
database DB_A
participant Service_A
queue Queue
participant Service_B
database DB_Bgroup Service_A本地事务DB_A <- Service_A: 写本地业务数据DB_A <- Service_A: 写本地消息数据
endService_A -> Queue: 发送消息
note left
发送消息放到事务外
防止由于网络延迟出现
Service_A认为发送失败导致事务回滚
而实际上MQ收到了消息
Service_B也消费了消息
从而出现数据不一致的情况
end noteQueue -> Service_B: 消费消息Service_B -> Service_B: 幂等判断
note right
防止重复消费消息
end notegroup Service_B本地事务Service_B -> DB_B: 写本地业务数据
endgroup 更新本地消息表状态Scheduled_Task <- Service_B: 更新本地消息表状态Scheduled_Task -> DB_A: 更新本地消息表状态
end
note right
这里即使失败了也无所谓
两个服务的数据已经一致了
没有更新消息状态,定时任务会重新投递
Service_B做好幂等处理
等下次消费再去修改消息状态即可
end noteloop 定时任务Scheduled_Task -> DB_A: 查询未成功投递的消息Scheduled_Task -> Queue: 重新投递
end@enduml

消息服务方案

本地消息表只只用系统中只有少量业务需要实现分布式事务的情况,如果系统中的绝大多数服务都存在分布式事务的业务场景,为每个服务都创建一张本地消息表显然很麻烦,难以维护。

用到的地方多,实际上就可以考虑上 Seata 了,专业的事要交给专业的服务来做。不过这里也可以改进一下本地消息表的方案,增加一个专门处理分布式事务消息的消息服务和消息库。

表设计

表设计同上面一样,消息服务只不过将所有本地消息表合并成一张表了

只不过 state 字段需要多一个状态来区分

在本地消息表方案中,由于写Service_A业务和创建消息是在同一个事务中,它们要么同时成功,要么同时失败,所以两个状态(待发送,已消费)就能表示整个消息的生命周期。

  1. 待发送状态,则表示Service_A业务和消息同时写入库成功,等待Service_B消费消息
  2. 已消费状态,则表示Service_B已经成功消费了消息

在消息服务方案中,写业务和创建消息不在同一个事务中,所以需要再加一个状态(发送中)

  1. 待发送状态,则表示刚创建消息,此时Service_A还没有写库
  2. 发送中状态:则表示Service_A已经写库成功,等待Service_B消费消息
  3. 已消费状态,则表示Service_B已经成功消费了消息

时序图

plantuml

@startuml
'https://plantuml.com/sequence-diagramautonumberdatabase DB_A
participant Service_A
participant Service_Msg
database DB_Msg
queue Queue
participant Service_B
database DB_Bgroup 创建消息Service_A -> Service_Msg: 创建消息note left: 生成业务idService_Msg -> DB_Msg: 创建消息note left: 消息状态:待发送Service_A <- Service_Msg: 返回消息ID
endgroup Service_A本地事务DB_A <- Service_A: 写本地业务数据
endService_A -> Service_Msg: 发送消息
note left: 携带消息ID
Service_Msg -> DB_Msg: 更新消息状态
note right: 消息状态:发送中
Service_Msg -> Queue: 发送消息
Queue -> Service_B: 消费消息Service_B -> Service_B: 幂等判断group Service_B本地事务Service_B -> DB_B: 写本地业务数据
endgroup 更新消息状态Service_Msg <- Service_B: 更新消息状态Service_Msg -> DB_Msg: 更新消息状态note right: 消息状态:已消费
endloop 定时任务Service_Msg -> DB_Msg: 查询状态为发送中的消息Service_Msg -> Queue: 重新投递
end@enduml

相关文章:

基于本地消息表实现分布式事务(最终一致性)

前言 传统单体架构下&#xff0c;所有的功能模块都在一个应用下&#xff0c;所有的代码和业务逻辑都在同一个应用下实现&#xff0c;所以保证数据的一致性就很简单&#xff0c;保证相关操作都在同一个本地事务下就可以了。 但是在微服务架构下&#xff0c;将一个应用拆分成了…...

大数据mapper书写范式hdfs

文章目录 1. 大数据mapper书写范式hdfs 1. 大数据mapper书写范式hdfs import json import sysdef read_input(input_stream):for line in input_stream:yield line.rstrip(\n)def load_json_data(json_line):try:data json.loads(json_line)unique_id data.get(id)combined_…...

ubuntu将软件放到任务栏

右键点击这个 pycharm 方法1&#xff1a; 方法2&#xff1a; sudo nano /usr/share/applications/PyCharm.desktop 编辑这个 [Desktop Entry] NamePyCharm CommentPyCharm Integrated Development Environment Exec/path/to/PyCharm.sh Icon/path/to/PyCharm.svg Terminalf…...

Spring Boot 参数校验 Validation 使用

概述 当我们想提供可靠的 API 接口&#xff0c;对参数的校验&#xff0c;以保证最终数据入库的正确性&#xff0c;是必不可少的活。前、后端校验都是保证参数的准确性的手段之一&#xff0c;前端校验并不安全&#xff0c;任何人都可以通过接口来调用我们的服务&#xff0c;就算…...

基于el-table的表格点选和框选功能

开篇 本篇文章旨在实现一个基于el-table的表格点选和框选功能&#xff0c;除此之外&#xff0c;还支持多种模式的切换、自定义勾选日期等。且&#xff0c;该表格后续可能还会持续优化&#xff01; 功能介绍 表格点选和框选功能&#xff08;没有点击ctrl键的情况下&#xff09;…...

LabVIEW压电陶瓷阻抗测试系统

开发了一种基于LabVIEW软件与PXI模块化仪器的压电陶瓷阻抗测试系统。该系统能在高电压工作条件下测量压电陶瓷的阻抗特性&#xff0c;包括阻抗模值与阻抗角的频率特性&#xff0c;为压电陶瓷的进一步分析与应用提供了重要参考。 项目背景 现有的阻抗测试仪大多只能在低电压条件…...

电销机器人能大幅度提升效率

1、安全稳定性能好 营销机器人的稳定性非常强&#xff0c;在使用性能方面会有更好的优势&#xff0c;而且用的过程中也可以不断的这些模块更新和功能升级&#xff0c;所以会不断的满足大家更多的使用要求&#xff0c;在操作使用的时候非常简单和方便&#xff0c;直接就可以给客…...

虚拟机能访问网页但ping不通百度

最近遇到了奇怪的问题&#xff0c;虚拟机能访问网页&#xff0c;但ping不通百度&#xff0c;记录一下问题的排查过程。 能访问网页&#xff0c;说明DNS、TCP和HTTP没有问题&#xff0c;ping不通&#xff0c;说明ICMP应该出了问题。 首先通过traceroute追踪报文的转发过程&…...

RK3588开发笔记-buildroot编译配置

目录 前言 一、buildroot简介 二、buildroot配置编译 buildroot config配置 buildroot 编译 buildroot 如何单独编译某个软件包 何时需要完全重建 如何完全重建 总结 前言 Rockchip RK3588 是一款强大的多核处理器,广泛应用于边缘计算、人工智能、嵌入式系统等领域。为了在…...

Java设计模式(适配器模式)

定义 将一个类的接口转换成客户希望的另一个接口。适配器模式让那些接口不兼容的类可以一起工作。 角色 目标抽象类&#xff08;Target&#xff09;&#xff1a;目标抽象类定义客户所需的接口&#xff08;在类适配器中&#xff0c;目标抽象类只能是接口&#xff09;。 适配器类…...

机器学习框架巅峰对决:TensorFlow vs. PyTorch vs. Scikit-Learn实战分析

1.引言 1.1机器学习框架的重要性 在机器学习的黄金时代&#xff0c;框架的选择对于开发高效、可扩展的模型至关重要。合适的框架可以极大地提高开发效率&#xff0c;简化模型的构建和训练过程&#xff0c;并支持大规模的模型部署。因此&#xff0c;了解和选择最合适的机器学习…...

基于STM32的智能窗帘控制系统

目录 引言环境准备工作 硬件准备软件安装与配置系统设计 系统架构硬件连接代码实现 初始化代码控制代码应用场景 家居智能窗帘控制办公室窗帘自动调节常见问题及解决方案 常见问题解决方案结论 1. 引言 智能窗帘控制系统能够通过时间、光照强度或远程控制&#xff0c;实现对…...

【算法】普里姆算法解决修路问题

应用场景——修路问题 1.某地有 7 个村庄&#xff08;A&#xff0c;B&#xff0c;C&#xff0c;D&#xff0c;E&#xff0c;F&#xff0c;G&#xff09;&#xff0c;现在需要修路把 7 个村庄连通 2.各个村庄的距离用边线表示&#xff08;权&#xff09;&#xff0c;比如 A - …...

Python 之Scikit-learn(二) -- Scikit-learn标准化数据

在机器学习中&#xff0c;数据标准化是一项关键的预处理步骤。标准化&#xff08;Standardization&#xff09;是将数据转换为具有均值为0和标准差为1的分布。这样可以确保特征在相同的尺度上&#xff0c;有助于提升某些机器学习算法的性能和稳定性。 Scikit-learn提供了一个简…...

机械学习—零基础学习日志(python编程)

零基础为了学人工智能&#xff0c;正在艰苦的学习 昨天给高等数学的学习按下暂停键&#xff0c;现在开始学习python编程。 我学习的思路是直接去阿里云的AI学习课堂里面学习。 整体感觉&#xff0c;阿里云的AI课堂还是有一些乱&#xff0c;早期课程和新出内容没有更新和归档…...

WEB应用(十三)---RCE

什么是RCE&#xff1f; Remote Command/Code Execute&#xff0c;远程命令或代码执行。通过构造特殊的字符串&#xff0c;将数据提交至Web应用程序&#xff0c;并利用该方式执行外部程序或系统命令实施攻击&#xff0c;类似于SQL注入。 Web应用程序使用了一些可以执行系统命令或…...

【云原生】Service服务暴露详细

Service服务 文章目录 Service服务一、Service介绍1.1、介绍1.2、Kubernetes中的Service 二、Service服务类型2.1、ClusterIP2.2、NodePort2.3、LadBalancer2.4、ExternalName 三、Service玩法3.1、定义Service3.2、端口定义别名3.3、多端口Service 四、Service类型4.1、Cluste…...

实名认证次数限制

在业务层实现实名认证次数限制 这个功能是通过以下步骤实现实名认证的次数限制&#xff1a; 每日失败尝试次数限制&#xff1a;限制用户每天可以尝试失败的次数。失败后的冷却时间&#xff1a;用户在连续失败几次后需要等待一段时间才能再次尝试。成功认证后的限制&#xff1…...

【如何在Python中使用pathlib模块】

在Python中使用pathlib模块主要涉及创建Path对象&#xff0c;并利用这些对象提供的方法来执行文件系统的各种操作。以下是一些详细的步骤和示例&#xff0c;帮助你了解如何在Python中有效地使用pathlib模块。 1. 导入Path类 首先&#xff0c;从pathlib模块中导入Path类。 fr…...

sqli-labs第一关详细解答

首先判断是否有注入点 发现and 11 和 and 12结果一样&#xff0c;所以应该是字符型注入&#xff0c;需要对单引号做闭合 做闭合后发现报错&#xff0c;提示Limit 0,1&#xff0c;那就说明存在注入点&#xff0c;但是要注释掉后面的limit 0,1 使用--注释掉limit 0,1后&#xff…...

React Native 导航系统实战(React Navigation)

导航系统实战&#xff08;React Navigation&#xff09; React Navigation 是 React Native 应用中最常用的导航库之一&#xff0c;它提供了多种导航模式&#xff0c;如堆栈导航&#xff08;Stack Navigator&#xff09;、标签导航&#xff08;Tab Navigator&#xff09;和抽屉…...

2.Vue编写一个app

1.src中重要的组成 1.1main.ts // 引入createApp用于创建应用 import { createApp } from "vue"; // 引用App根组件 import App from ./App.vue;createApp(App).mount(#app)1.2 App.vue 其中要写三种标签 <template> <!--html--> </template>…...

什么是库存周转?如何用进销存系统提高库存周转率?

你可能听说过这样一句话&#xff1a; “利润不是赚出来的&#xff0c;是管出来的。” 尤其是在制造业、批发零售、电商这类“货堆成山”的行业&#xff0c;很多企业看着销售不错&#xff0c;账上却没钱、利润也不见了&#xff0c;一翻库存才发现&#xff1a; 一堆卖不动的旧货…...

IT供电系统绝缘监测及故障定位解决方案

随着新能源的快速发展&#xff0c;光伏电站、储能系统及充电设备已广泛应用于现代能源网络。在光伏领域&#xff0c;IT供电系统凭借其持续供电性好、安全性高等优势成为光伏首选&#xff0c;但在长期运行中&#xff0c;例如老化、潮湿、隐裂、机械损伤等问题会影响光伏板绝缘层…...

高防服务器能够抵御哪些网络攻击呢?

高防服务器作为一种有着高度防御能力的服务器&#xff0c;可以帮助网站应对分布式拒绝服务攻击&#xff0c;有效识别和清理一些恶意的网络流量&#xff0c;为用户提供安全且稳定的网络环境&#xff0c;那么&#xff0c;高防服务器一般都可以抵御哪些网络攻击呢&#xff1f;下面…...

自然语言处理——循环神经网络

自然语言处理——循环神经网络 循环神经网络应用到基于机器学习的自然语言处理任务序列到类别同步的序列到序列模式异步的序列到序列模式 参数学习和长程依赖问题基于门控的循环神经网络门控循环单元&#xff08;GRU&#xff09;长短期记忆神经网络&#xff08;LSTM&#xff09…...

【JavaWeb】Docker项目部署

引言 之前学习了Linux操作系统的常见命令&#xff0c;在Linux上安装软件&#xff0c;以及如何在Linux上部署一个单体项目&#xff0c;大多数同学都会有相同的感受&#xff0c;那就是麻烦。 核心体现在三点&#xff1a; 命令太多了&#xff0c;记不住 软件安装包名字复杂&…...

【Linux】Linux 系统默认的目录及作用说明

博主介绍&#xff1a;✌全网粉丝23W&#xff0c;CSDN博客专家、Java领域优质创作者&#xff0c;掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌ 技术范围&#xff1a;SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物…...

Chromium 136 编译指南 Windows篇:depot_tools 配置与源码获取(二)

引言 工欲善其事&#xff0c;必先利其器。在完成了 Visual Studio 2022 和 Windows SDK 的安装后&#xff0c;我们即将接触到 Chromium 开发生态中最核心的工具——depot_tools。这个由 Google 精心打造的工具集&#xff0c;就像是连接开发者与 Chromium 庞大代码库的智能桥梁…...

c# 局部函数 定义、功能与示例

C# 局部函数&#xff1a;定义、功能与示例 1. 定义与功能 局部函数&#xff08;Local Function&#xff09;是嵌套在另一个方法内部的私有方法&#xff0c;仅在包含它的方法内可见。 • 作用&#xff1a;封装仅用于当前方法的逻辑&#xff0c;避免污染类作用域&#xff0c;提升…...