【操作幂等和数据一致性】保障业务在MySQL和COS对象存储的一致
业务场景
- 发布信息,更新到数据库MySQL
- COS操作,更新JSON文件
不过可能存在幂等性和数据一致性的问题。
// 批量存MySQL
entityPublishService.saveOrUpdateBatch(entityPublishList);
// 遍历批量存COS对象存储searchEntitys.forEach(req -> {//删除旧的json文件this.cosFileClient.deleteFile(Constant.ResourcePath.RESOURCE_PATH + req.getId());ObjectMapper mapper = new ObjectMapper();String jsonString = null;try {jsonString = mapper.writeValueAsString(req);// 将 JSON 字符串转换为 InputStream 并上传InputStream inputStream = new ByteArrayInputStream(jsonString.getBytes());this.cosFileClient.uploadFile(Constant.ResourcePath.RESOURCE_PATH + req.getId(), inputStream);} catch (Exception e) {throw new RuntimeException(e);}});
数据一致性与幂等
- 幂等性指的是无论操作执行多少次,结果都一致。
比如,如果这段代码被重复执行,应该不会导致数据错误或重复上传。 - 数据一致性则要确保数据库和COS中的JSON文件状态一致,
比如更新数据库后,必须成功上传新的JSON,否则应该回滚或处理失败情况。
业务潜在问题
当前的代码在保存或更新数据库后,遍历entitys,删除旧的JSON,然后生成新的并上传。这里有几个潜在的问题:
-
数据库操作和文件操作之间没有事务管理,如果上传文件失败,数据库已经提交了事务,导致数据不一致。
-
删除旧文件后,如果上传新文件失败,会导致数据丢失。
-
如果方法被重复调用,可能导致多次上传或删除,不幂等。
寻找解决方案
-
可能的解决方案是,将数据库的保存操作拆分为每个实体的单独操作,并在每个实体处理时,先上传文件,再更新数据库。这样,每个实体的处理是原子性的:上传文件成功,然后更新数据库。如果上传失败,数据库不更新。但这样会影响性能,因为批量操作变为单个操作。
-
为了数据一致性,可能需要在上传失败时,提供某种回滚机制,比如删除已更新的数据库记录。但这在批量操作中较为困难。
因此可能需要业务层面的处理,比如标记记录为待定状态,或者记录操作日志,用于后续的补偿。 -
正确的顺序应该是先保存数据库,再上传文件,这样即使上传失败,数据库已经更新,但文件未更新,其他系统可能无法获取最新数据,但至少数据库是正确的,可以触发后续的修复机制。
后续修复或补偿机制,比如在RabbitMQ消费者中业务,配置重试机制。人工操作记录人工补偿机制
为了确保操作的幂等性和数据一致性,尤其是批量操作,代码改进:
- 移除不必要的旧文件删除操作:直接通过覆盖上传实现更新,避免删除后上传失败导致的数据丢失。
- 添加上传重试机制:提高上传成功率,减少因临时问题导致的失败。
- 异常处理和事务分离:确保数据库操作后尽可能完成文件上传,若失败则通过异常通知上层逻辑处理。
// 批量存储MySQL
entityPublishService.saveOrUpdateBatch(entityPublishList);// 遍历批量对象存储COS
entitys.forEach(req -> {ObjectMapper mapper = new ObjectMapper();String jsonString;InputStream inputStream = null;final int maxRetries = 3;int retryCount = 0;boolean uploaded = false;while (retryCount < maxRetries && !uploaded) {try {// 序列化JSON数据jsonString = mapper.writeValueAsString(req);inputStream = new ByteArrayInputStream(jsonString.getBytes(StandardCharsets.UTF_8));// 幂等上传(覆盖模式)this.cosFileClient.uploadFile(Constant.ResourcePath.RESOURCE_PATH + req.getId(), inputStream);uploaded = true; // 标记上传成功} catch (JsonProcessingException e) {// JSON序列化失败,无需重试throw new RuntimeException("JSON序列化失败,ID: " + req.getId(), e);} catch (Exception e) {retryCount++;if (retryCount >= maxRetries) {throw new RuntimeException("文件上传失败,超过最大重试次数,ID: " + req.getId(), e);}// 指数退避等待try {Thread.sleep(1000 * retryCount);} catch (InterruptedException ie) {Thread.currentThread().interrupt();throw new RuntimeException("上传操作被中断,ID: " + req.getId(), ie);}} finally {if (inputStream != null) {try {inputStream.close();} catch (IOException e) {// 日志记录关闭异常,但不影响主流程}}}}if (!uploaded) {// 此处可根据业务需要记录失败状态或触发补偿机制throw new RuntimeException("上传未完成,ID: " + req.getId());}
});
改进说明:
-
幂等性保障:
- 覆盖上传:直接调用
uploadFile
覆盖同名文件,多次执行结果一致。 - 数据库操作:
saveOrUpdateBatch
本身应设计为幂等(如使用唯一约束或主键更新)。
- 覆盖上传:直接调用
-
数据一致性措施:
- 先持久化数据库:确保数据库更新后再同步文件,符合业务逻辑依赖。
- 重试机制:通过最多3次重试(含退避等待),减少网络抖动等临时问题的影响。
- 异常处理:上传失败时抛出异常,通知调用方处理(如日志记录、告警、人工干预或事务补偿)。
-
异常情况处理:
- 序列化错误:直接终止,无需重试(数据问题需修复)。
- 上传失败:重试后仍失败则向上抛出,由系统统一处理(如标记数据状态、异步任务修复)。
注意事项:
- 若业务允许最终一致性,可考虑将上传失败记录至持久化队列,由后台任务异步重试。
- 数据库设计可增加
lastUpdateTime
字段,确保重复提交时数据版本一致。 - 监控上传失败异常,及时处理以保证系统健康度。
相关文章:
【操作幂等和数据一致性】保障业务在MySQL和COS对象存储的一致
业务场景 发布信息,更新到数据库MySQLCOS操作,更新JSON文件 不过可能存在幂等性和数据一致性的问题。 // 批量存MySQL entityPublishService.saveOrUpdateBatch(entityPublishList); // 遍历批量存COS对象存储searchEntitys.forEach(req -> {//删除…...
[答疑]领域建模:邓丽君、周杰伦和少女时代
DDD领域驱动设计批评文集 做强化自测题获得“软件方法建模师”称号 《软件方法》各章合集 第五元素 2025-2-18 17:12 潘老师,画线的这句话,在这个类图中怎么体现呢? (回答者补注:问题的素材来自《邓丽君的领域建模》…...
【鸿蒙开发】第四十三章 Notification Kit(用户通知服务)
目录 1 简介 1.1 使用场景 1.2 能力范围 1.3 业务流程 1.4 通知样式 1.5 约束限制 1.6 与相关Kit的关系 2 请求通知授权 2.1 接口说明 2.2 开发步骤 3 管理通知角标 3.1 接口说明 3.2 开发步骤 4 管理通知渠道 4.1 通知渠道类型说明 4.2 接口说明…...
Ubuntu 20.04源码安装opencv 4.5.0
安装依赖项 sudo apt install -y g sudo apt install -y cmake sudo apt install -y make sudo apt install -y wget unzip安装opencv依赖库 sudo apt-get install build-essential libgtk2.0-dev libgtk-3-dev libavcodec-dev libavformat-dev libjpeg-dev libswscale-dev l…...
buu-get_started_3dsctf_2016-好久不见39
栈溢出外平栈 1外平栈与内平栈的区别 外平栈: 栈帧的局部变量和返回地址之间没有额外的对齐或填充。返回地址直接位于局部变量的上方(即栈顶方向)。在计算偏移时,不需要额外加 4(因为返回地址紧邻局部变量)…...
一周学会Flask3 Python Web开发-客户端状态信息Cookie以及加密
锋哥原创的Flask3 Python Web开发 Flask3视频教程: 2025版 Flask3 Python web开发 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili HTTP是无状态(stateless)协议。也就是说,在一次请求响应结束后,服务器不会留下任何关于对…...
深入解析Qt事件循环
在Qt开发中,QApplication::exec()这行代码是每个开发者都熟悉的“魔法咒语”。为什么GUI程序必须调用它才能响应操作?为何耗时操作会导致界面冻结?本文将以事件循环为核心,揭示Qt高效运转的底层逻辑,探讨其设计哲学与最…...
python中的异常-模块-包
文章目录 异常异常的定义异常捕获语法捕获常规异常捕获指定异常捕获多个异常捕获所有异常异常else异常finally 异常传递总结 模块概念导入自定义模块及导入main方法all变量 总结 包自定义包定义pycharm中建包的基本步骤导入方式 第三方包 异常 异常的定义 当检测到一个错误时…...
AI 百炼成神:线性回归,预测房价
我们开始第一个项目——线性回归:预测房价。这是一个经典的机器学习入门项目,可以帮助你理解如何使用线性回归模型来预测连续的数值。 第一个项目:线性回归预测房价 项目目标 学习线性回归的基本概念。使用历史房价数据建立一个预测模型。理解如何评估模型的性能。项目步骤…...
Grok-3 与 DeepSeek 的技术架构与性能分析
随着 AI 大模型技术的快速发展,Grok-3(xAI)与 DeepSeek-V3/R1(深度求索)成为近期备受关注的焦点。本文将从技术架构、性能表现、成本效率和应用场景等维度,深入对比分析这两大模型的优劣势。 一、技术架构对比 1. DeepSeek-V3/R1:高效 MoE 架构与工程优化 混合专家模型…...
机器学习实战(4):逻辑回归——分类问题的基础
第4集:逻辑回归——分类问题的基础 在机器学习中,逻辑回归(Logistic Regression) 是解决分类问题的经典算法之一。尽管名字中有“回归”,但它实际上是一种分类模型,广泛应用于二分类任务(如垃圾…...
我是如何从 0 到 1 找到 Web3 工作的?
作者:Lotus的人生实验 关于我花了一个月的时间,从 0 到 1 学习 Web3 相关的知识和编程知识。然后找到了一个 Web3 创业公司实习的远程工作。 👇👇👇 我的背景: 计算机科班,学历还可以(大厂门槛水平) 毕业工…...
基于WebRTC与AI大模型接入EasyRTC:打造轻量级、高实时、强互动的嵌入式音视频解决方案
随着物联网和嵌入式技术的快速发展,嵌入式设备对实时音视频通信的需求日益增长。然而,传统的音视频解决方案往往存在体积庞大、实时性差、互动体验不佳等问题,难以满足嵌入式设备的资源限制和应用场景需求。 针对以上痛点,本文将介…...
【DeepSeek】本地部署,保姆级教程
deepseek网站链接传送门:DeepSeek 在这里主要介绍DeepSeek的两种部署方法,一种是调用API,一种是本地部署。 一、API调用 1.进入网址Cherry Studio - 全能的AI助手选择立即下载 2.安装时位置建议放在其他盘,不要放c盘 3.进入软件后…...
Java 大视界 -- 国际竞争与合作:Java 大数据在全球市场的机遇与挑战(94)
💖亲爱的朋友们,热烈欢迎来到 青云交的博客!能与诸位在此相逢,我倍感荣幸。在这飞速更迭的时代,我们都渴望一方心灵净土,而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识,也…...
流程绩效分析,实现销售目标的保障
在当今竞争激烈的商业环境里,客户关系管理(CRM)行业正迎来深刻变革。企业若想在市场中脱颖而出,实现业务的持续增长,流程绩效分析成为关键。通过提供销售全流程绩效分析能力,企业能够针对销售全流程的复杂业…...
Linux NFS
Linux NFS NFS(Network File System)是一种用于在网络上共享文件系统的协议,允许不同的计算机通过网络访问和共享文件,就像访问本地文件一样。它广泛应用于 Linux 和 UNIX 系统中,支持多用户并发访问,适合…...
一文精通JWT Token、ID Token、Access Token、Refresh Token
JWT Token JSON Web Token (JWT,RFC 7519 (opens new window)),是为了在网络应用环境间传递声明而执行的一种基于 JSON 的开放标准((RFC 7519)。该 token 被设计为紧凑且安全的,特别适用于分布式站点的单点登录(SSO)场景。JWT 的声明一般被用来在身份提供者和服务提供者…...
CSS基础(浮动、相对定位、绝对定位、固定定位、粘性定位、版心、重置默认样式)
文章目录 1. 浮动(float)1.1 简介1.2 元素浮动后的特点1.3 脱离文档流示例图1.4 浮动产生的影响1.4.1 积极影响1.4.2 消极影响 1.5 解决浮动产生的影响1.5.1 清除浮动(Clearfix)1.5.2 创建新的块格式化上下文(BFC&…...
uniapp中引入Vant Weapp的保姆级教学(包含错误处理)
废话不多说,直接上方法,网上的教学好多都是错误的 1.安装vant weapp 在Hbuilder的终端,输入以下代码 npm install vant/weapp -S --production 2.新建wxcomponents文件夹 在项目的跟目录新建一个“wxcomponents’文件夹,与app.…...
Datawhale Ollama教程笔记5
Dify 接入 Ollama 部署的本地模型 Dify 支持接入 Ollama 部署的大型语言模型推理和 embedding 能力。 快速接入 下载 Ollama 访问 Ollama 安装与配置,查看 Ollama 本地部署教程。 运行 Ollama 并与 Llama 聊天 ollama run llama3.1Copy to clipboardErrorCopied …...
STL —— 洛谷字符串(string库)入门题(蓝桥杯题目训练)(二)
目录 一、B2121 最长最短单词 - 洛谷 算法代码: 代码分析 变量定义 输入处理 单词长度计算 更新最长和最短单词的长度 输出最长单词 输出最短单词 评测记录:编辑 二、B2122 单词翻转 - 洛谷 算法代码: 代码分析 引入头文件和定…...
P1055 [NOIP 2008 普及组] ISBN 号码(java)【AC代码】
每一本正式出版的图书都有一个 ISBN 号码与之对应,ISBN 码包括 9 位数字、1 位识别码和 3 位分隔符,其规定格式如 x-xxx-xxxxx-x,其中符号 - 就是分隔符(键盘上的减号),最后一位是识别码,例如 0…...
JavaScript如何创建一个对象?对象字面量和构造函数创建对象有什么区别?
JavaScript如何创建一个对象?对象字面量和构造函数创建对象有什么区别? JavaScript 创建对象的方式 在 JavaScript 中,有多种方式可以创建对象,这里主要介绍对象字面量和构造函数这两种常见的方式。 1. 对象字面量 对象字面量…...
【量化科普】Sharpe Ratio,夏普比率
【量化科普】Sharpe Ratio,夏普比率 🚀🚀🚀量化软件开通🚀🚀🚀 🚀🚀🚀量化实战教程🚀🚀🚀 在量化投资领域,…...
知识蒸馏知识点
1基于kl散度计算,学生模型需要用log_softmax处理 2 为了避免温度对梯度的影响,loss*T**2 操作目的教师 / 学生输出除以 软化概率分布,暴露类别间关系损失乘以 抵消温度对梯度的缩放,维持梯度量级稳定,确保训练收敛性 import torch import torch.nn.functional as F# 原…...
Springboot + Ollama + IDEA + DeepSeek 搭建本地deepseek简单调用示例
1. 版本说明 springboot 版本 3.3.8 Java 版本 17 spring-ai 版本 1.0.0-M5 deepseek 模型 deepseek-r1:7b 需要注意一下Ollama的使用版本: 2. springboot项目搭建 可以集成在自己的项目里,也可以到 spring.io 生成一个项目 生成的话,如下…...
【MySQL】MySQL表的增删改查(进阶)
1.❤️❤️前言~🥳🎉🎉🎉 Hello, Hello~ 亲爱的朋友们👋👋,这里是E绵绵呀✍️✍️。 如果你喜欢这篇文章,请别吝啬你的点赞❤️❤️和收藏📖📖。如果你对我的…...
装修流程图: 装修前准备 → 设计阶段 → 施工阶段 → 安装阶段 → 收尾阶段 → 入住
文章目录 引言I 毛坯房装修的全流程**1. 装修前准备****1.1 确定装修预算****1.2 选择装修方式****1.3 选择装修公司****1.4 办理装修手续****2. 设计阶段****2.1 量房****2.2 设计方案****2.3 确认方案****3. 施工阶段****3.1 主体拆改****3.2 水电改造****3.3 防水工程****3.…...
JavaScript系列(79)--Web Worker 高级应用
Web Worker 高级应用 🔄 Web Worker 为JavaScript提供了真正的多线程能力,让我们能够在后台线程中执行复杂的计算而不阻塞主线程。今天让我们深入探讨Web Worker的高级应用。 Web Worker 概述 🌟 💡 小知识:Web Work…...
人工智能之自动驾驶技术体系
自动驾驶技术体系 自动驾驶技术是人工智能在交通领域的重要应用,旨在通过计算机视觉、传感器融合、路径规划等技术实现车辆的自主驾驶。自动驾驶不仅能够提高交通效率,还能减少交通事故和环境污染。本文将深入探讨自动驾驶的技术体系,包括感…...
该如何搭建高效的跨境网络专线?
在如今这个全球化的商业环境中,跨境网络专线成为了企业与个人实现高效、安全跨国通信的重要工具。大家好,在接下来的内容中,我将深入为您探讨跨境网络专线的概念、特点以及搭建流程,帮助您更好地理解和利用这一技术。 一、什么是…...
网络运维学习笔记 017HCIA-Datacom综合实验01
文章目录 综合实验1实验需求总部特性 分支8分支9 配置一、 基本配置(IP二层VLAN链路聚合)ACC_SWSW-S1SW-S2SW-Ser1SW-CoreSW8SW9DHCPISPGW 二、 单臂路由GW 三、 vlanifSW8SW9 四、 OSPFSW8SW9GW 五、 DHCPDHCPGW 六、 NAT缺省路由GW 七、 HTTPGW 综合实…...
Redis数据结构-String字符串
1.String字符串 字符串类型是Redis中最基础的数据结构,关于数据结构与要特别注意的是:首先Redis中所有的键的类型都是字符串类型,而且其他集中数据结构也都是在字符串类似基础上进行构建,例如列表和集合的元素类型是字符串类型&a…...
个人简历html网页模板,科技感炫酷html简历模板
炫酷动效登录页 引言 在网页设计中,按钮是用户交互的重要元素之一。这样一款黑色个人简历html网页模板,科技感炫酷html简历模板,设计效果类似科技看板图,可帮您展示技能、任职经历、作品等,喜欢这种风格的小伙伴不要犹豫哦。该素材呈现了数据符号排版显示出人形的动画效…...
【Python爬虫(39)】掌控全局:分布式爬虫的任务管理与监控之道
【Python爬虫】专栏简介:本专栏是 Python 爬虫领域的集大成之作,共 100 章节。从 Python 基础语法、爬虫入门知识讲起,深入探讨反爬虫、多线程、分布式等进阶技术。以大量实例为支撑,覆盖网页、图片、音频等各类数据爬取ÿ…...
输入框元素覆盖冲突
后端响应中的 "trainingKbGroupName": "基础死型" 通过searchForm2.initFormData(rowData[0]);操作会把基础死型四个字填充到<div class"col-sm-5 form-group"> <label class"col-sm-3 control-label">知识点分组名称<…...
R语言学习笔记——确定指标权重:层次分析法/熵权法/CRITIC方法
本文介绍使用R语言确定指标权重的方法,包括:层次分析法、熵权法和CRITIC方法,内容包含了逆向指标正向化处理。 1、层次分析法 #######层次分析法###### ###几何平均法求权重 options(digits 2) library(tidyverse)macro <- tibble(x1c(…...
前端面试之Box盒子布局:核心知识与实战解析
目录 引言:布局能力决定前端高度 一、盒模型基础:看得见的像素战争 1. 标准盒模型 vs IE盒模型 2. 核心组成公式 3. 视觉格式化模型 二、传统布局三剑客 1. 浮动布局(Float Layout) 2. 定位布局(Position Layou…...
前端VUE+后端uwsgi 环境搭建
1整体架构 请求流程the web clinet--the web server->the socket->uwsgi--django 第一级的nginx并不是必须的,uwsgi完全可以完成整个的和浏览器交互的流程;在nginx上加上安全性或其他的限制,可以达到保护程序的作用;uWSGI本…...
保姆级! 本地部署DeepSeek-R1大模型 安装Ollama Api 后,Postman本地调用 deepseek
要在Postman中访问Ollama API并调用DeepSeek模型,你需要遵循以下步骤。首先,确保你有一个有效的Ollama服务器实例运行中,并且DeepSeek模型已经被加载。 可以参考我的这篇博客 保姆级!使用Ollama本地部署DeepSeek-R1大模型 并java…...
【python】pip命令合集
文章目录 1. 包安装与卸载2. 依赖管理与文件操作3. 包下载与构建4. 配置与缓存管理5. 高级调试与日志6. 虚拟环境集成7. 哈希验证与安全8. 实验性功能(可能不稳定)9. 其他实用命令参数大全(全局常用参数)示例场景 conda: 【python…...
【鸿蒙开发】第四十章 Form Kit(卡片开发服务)
目录 1 概述 1.1 卡片使用场景 1.2 服务卡片架构 1.3 亮点/特征 1.4 开发模式 1.5 与相关Kit的关系 1.6 约束限制 2 ArkTS卡片运行机制 2.1 实现原理 2.2 ArkTS卡片的优势 2.3 ArkTS卡片的约束 3 ArkTS卡片相关模块 4 ArkTS卡片开发指导 4.1 创建一个ArkTS卡片 …...
汽车自动驾驶辅助L2++是什么?
自动驾驶辅助级别有哪些? 依照SAE(SAE International,Society of Automotive Engineers国际自动机工程师学会)的标准,大致划分为6级(L0-L5): L0人工驾驶:即没有驾驶辅助…...
微信小程序消息推送解密
package com.test.main.b2b;import org.apache.commons.codec.binary.Base64;import javax.crypto.Cipher; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import java.util.Arrays;/*** author * version 1.0* description: 解谜微信小…...
java项目之城市公园信息管理系统的设计与实现(源码+文档)
风定落花生,歌声逐流水,大家好我是风歌,混迹在java圈的辛苦码农。今天要和大家聊的是一款基于ssm的城市公园信息管理系统的设计与实现。项目源码以及部署相关请联系风歌,文末附上联系信息 。 项目简介: 城市公园信息…...
EasyRTC:基于WebRTC与P2P技术,开启智能硬件音视频交互的全新时代
在数字化浪潮的席卷下,智能硬件已成为我们日常生活的重要组成部分,从智能家居到智能穿戴,从工业物联网到远程协作,设备间的互联互通已成为不可或缺的趋势。然而,高效、低延迟且稳定的音视频交互一直是智能硬件领域亟待…...
【前端框架】vue2和vue3的区别详细介绍
Vue 3 作为 Vue 2 的迭代版本,在性能、语法、架构设计等多个维度均有显著的变革与优化。以下详细剖析二者的区别: 响应式系统 Vue 2 实现原理:基于 Object.defineProperty() 方法实现响应式。当一个 Vue 实例创建时,Vue 会遍历…...
23.1 WebBrowser控件
版权声明:本文为博主原创文章,转载请在显著位置标明本文出处以及作者网名,未经作者允许不得用于商业目的。 WebBrowser控件类似于IE浏览器的文档界面(事实上IE也是使用的这个控件),它提供了显示网页及支持…...
从0-1搭建mac环境最新版
从0-1搭建mac环境 先查看自己的芯片信息 bash uname -mbash-3.2$ uname -m arm64这里是自己的型号安装brew xcode-select --install xcode-select -p /bin/zsh -c “$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)” source /Users/lanren/.…...