记一次死锁问题

news2024/11/26 10:41:11

最近在做一个需求,碰到了死锁的问题,记录下解决问题的过程

背景

这个需求要改动一个接口,我这边称为A接口,原先的逻辑是A接口内部会调用c方法,c方法是一个dubbo方法,
现在需要再A接口里添加调用B方法,b方法是本地调用。

A接口的入参是某个商品的编码,拿到这个商品编码后匹配到一个交易订单,B方法和C方法都是需要操作这个订单商品的库存,所以都上了锁。

原逻辑

在这里插入图片描述

现逻辑

在这里插入图片描述

加完B方法后,发现每次调用接口都会超时,分析日志发现是c方法加库存锁超时了。c方法的库存锁还未释放,同时B方法又加了这个锁,B需要等待C占用的锁释放,而c的锁释放也需要等待B方法结束,于是就产生了死锁

于是我产生了以下几个疑问

1、我们的锁不是支持可重入吗,为什么还会死锁?

是因为可重入是需要同一个线程,而c方法因为是dubbo调用,已经不是一个同一个线程了,就会产生互斥的效果

2、我们项目中的锁做了统一处理,都是在事务结束后才释放锁,是否可以在B方法执行完就释放锁?

这个地方我们之前是踩过坑的,如果在事务完成前释放锁,那么另一个线程会拿到锁,但是因为前面的事务还未提交,所以他查询的数据还是老数据。这样加锁就没有达到目的了,所以必须在事务完成后再释放锁

解决方法

方案1

首先我的想法是能否从业务上解决,如果业务上不关心B方法跟A方法的一致性的一致性的话,就是如果A方法报错了,B方法不需要回滚,那么最简单的做法就是B方法新起一个事务,这样当B方法结束后,B的事务也就结束了,库存锁也就释放了,也就不会影响到c方法

但是产品的想法是需要保证一致,所以这个方法不能搞

方案2

将B方法的加锁和c方法的加锁挪到最外层A方法上,B方法和c方法都不用加锁了

这种方案可以解决问题,但是会引发其他问题,一个就是加锁的范围变大了,会影响这个接口整体的性能,其次需要改动B方法和c方法,也容易改出问题

方案3

B方法和c方法顺序调换,先执行B方法再执行C方法,因为B方法是dubbo方法,所以B方法执行完后它自己的事务也就结束了,B占用的库存锁也会释放。再执行c方法就不会导致锁等待

这个方案是可以实施的,但是会出现一种情况,当c方法报错时,B方法因为已经执行完了,就无法回滚了。之前B方法调用放在最后调用是不会有问题的。同时B方法和c方法顺序调换需要调整一些代码,不是简单的调换就可以的,基于这两点我最后也没有采用这个方案

方案4

结合方案1,B方法另起一个事务,同时如果后续逻辑报错了,捕获异常,调用B方法的回滚方法(也是新事务)
有点像tcc模式

最终采用了这个方案,改动量和影响点最小

碰到了另一个坑

另起一个事务用了Propagation.REQUIRES_NEW 这个传播级别,但是测试的时候发现还是死锁,似乎没有起到效果,于是我回想起事务失效的几种场景,又复习了遍AOP的底层原理,知道自己踩坑了

原始代码A方法调用B方法

service A {
    @Transactional
    method A() {
        B();
    }
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    method B() {
        
    }
}

spring启动后会扫描@Transactional注解,生成代理类AProxy,添加事务的逻辑

service AProxy {
    A a;
    
    method A() {
        // 开启事务
        a.B();
        // 结束事务
    }

    // 没有走这个方法
    method B() {
        // 新开事务
        // 结束事务
    }
}

当我们执行A方法,会执行代理类AProxy的方法,但是调用B方法是没有调用代理类的B方法,而是service A自己原本的方法,所以method B上的注解没有其效果

解决方法也有好几种,我这边是将method B方法写在其他类中,跨类调用就可以了

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/460789.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

springcloud之Feign、ribbon设置超时时间和重试机制的总结

目录标题 超时时间ribbon和Feignribbon和Feign默认超时时间关于ribbon和Feign超时时间配置说明 关于hystrix默认超时时间与配置说明 ribbon的重试机制重试的次数hystrix超时时间举个例子 超时时间 feign/ribbon对应的是请求的时间 hystrix对应的是断路器的时间 一般情况下 都是…

【Linux】2. 常见指令

1. 操作系统的定义 在真正了解Linux操作系统之前,我们需要初步明确什么是操作系统 Linux下的基本指令 指令的作用是什么,其实就是相当于Windows的基本操作,Linux操作系统是以命令行显示的,而Windows则是以图形化界面的方式展现…

图像融合方向:《Deep Image Blending》论文理解

《Deep Image Blending》论文理解 论文:《Deep Image Blending》WACV 2020 链接:Deep Image Blending 本文目录 《Deep Image Blending》论文理解论文创新点具体实现思路文中使用的基准方法文章内容解析使用模型整体架构两阶段算法详情第1阶段第2阶段 损…

一款高效、可靠的自动化测试平台,提升效率、降低测试成本

一、开源项目简介 扬帆测试平台是一款高效、可靠的自动化测试平台,旨在帮助团队提升测试效率、降低测试成本。该平台包括用例管理、定时任务、执行记录等功能模块,支持多种类型的测试用例,目前支持API(http和grpc协议)、性能,并且…

轻量级服务器nginx:负载均衡

负载均衡就是让每个设备,以同样的概率,处理用户对于服务器的任务请求,默认采用的负载调度策略就是轮流询问,Nginx作为反向代理服务器安装在服务端,Nginx的功能就是把请求转发给后面的应用服务器. 这里写目录标题 一 负…

差分优化算法——DE

🍎道阻且长,行则将至。🍓 目录 一、DE1.步骤2.特点 二、DE Optimiza1.函数最小值问题2.差分进化算法求解2.Java 实现与结果绘图 一、DE 差分进化算法是一种基于群体智能的优化算法,由Storn和Price于1995年提出,最早用…

vue3+ts开发微信小程序----使用FontAwesome图标的步骤(只适用于面性图标)

vue3ts开发微信小程序----使用FontAwesome图标的步骤(只适用于面性图标) 因为用的vue3ts 但是对于npm引进FontAwesome来说,好像对于小程序不支持,所以用了引入文件的方式。 下载FontAwesome字体,我用的是5版本的。[官方…

从初识RabbitMQ到安装了解

一、同步和异步通讯 微服务间通讯有同步和异步两种方式: 同步通讯:就像打电话,需要实时响应。 异步通讯:就像发邮件,不需要马上回复。 两种方式各有优劣,打电话可以立即得到响应,但是你却不…

记 SAM React Demo 转 Vue 遇到的一些问题

前言 SegmentAnything Model (SAM) 是 Meta 开源的分割万物 AI 模型,因笔者主要使用 Vue,因此对官方 Demo 进行了工程迁移工作,这里记录了迁移过程遇到的一些问题。 没有使用多线程加速 官方的 React Demo 项目使用ort-wasm-simd-threaded…

态路小课堂丨浅谈IDC数据中心综合布线互联

在数据中心发展过程中,服务器、光模块等设备更新周期短,迭代快。但是,对于IDC数据中心综合布线系统来说,其使用周期一般都比较长。因此,为了能够匹配IDC数据中心的发展,关于综合布线的设计尤为重要。 目前&…

【vue】elementUI中el-table拖动滚动条的时候固定某一列

文章目录 前言:需求 前言: 写项目的时候有一个需求,就是当el-table的滚动条滑动的时候,可见区域如果没有该列则固定到左侧,由elementUi官方网站可知el-table固定一列的代码如下: fixed为主要的标识 头部固定设置的是t…

leetcode 2336. Smallest Number in Infinite Set(有限集中的最小数字)

实现一个SmallestInfiniteSet类(后面用set简称),满足以下功能: 初始化时,set含有所有的正整数。 pop函数返回set中最小的整数。 add函数在set中添加一个整数。 思路: set具有以下的功能: 可以取出最小的数字。 可以查…

FPGA入门系列13--异步串口通信

文章简介 本系列文章主要针对FPGA初学者编写,包括FPGA的模块书写、基础语法、状态机、RAM、UART、SPI、VGA、以及功能验证等。将每一个知识点作为一个章节进行讲解,旨在更快速的提升初学者在FPGA开发方面的能力,每一个章节中都有针对性的代码…

Baklib如何帮助企业设计并维护FAQ页面?

作为现代企业的一部分,客户支持服务是为客户提供解决方案、回答问题和解决技术难题的关键部分。而其中最重要的一个基本工具是FAQ页面(Frequently Asked Questions),它可以有效地减轻客户支持压力和提高工作效率。然而&#xff0c…

Linux——进度条与git的使用

目录 main.c Makefile process.c \r process.h 进度条的演示动图 git的使用 在gitee上创建一个仓库 复制HTTPS到xshell git clone .gitignore ​编辑 git add git commit -m 这里写日志信息 git push sudo yum -y install git git log git status git mv / …

vue2之echarts的封装 折线图,饼图,大图

目录 vue2之echarts的封装 折线图,饼图,大图折线图,饼图chartPan.vue使用 chartPan.vue 之饼图效果使用 chartPan.vue 之折线图效果展开大图大图组件 maxChart.vue大图效果 vue2之echarts的封装 折线图,饼图,大图 折线…

视觉回归测试—UI自动化的最后1分钟

视觉回归测试是一种验证应用GUI是否正确地展示给用户的操作。测试目标是找出应用在可视化上存在的软件缺陷,例如,字体、布局和渲染问题。这使得所发现的软件缺陷可在被最终用户看到前得到修正。此外,视觉测试可用于验证页面的内容&#xff0c…

车道线检测

前言 目前,车道线检测技术已经相当成熟,主要应用在自动驾驶、智能交通等领域。下面列举一些当下最流行的车道线检测方法: 基于图像处理的车道线检测方法。该方法是通过图像处理技术从摄像头传回的图像中提取车道线信息的一种方法&#xff0c…

【AI工具 收藏】

文章目录 miniGPT4:chatGPT,支持图片哔哔终结者 BibiGPT:自动总结视频内容Scribble Diffusion:草图绘画ChatGPT Shortcut:prompt提示词其他 博客总结的工具: miniGPT4:chatGPT,支持图…

ROS2下机械手的手眼标定

最近发现老是有人通过爬虫把文章爬去他们网站,因此先发一遍这个草稿,让他们先爬。爬完我再慢慢修改 0.前期准备 0.1机械手要先映射(标定好)世界坐标系与用户坐标系 这个基本应该可以通过机械手自带的坐标系建立完成 一般机械手…