记一次死锁问题
最近在做一个需求,碰到了死锁的问题,记录下解决问题的过程
背景
这个需求要改动一个接口,我这边称为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 {@Transactionalmethod 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方法写在其他类中,跨类调用就可以了
相关文章:

记一次死锁问题
最近在做一个需求,碰到了死锁的问题,记录下解决问题的过程 背景 这个需求要改动一个接口,我这边称为A接口,原先的逻辑是A接口内部会调用c方法,c方法是一个dubbo方法, 现在需要再A接口里添加调用B方法&…...

Bean 作⽤域和⽣命周期
目录 1.lombok 1.1 1.添加依赖:(pom.xml) 1.2 在实体类上使用lombok提供的注解 1.3 安装插件 2. Bean 的 6 种作⽤域(Scope) 2.1 singleton(默认模式) 2.2 prototype(原型模式…...

SVN通过备份、过滤、再导入的方式彻底删除废弃目录
文章目录 前言简要步骤操作示例总结 前言 SVN占用的空间随着项目版本迭代越来越大,因为保存了历史记录中的各个版本,所以即使本地把废弃的目录删掉提交,也不会释放出多余的空间,大概率因为操作删除增加了一个版本号,使…...

golang支持优雅关闭和core错误记录
#经过测试,不能使用 ENTRYPOINT ["/modapi/modapi", "1>> /dev/null","2>> ./logs/stderr.log"],原因是虽然这种方案可以 #保证modapi命令为1号程序,能够接收到os的signal信号。但是如果程序core了…...

Basics of Container Isolation 容器隔离的实现原理
目录 容器隔离的实现原理 1. 使用cgroups实现资源隔离 自定义一个cgroup 设置进程的内存使用 启动一个docker 容器,观察cgroup的创建情况 2. 使用Namespaces进行资源分区 namespace继承关系引发的问题 3. 结合来使用Namespaces 和chroot 4. 结论 参考文档…...

EBS R12.1 注册客户化应用的步骤
创建客户化应用目录 登录成 applxxx 用户 -- applxxx 改成所需用户名 # 以标准INV模块作为客户化应用目录的模板 cd $APPL_TOP mkdir -p cust cp -r inv cust/template cd cust # 删除template 目录下的文件,只保留目录结构 cd $APPL_TOP/cust for rm_list in …...

算法记录 | Day38 动态规划
对于动态规划问题,将拆解为如下五步曲 确定dp数组(dp table)以及下标的含义确定递推公式dp数组如何初始化确定遍历顺序举例推导dp数组 509.斐波那契数 思路: 确定dp数组(dp table)以及下标的含义&#x…...

PMP项目管理-[第六章]进度管理
进度管理知识体系: 规划进度管理: 定义活动: 排列活动顺序: 估算活动持续时间: 制定进度计划: 6.1 规划进度管理 定义:为规划、编制、管理、执行和控制项目进度而制定政策、程序和文档的过程 作…...

Python变量
一、变量的定义 变量名的命名规范:变量名是标识符的一种,变量名不能随便起,要遵守 Python 标识符命名规范。 ## 常用的命名规范有以下几种: 1. 变量名为单个单词的话全部小写 name "张三" 2. 多个单词组成的话&#…...

准备换工作的看过来~
大家好,最近有不少小伙伴在后台留言,得准备面试了,又不知道从何下手!为了帮大家节约时间,特意准备了一份面试相关的资料,内容非常的全面,真的可以好好补一补,希望大家在都能拿到理想…...

免费AI人工智能在线写作伪原创-百度ai自动写文章
免费伪原创洗稿工具 免费伪原创洗稿工具现在终于推出了!你是否在写作的时候,经常因为缺乏灵感而苦恼?或者,你在撰写文章的时候,发现自己的语言表述不够丰富,缺乏变化,语句重复率太高?…...

互联网摸鱼日报(2023-04-21)
互联网摸鱼日报(2023-04-21) InfoQ 热门话题 3年不用云能节省4亿美元!想知道我们为什么敢不用AWS吗? 华为周红:通过行业大模型促进AI价值创造 建设业务规划、交付和反馈闭环| BizDevOps 公开课 云原生时…...

5.3、web服务器简介HTTP协议
代码地址 5.3、web服务器简介HTTP协议 1.Web-Server(网页服务器)2.HTTP协议(应用层的协议)①简介②概述③工作原理④HTTP请求报文格式⑤HTTP响应报文格式⑥HTTP请求方法⑦HTTP状态码 1.Web-Server(网页服务器) 一个 Web Server …...

【观察】华为:新一代楼宇网络,使能绿建智慧化
“碳达峰”、“碳中和”目标是我国生态文明建设和高质量可持续发展的重要战略安排,将推动全社会加速向绿色低碳转型。作为全球既有建筑和每年新建建筑量最大的国家,大力发展绿色建筑对中国全方位迈向低碳社会、实现高质量发展具有重要意义。 《“十四五”…...

【C# .NET】chapter 13 使用多任务改进性能和可扩展性
目录 一、物理内存和虚拟内存使用(Recorder 类) 二、 对比 string的“”操作与stringbuilder 操作 的处理效率,内存消耗情况, 三、异步运行任务、三种启动任务方法、将上一任务方法处理结果作为参数传给下一任务方法 四、嵌套…...

CA(证书颁发机构)
CA 根证书路径/csk-rootca/csk-ca.pem; ~ 签发数字证书,颁发者信息:(仅包含如下信息) C CN ST China L BeiJing O skills OU Operations Departments CN CSK Global Root CA 1.修改证书的路径以及相关配置 vi /etc/pki/tls/op…...

辛弃疾最有代表性的十首词
辛弃疾的词,风格多样,题材广阔,几乎涉及到生活中的各个方面,从爱国情怀到日常生活,甚至连戒酒这种事都能写入词中。辛弃疾也是两宋词人中,存词最多的作家之一,现存的六百多首作品。 辛弃疾的词…...

MC9S12G128开发板—实现按键发送CAN报文指示小车移动功能
实验环境:MC9S12G128开发板 基本功能:控制开发板上的按键,模拟车辆移动的上下左右四个方位,通过can通信告诉上位机界面,车辆轨迹的移动方位。 1. 1939报文发送的示例代码 MC9S12G128开发板1939协议发送can报文数据的…...

尚融宝22-提交借款申请
目录 一、需求介绍 二、图片上传 (一)前端页面 (二)实现图片上传 三、数据字典展示 (一)后端 (二)前端 四、表单信息提交 (一)后端 1、VO对象&…...

机器学习在生态、环境经济学中的实践技术应用及论文写作
近年来,人工智能领域已经取得突破性进展,对经济社会各个领域都产生了重大影响,结合了统计学、数据科学和计算机科学的机器学习是人工智能的主流方向之一,目前也在飞快的融入计量经济学研究。表面上机器学习通常使用大数据…...

Android硬件通信之 WIFI通信
一,简介 1.1 随着网络的普及和通信技术的发展,网络的传输速度也越来越快,wifi技术也还成为手机设备最基本的配置。我们可以通过wifi实现手机与手机之前的信息传输,当然也可以与任意一台有wifi模块的其它设备传输。 1.2 wifi与蓝…...

面试官:“请描述一下Android系统的启动流程”
作者:OpenGL 前言 什么是Android启动流程呢?其实指的就是我们Android系统从按下电源到显示界面的整个过程。 当我们把手机充好电,按下电源,手机会弹出相应启动界面,在等了一段时间之后,会弹出我们熟悉的主…...

k8s delete node 后 重启kubelet会自己加入到集群 ?
原因 当执行kubectl delete node命令时,Kubernetes API服务器会收到该节点的删除请求,并将其从集群中删除。此时,kubelet服务在该节点上仍然在运行,但已经不再与集群通信。 当您重启kubelet服务时,它会重新向API服务…...

REXROTH液压方向阀安装须知
安装规程 阀安装到系统之前,应该对照订货型号比较其型号说明。 确认阀的连接表面和底板无水分,没有油。 - 清洁: ‧ 安装元件时,确认工业阀和周围干净 ‧ 油箱须密闭,以防止外部污染 ‧ 安装之前&…...

【数据结构实验】哈夫曼树
【数据结构实验】哈夫曼树 简介: 为一个信息收发站编写一个哈夫曼码的编/译码系统。文末贴出了源代码。 需求分析 完整的系统需要具备完整的功能,包含初始化、编码、译码、印代码文件和印哈夫曼树,因此需要进行相应的文件操作进行配合。哈…...

浏览器不好用?插件来帮忙
一、目的 浏览器本身具备的功能并不完善,不同的用户可以为自己浏览器增加想要功能,使得浏览器更能符合自己的需求,提高浏览器使用的舒适度 二、推荐插件 AdblockPlus LastPass(密码记录,全平台通用) Dar…...

Qt Quick - 容器控件综述
Qt Quick - 容器控件综述 一、概述二、ApplicationWindow Control三、Frame Control四、GroupBox Control五、Page Control六、Pane Control七、ScrollView Control八、StackView Control九、SwipeView Control十、TabBarControl十一、ToolBar控件 一、概述 Qt Quick Controls…...

面试题30天打卡-day06
1、什么是反射机制?说说反射机制的优缺点、应用场景? 反射机制:Java的反射机制是在运行状态,对于任意一个类,都能够动态的获得这个类的属性和方法;对于一个对象,都能动态的调用它当中的方法和属…...

Spring Boot的基础使用和< artifactId>spring-boot-maven-plugin</ artifactId>爆红的处理
Spring Boot的基础使用和< artifactId>spring-boot-maven-plugin</ artifactId>爆红的处理 Spring Boot概述 微服务概述 微服务Microservices是一种软件架构风格,他是以专注于单一责任与功能的小型功能区块Small Building Blocks 为基础,…...

项目管理中的必不可少的强大工具有哪些?
在项目管理中,我们总是想寻求一套功能强大的工具,来满足我们多样化的需求。但往往事与愿违,这样强大的工具总是费用高,操作复杂,需安装多个插件。下面,我就给大家推荐一款项目管理软件 ~Zoho Projects&…...