死锁

在压测Sharding-JDBC时遇到程序假死现象,通过jstack发现多线程阻塞在Druid的takeLast方法,原因是分布式ID获取时重新获取连接而非使用同一Session。由于未设置最大连接数和最大等待时间,导致连接耗尽,形成死锁。调整Druid数据源配置,增大连接数并设置最大等待时间,成功避免死锁问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

死锁

压测sharding-jdbc 改造一个原先用类似mycat的一个程序放到压测平台后,发现运行一会程序就假死了。于是在本地压测。同样运行一会就假死,然后debug。 发现在获取分布式id的时候在锁的地方进行不下去。然后怀疑是哪里导致了死锁,于是运行jstack -l 如下

 

发现很多请求的线程都等待在了druid的takelast 方法。进去这个方法看,发现是 一个生产者消费者模式的 获取连接的数组。由于没有可以用的链接了(大于最大的链接数 默认是8个)。所以没有链接了就在这里一直阻塞。为什么没有链接了。及时是很多的请求,那么获取到链接请求的线程也应该往下走,而不是假死。于是继续往下看线程状态。发现开始的几个请求阻塞在了分布式id获取id的地方

 

进去nextRang查看 发现他会从新获取连接 而不是用当前线程的链接

 

mybatis-spring包提供的sqlsessionFactory 可以保证当前线程都是同一个session (同一个链接)但是这里 获取分布式id的时候是重新获取连接。没有用sqlsessionFactory 来管理。sqlsessionFactory 具体怎么分析https://blog.youkuaiyun.com/z530065424/article/details/82864328

由于我在设置druid数据源的时候没有传入最大的链接数,和最大等待时间。 因此默认链接最多只有8个。且获取连接时 没有等待期限。在这两个前提下。多个请求进来 将连接数用满。一个请求在去获取链接来查询分布式id 的时候就拿不到链接从而阻塞了。而他又 获取了锁。导致他拿着锁,阻塞在了这里。当其他请求进行到这里获取分布式id的时候就会阻塞在这个锁上。然后执行不下去。那么该请求不会释放自己占有的链接。当多个线程阻塞在这,那么连接就耗尽了,那么拿着分布式id 锁的 线程 得不到链接 就不放锁。从而导致一个典型的死锁。导致数据源链接泄露。程序假死。

开始出现这个问题的时候不知道druid不传 最大等待时间会一直等待。因此没有找出上面的死锁原因。于是乎拿mycat测试。看mycat会不会死锁。压测后发现不死锁。于是看他的连接信息发现,他最大链接是80个最大等待时间5秒。把最大等待时间去掉。最大链接数减小。在压测。发现程序也是一样的假死了。因此回到sharding-jdbc 把数据源的连接数调大,等待时间加上。程序不会死锁了。因为 拿不到链接的时间有限,超过时间就放弃了。打破了死锁。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值