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

spring重试机制

数据库死锁处理与重试机制实现指南

1. 业务场景

1.1 问题现象

  • 高并发批量数据处理时频繁出现数据库死锁
  • 主要发生在"先删除历史数据,再重新计算"的业务流程中
  • 原有逐条处理方式:list.forEach(item -> { delete(); calculate(); })

1.2 死锁原因分析

  • 锁竞争:多个线程同时对相同数据进行删除和插入操作
  • 事务时间过长:删除和计算在同一事务中,持锁时间长
  • 锁升级:行锁升级为表锁,增加死锁概率

2. 改造步骤

2.1 添加依赖

pom.xml 中添加Spring Retry相关依赖:

<dependency><groupId>org.springframework.retry</groupId><artifactId>spring-retry</artifactId>
</dependency>
<dependency><groupId>org.springframework</groupId><artifactId>spring-aspects</artifactId>
</dependency>

2.2 创建重试配置类

@Configuration
@EnableRetry
public class RetryConfig {@Beanpublic RetryTemplate retryTemplate() {RetryTemplate retryTemplate = new RetryTemplate();// 重试策略:最多重试3次SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy();retryPolicy.setMaxAttempts(3);retryTemplate.setRetryPolicy(retryPolicy);// 退避策略:指数退避,初始延迟1秒ExponentialBackOffPolicy backOffPolicy = new ExponentialBackOffPolicy();backOffPolicy.setInitialInterval(1000);backOffPolicy.setMultiplier(2.0);backOffPolicy.setMaxInterval(5000);retryTemplate.setBackOffPolicy(backOffPolicy);return retryTemplate;}
}

2.3 启用重试机制

在主应用类上添加 @EnableRetry 注解:

@EnableRetry
@SpringBootApplication
public class Application {public static void main(String[] args) {SpringApplication.run(Application.class, args);}
}

2.4 改造核心处理逻辑

改造前(容易死锁):
public void processData(List<DataDto> list, QueryParam param) {// 逐条处理:删除 + 计算list.forEach(item -> {deleteRelatedData(item.getId());  // 单条删除calculateData(item);              // 单条计算});
}
改造后(两阶段处理):
public void processData(List<DataDto> list, QueryParam param) {if (CollectionUtils.isEmpty(list)) {return;}// 第一阶段:范围删除(有重试机制)deleteDataByRange(param.getType(), param.getCategory(), param.getStartTime(), param.getEndTime(), param.getTempId());// 第二阶段:批量计算(纯计算,无删除操作)for (DataDto item : list) {calculateData(item);}
}

2.5 在关键方法上添加重试注解

@Retryable(value = {DeadlockLoserDataAccessException.class, DataAccessException.class},maxAttempts = 3,backoff = @Backoff(delay = 1000, multiplier = 2, maxDelay = 5000)
)
public void deleteDataByRange(String type, String category, LocalDateTime startTime, LocalDateTime endTime, String tempId) {log.info("开始范围删除数据:type={}, category={}", type, category);dataMapper.deleteByRange(type, category, startTime, endTime, tempId);log.info("范围删除完成");
}@Recover
public void recoverFromDeadlock(Exception ex, String type, String category,LocalDateTime startTime, LocalDateTime endTime, String tempId) {log.error("删除数据重试失败,最终放弃。参数:type={}, category={}", type, category, ex);throw new BusinessException("数据删除失败,请稍后重试");
}

2.6 移除冗余删除操作

检查并移除业务流程中的冗余删除调用:

public void businessProcess(ProcessParam param) {// 移除冗余的删除调用// deleteRelatedData(param);  // 删除这行// 保留必要的删除操作deleteSpecificTypeData(param);// 业务计算逻辑processBusinessLogic(param);
}

3. 关键改造点总结

3.1 核心改造思路

  1. 分离删除和计算:避免在同一循环中进行删除和计算
  2. 范围删除替代逐条删除:减少数据库操作次数和锁竞争
  3. 添加重试机制:对不可避免的死锁进行自动重试
  4. 清理冗余操作:移除不必要的删除调用

3.2 改造前后对比

改造前改造后
逐条删除 + 计算范围删除 + 批量计算
长事务持锁短事务快速释放锁
无重试机制自动重试死锁异常
多处冗余删除精简删除操作

3.3 效果验证

  • 死锁发生频率显著降低
  • 数据处理性能提升
  • 系统稳定性增强
  • 无数据丢失问题

4. 注意事项

4.1 重试配置要点

  • 只对特定异常类型重试(如死锁异常)
  • 设置合理的重试次数和间隔
  • 必须提供 @Recover 方法处理最终失败

4.2 两阶段处理要点

  • 确保删除和计算之间没有其他操作干扰
  • 删除操作要支持范围查询
  • 计算逻辑要保证幂等性

4.3 数据一致性保证

  • 关键保存操作不能遗漏
  • 事务边界要合理设置
  • 必要时使用分布式锁

相关文章:

spring重试机制

数据库死锁处理与重试机制实现指南 1. 业务场景 1.1 问题现象 高并发批量数据处理时频繁出现数据库死锁主要发生在"先删除历史数据&#xff0c;再重新计算"的业务流程中原有逐条处理方式&#xff1a;list.forEach(item -> { delete(); calculate(); }) 1.2 死…...

C语言的全称:(25/6/6)

C语言&#xff0c;全称为"C Programming Language"&#xff08;C程序设计语言&#xff09;&#xff0c;是一种广泛使用的计算机编程语言。它是由Dennis Ritchie于1972年在贝尔实验室设计的&#xff0c;继承了B语言的许多思想&#xff0c;并加入了数据类型的概念及其他…...

智能制造数字孪生全要素交付一张网:智造中枢,孪生领航,共建智造生态共同体

在制造业转型升级的浪潮中&#xff0c;数字孪生技术正成为推动行业变革的核心引擎。从特斯拉通过数字孪生体实现车辆全生命周期优化&#xff0c;到海尔卡奥斯工业互联网平台赋能千行百业&#xff0c;数字孪生技术已从概念验证走向规模化落地。通过构建覆盖全国的交付网络&#…...

stylus - 新生代CSS预处理框架

stylus是什么 Stylus 是一种 CSS 预处理器&#xff0c;它扩展了 CSS 的功能&#xff0c;使得编写样式变得更简洁和高效。Stylus 允许使用嵌套、变量、混入等编程功能&#xff0c;这些功能可以极大地提高开发效率和代码的可维护性。 stylus中文文档 https://stylus.uihtm.co…...

python八股文算法:三数之和

双指针解法&#xff1a; 原理见注释 # 2025/6/6 9:40 # -*- coding:UTF-8 -*- nums [-1, 0, 1,1, 2, -1, -4,0,2,1,-3,4,10,-9] def three_sum(nums):nums.sort()n len(nums)result []for i in range(n-2):# n-2&#xff0c;此时i取值到n-2-1&#xff0c;即倒数第3个数&…...

HttpServletRequest常用方法

方法说明示例String getMethod()获取请求的 HTTP 方法&#xff08;如 GET、POST 等&#xff09;。request.getMethod() 返回 "GET"String getRequestURI()获取请求的 URI&#xff08;路径部分&#xff0c;不包括域名和协议&#xff09;。请求 http://localhost:8080/…...

BugKu Web渗透之网站被hei(仅仅是ctf题目名称)

启动场景&#xff0c;打开网页&#xff0c;显示如下&#xff1a; 目前没有看出任何异常。 步骤一&#xff1a; 右键查看源代码。源代码较多&#xff0c;也没发现异常。 步骤二&#xff1a; 用dirsearch扫描网站目录。 如图&#xff1a; 看起来shell.php很可疑。 步骤三&…...

群论在现代密码学中的应用探索与实践 —— 从理论到C语言实现

1. 引言&#xff1a;数字时代的信息安全挑战 随着互联网和数字技术的快速发展&#xff0c;信息安全问题变得日益严峻。无论是个人隐私保护&#xff0c;还是企业数据安全&#xff0c;乃至国家安全&#xff0c;都依赖于有效的加密技术保障信息的机密性和完整性。网络攻击、数据泄…...

深入理解MySQL死锁:从原理、案例到解决方案

一、MySQL死锁的概念与定义 1. 死锁的基本定义 MySQL中的死锁是指两个或多个事务在同一资源上相互等待对方释放锁&#xff0c;导致这些事务都无法继续执行的情况。从本质上讲&#xff0c;死锁是多个事务形成了一个等待环路&#xff0c;每个事务都在等待另一个事务所持有的锁资…...

关于华为仓颉编程语言

文章目录 一、基本概况二、技术特点1. 多范式编程2. 原生智能化3. 高性能与安全4. 全场景兼容 三、编译器与开发工具四、语言相似性对比五、行业应用实例总结 最近经常看到这个东西&#xff0c;于是搜了一下&#xff0c;整理了一些内容&#xff0c;水一篇&#xff0c;以后慢慢研…...

无字母数字webshell的命令执行

在Web安全领域&#xff0c;WebShell是一种常见的攻击手段&#xff0c;通过它攻击者可以远程执行服务器上的命令&#xff0c;获取敏感信息或控制系统。而无字母数字WebShell则是其中一种特殊形式&#xff0c;通过避免使用字母和数字字符&#xff0c;来绕过某些安全机制的检测。 …...

Spring AI 项目实战(五):Spring Boot + AI + DeepSeek + Redis 实现聊天应用上下文记忆功能(附完整源码)

系列文章 序号文章名称1Spring AI 项目实战(一):Spring AI 核心模块入门2Spring AI 项目实战(二):Spring Boot + AI + DeepSeek 深度实战(附完整源码)3Spring AI 项目实战(三):Spring Boot + AI + DeepSeek 打造智能客服系统(附完整源码)4Spring AI 项目实战(四…...

【华为云Astro-服务编排】服务编排使用全攻略

目录 概述 为什么使用服务编排 服务编排基本能力 拖拉拽式编排流程 逻辑处理 对象处理 服务单元组合脚本、原生服务、BO、第三方服务 服务编排与模块间调用关系 脚本 对象 标准页面 BPM API接口 BO 连接器 如何创建服务编排 创建服务编排 如何开发服务编排 服…...

解决el-select选择框右侧下拉箭头遮挡文字问题

如图所示&#xff1a; el-select长度较短的时候&#xff0c;选择框右侧下拉箭头会遮挡选中的数据 选中数据被遮挡 解决办法&#xff1a; 组件如下&#xff1a; <td class"fmtd" :colspan"col.ptproCupNum" v-for"col in row" :key"…...

20250603在荣品的PRO-RK3566开发板的Android13下的使用命令行来查看RK3566的温度【显示优化版本】

20250603在荣品的PRO-RK3566开发板的Android13下的使用命令行来查看RK3566的温度【显示优化版本】 2025/6/3 11:58 RK3566的cpu运行效率 top busybox top rk3566_t:/ # rk3566_t:/ # rk3566_t:/ # cd /sys/class/thermal/ rk3566_t:/sys/class/thermal # ls -l rk3566_t:/sys/c…...

C语言字符数组初始化的5种方法(附带实例)

所谓初始化&#xff0c;就是在定义的同时进行赋值。 C语言中&#xff0c;初始化字符数组的方式多样&#xff0c;每种方式都有其特定的用途和优势。 1、使用字符串字面量初始化 最常见和简洁的初始化方式是使用字符串字面量。在这种方法中&#xff0c;我们直接将一个用双引号…...

npm run dev 报错:Error: error:0308010C:digital envelope routines::unsupported

npm run dev时报错如下 原因&#xff1a;更换node版本导致 解决&#xff1a; 修改package.json文件&#xff0c;在相关构建命令之前加入 SET NODE_OPTIONS–openssl-legacy-provider 运行成功...

模板方法模式:优雅封装不变,灵活扩展可变

引言:代码复用与扩展的艺术 在日常开发中,我们常遇到核心流程固定但某些步骤需差异化的场景。例如: 数据库操作的通用流程(连接→执行→关闭)HTTP请求的固定步骤(构建请求→发送→解析响应)报表生成的骨架(数据获取→格式转换→输出)模板方法模式正是为解决这类问题而…...

基于LLaMA-Factory和Easy Dataset的Qwen3微调实战:从数据准备到LoRA微调推理评估的全流程指南

随着开源大模型如 LLaMA、Qwen 和 Baichuan 的广泛应用&#xff0c;其基于通用数据的训练方式在特定下游任务和垂直领域中的表现仍存在提升空间&#xff0c;因此衍生出针对具体场景的微调训练需求。这些训练涵盖预训练&#xff08;PT&#xff09;、指令微调&#xff08;SFT&…...

6.6本日总结

一、英语 复习默写list9list20 二、数学 学习线代第一讲&#xff0c;订正13讲1000题&#xff0c;写15讲课后题 三、408 学习计组2.2&#xff0c;写计组习题 四、总结 单词再背完一遍后背阅读词&#xff0c;未处理的习题堆积过多要及时处理 五、明日计划 英语&#xff…...

idea中 maven 本地仓库有jar包,但还是找不到,解决打包失败和无法引用的问题

1、删除本地仓库中的文件 进入本地仓库对应jar包文件目录中删除_remote.repositories文件和结尾为.lastUpdated的文件 2、回到IDEA刷新Maven 3、查看之前引用不了的jar是否引入成功...

安全编码规范与标准:对比与分析及应用案例

在软件开发领域&#xff0c;尤其是涉及安全关键系统的开发中&#xff0c;遵循编码规范和标准是确保软件质量和安全性的重要手段。除了CERT C、CERT Java和MISRA外&#xff0c;还有其他多个与安全相关的编码规范和标准&#xff0c;以下是一些主要标准的对比说明&#xff1a; 一…...

(33)课54--??:3 张表的 join-on 连接举例,多表查询总结。

&#xff08;112&#xff09;3 张表的 join-on 连接举例 &#xff1a; &#xff08;113&#xff09; 多表查询总结 &#xff1a; &#xff08;114&#xff09;事务 &#xff1a; &#xff08;115&#xff09; &#xff08;116&#xff09; &#xff08;117&#xff09; …...

集群与分布式与微服务

1.集群和分布式 1.1 集群是个物理形态&#xff0c;分布式是个工作方式 分布式&#xff1a;一个业务分拆多个子业务&#xff08;节点&#xff09;&#xff0c;部署在不同的服务器上集群&#xff1a;同一个业务&#xff0c;部署在多个服务器上 1&#xff09;分布式是指将不同的…...

8.axios Http网络请求库(1)

一句话总结 Axios 是一个基于 Promise 的 HTTP 客户端&#xff0c;用于浏览器和 Node.js&#xff0c;帮助你轻松发送请求、接收响应。 Axios is a Promise-based HTTP client for the browser and Node.js, making it easy to send requests and handle responses. &#x1…...

Python爬虫实战:研究mechanize库相关技术

1. 引言 随着互联网数据量的爆炸式增长,网络爬虫已成为数据采集和信息挖掘的重要工具。Python 作为一种功能强大且易于学习的编程语言,拥有丰富的爬虫相关库,如 Requests、BeautifulSoup、Scrapy 等。Mechanize 库作为其中的一员,特别擅长处理复杂的表单提交和会话管理,为…...

c++算法学习5——贪心算法

一、贪心算法的原理 贪心算法&#xff08;Greedy Algorithm&#xff09;是一种在每一步选择中都采取当前最优决策的策略&#xff0c;通过局部最优解的累积逼近全局最优解。其核心思想是“着眼当前&#xff0c;忽略整体”&#xff0c;适用于满足​​最优子结构​​和​​贪心选…...

SpringCloud学习笔记-3

声明&#xff1a;笔记来源于网络&#xff0c;如有侵权联系删除 1 openfeign 1&#xff09;openfeign远程调用声明式实现 1.启动类中添加注解 EnableFeignClients EnableFeignClients SpringBootApplication public class OrderMainApplication {public static void main(St…...

【时时三省】(C语言基础)局部变量和全局变量

山不在高&#xff0c;有仙则名。水不在深&#xff0c;有龙则灵。 ----CSDN 时时三省 以前所见到的程序大多数是一个程序只包含一个main函数&#xff0c;变量是在函数的开头处定义的。这些变量在本函数范围内有效&#xff0c;即在本函数开头定义的变量&#xff0c;在本函数中可…...

An improved YOLACT algorithm for instance segmentation of stacking parts

【一种用于堆叠零件实例分割的改进 YOLACT 算法】 摘要 实例分割在众多应用场景中均是一项至关重要的任务。对于计算机视觉而言,堆叠物体的实例分割是一项挑战。为应对这一挑战,我们提出了一种改进的 YOLACT(You Only Look At CoefficienTs)算法。为提高密集堆叠场景下特…...