在本文中,将介绍一次遇到的.Net分布式事务死锁现象以及解决方法。我们将首先了解事务框架的构成,然后分析导致死锁的代码,最后提出解决方法。

事务框架

本次开发框架JMSFramework将分布式事务划分为4个阶段,分别是:执行、确认、提交和重试。

1、执行

调用微服务来执行相关的业务操作。如果其中任何一个服务执行抛出异常或者宕机,那么所有的事务都会回滚。

2、确认

这个阶段会向各个微服务发送确认请求,主要目的是校验一下当前的网络是否正常,微服务有没有宕机,如果这个阶段有任何异常,那么所有的事务都会回滚。

3、提交

首先JMSFramework会通知网关,标识这次分布式事务为成功状态。(如果通知网关失败,则回滚所有事务)

然后通知各个微服务提交事务,确保所有的操作都已经完成。

如果某个服务提交事务失败,不会影响其他服务提交事务。

4、重试

有很小的机率会执行到此阶段。

当某个微服务在真正提交事务的时候发生意外宕机,导致事务没有成功提交。一旦服务器重新启动后,它会向网关咨询,并得知该事务已经被标记为成功状态。这时,系统会自动重新执行相关的业务代码,并提交事务,以确保数据的一致性。

产生死锁的代码

接下来我们看看触发死锁的代码:

            using ( var client = new RemoteClient(gatewayAddrs))
{
//标识后面的调用需要启用分布式事务控制
client.BeginTransaction(); //获取服务接口
var accountService = await client.GetMicroServiceAsync("UserAccountService");
var giftService = await client.GetMicroServiceAsync("UserAccountService"); //扣除指定用户100积分
accountService.InvokeAsync("UseMemberPoints", userid , 100 ); //把某个礼品赠予指定用户
var ret = await giftService.InvokeAsync<GiftResult>("GiveGiftToUser", giftid, userid);
if(ret.GiftsReceivedCount > 10)
{
//如果累计收取礼品大于10个,升级用户vip等级
accountService.InvokeAsync("UpgradeVip" , userid);
} //提交分布式事务
await client.CommitTransactionAsync();
}

这是一段调用几个微服务的代码,功能是:扣除用户100积分,同时把一个礼品转给这个用户,如果发现此用户累计已经兑换超过10个礼品,那么提升此用户的vip等级。

代码很简单,看不出有什么问题,并且上面所调用的三个接口函数,也都是通过了单元测试。

但运行后却发现卡死在client.CommitTransactionAsync()。

看来是调用某个服务卡住了,当我把每个调用都加上await后,发现其实是卡在了await accountService.InvokeAsync("UpgradeVip" , userid);

经过查阅代码,得知该函数会去更新用户信息表,而扣除用户100积分的函数也会去更新用户信息表。由于这两个函数在不同的线程中执行(服务调用属于远程请求,每次请求都是一个独立的线程),它们都要锁定同一个资源,因此只会有第一个线程成功更新,但由于数据库事务不会立即提交,而是最后一起提交,因此该用户数据会一直被锁定。第二个线程无法获取锁,更新语句也一直无法执行。由于第二个线程被阻塞,代码无法执行到client.CommitTransactionAsync(),导致事务无法提交,锁也不会被释放,这就形成了死锁。

解决方法

问题的根本不是两个线程锁定同一个资源,而是两个不同的数据库对象锁定同一个资源。如果这两个线程使用的是同一个数据库对象和同一个数据库事务,就不会出现这个问题。

因此,解决方法如下:

  • 数据库对象作用域管理:使用AddScope方式依赖注入数据库对象,确保在同一个作用域中获取的数据库对象是同一个。

  • 利用JMSFramework特性:利用JMSFramework 5.0及以上版本的特性,自动将同一个分布式事务范围内的远程调用整合到一个网络请求中。这样,如果调用的服务属于同一个进程,它们将被安排在同一个作用域中,从而保证获取到的数据库对象是同一个。

通过以上解决方法,可以有效避免分布式事务死锁的发生。

记一次.Net分布式事务死锁现象以及解决方法的更多相关文章

  1. I2C死锁原因及解决方法(转)

    源:http://blog.csdn.net/zyboy2000/article/details/5603091 死锁总线表现为:SCL为高,SDA一直为低 现象:单片机采用硬件i2c读取E2PROM ...

  2. libnids关于计算校验和引起的抓不到包的现象的解决方法

    libnids关于计算校验和引起的抓不到包的现象的解决方法: nids.h中有这么一段: struct nids_chksum_ctl { u_int netaddr; u_int mask; u_i ...

  3. 将不确定变为确定~transactionscope何时提升为分布式事务?(sql2005数据库解决提升到MSDTC的办法)

    回到目录 对于transactionscope不了解的同学,可以看我的相关文章 第二十六回   将不确定变为确定~transactionscope何时提升为分布式事务? 第二十七回   将不确定变为确 ...

  4. sqlserver 死锁原因及解决方法

    其实所有的死锁最深层的原因就是一个:资源竞争 表现一: 一个用户A 访问表A(锁住了表A),然后又访问表B,另一个用户B 访问表B(锁住了表B),然后企图访问表A,这时用户A由于用户B已经锁住表B,它 ...

  5. TCP协议的粘包现象和解决方法

    # 粘包现象 # serverimport socket sk = socket.socket()sk.bind(('127.0.0.1', 8005))sk.listen() conn, addr ...

  6. Mysql并发时经典常见的死锁原因及解决方法

    1.    mysql都有什么锁 MySQL有三种锁的级别:页级.表级.行级. 表级锁:开销小,加锁快:不会出现死锁:锁定粒度大,发生锁冲突的概率最高,并发度最低. 行级锁:开销大,加锁慢:会出现死锁 ...

  7. MySQL学习笔记(五)并发时经典常见的死锁原因及解决方法

    MySQL都有什么锁? MySQL有三种锁的级别:页级.表级.行级. 表级锁:开销小,加锁快:不会出现死锁:锁定粒度大,发生锁冲突的概率最高,并发度最低. 行级锁:开销大,加锁慢:会出现死锁:锁定粒度 ...

  8. C++(八)— 死锁原因及解决方法

    1.死锁原因 死锁问题被认为是线程/进程间切换消耗系统性能的一种极端情况.在死锁时,线程/进程间相互等待资源,而又不释放自身的资源,导致无穷无尽的等待,其结果是任务永远无法执行完成. 打个比方,假设有 ...

  9. hadoop 完全分布式 下 datanode无法启动解决方法

    问题描述: 在集群模式下更改节点后,启动集群发现 datanode一直启动不起来. 我集群配置:有5个节点,分别为master slave1-5 . 在master以Hadoop用户执行:start- ...

  10. ORA-02049: 超时: 分布式事务处理等待锁的解决方法

    是其他地方执行了操作没有提交,把其他地方提交了就好了

随机推荐

  1. [Linux]调整swap

    在启动Tomcat的过程中,tomcat/catalina.out中报出如下故障: > /opt/govern/wydaas/logs/catalina.out # There is insuf ...

  2. scikit-learn 中 Boston Housing 数据集问题解决方案

    scikit-learn 中 Boston Housing 数据集问题解决方案 在部分旧教程或教材中是 sklearn,现在[2023]已经变更为 scikit-learn 作用:开源机器学习库,支持 ...

  3. 网络框架重构之路plain2.0(c++23 without module) 环境

    接下来本来就直接打算分享框架重构的具体环节,但重构的代码其实并没有完成太多,许多的实现细节在我心中还没有形成一个定型.由于最近回归岗位后,新的开发环境需要自己搭建,搭建的时间来说花了我整整一天的时间才 ...

  4. 5221. 【GDOI2018模拟7.10】A

    题目大意: 给你一棵有根树,问你在这棵树上总共有多少棵子树的节点构成了一个完整的整数区间. 考试想法: 考试时就想到了正解,正解就是从下到上遍历整一棵树,每一个节点记录一下它的最小值min.最大值ma ...

  5. SSM整合之基础xml文件以及基础理解

    文章目录 前言 什么是SSM框架 实例 pom依赖 Spring 文件配置 最后 展示代码 总结 前言 最近在学习SSM框架,就去找了一些视频来看,写一篇整合的文章,文章包括一些整合的依赖,以及创建的 ...

  6. 虚拟机的安装与linux系统的使用

    虚拟机的安装与应用 下载安装VMware Workstation Pro 安装成功之后点击创建虚拟机 勾选典型机型 勾选自动检测安装映像文件 设置虚拟机的命名和安装路径 设置磁盘的大小和虚拟磁盘的储存 ...

  7. 音视频八股文(2)--ffmpeg常见命令(1)

    官方文档: https://www.ffmpeg.org/ffplay-all.html https://www.ffmpeg.org/ffmpeg-all.html 01-Windows FFMPE ...

  8. Kerberos协议原理

    本文主要介绍Kerberos认证协议的原理以及解决了什么问题 Kerberos是什么 Kerberos是计算机网络世界中的一种身份认证协议. 身份认证是我们日常生活中经常进行的活动,比如我们要去银行取 ...

  9. Actor Prioritized Experience Replay

    论文宗旨: 由于PER 是以TD-error成正比的非均匀概率进行抽样的,但是在AC算法中即连续动作空间中,会表现出低效果. 分析结果是:Actor不能有效的从high TD-error的transi ...

  10. Luogu1772 [ZJOI2006] 物流运输

    传送门 简化题意 给你 \(m\) 个码头,码头之间有双向边连接,\(n\) 天,其中一些码头在某些天会不可用,这 \(n\) 天都要有一条从 \(1\) 到 \(m\) 的路,每一次更换道路会需要 ...