踩坑记录:spring事务和锁冲突,导致锁失效问题

一、背景前言

前一段做的一个抢购秒杀的功能,用户只能限量抢到一个商品,但是后来发现有个用户抢到了两个商品?!排查问题时发现,是spring事务提交和redis锁释放的顺序,与预想中不一样导致的。

二、问题描述

@Transactional(rollbackFor = Exception.class)
public void test() {
	if (!redisLock.tryLock("lock_1", "123", 5L, TimeUnit.SECONDS)) {
	    throw new ServiceException("已被其他线程锁住!");
	}
	try {
	    // 业务逻辑
	} finally {
	    redisLock.releaseLock("lock_1", "123");
	}
}

debug发现:

1. \color{#FF7D00}{1.} 1.  线程A,先执行finally语句,导致锁释放掉了,这时候,线程A事务还没提交;

2. \color{#FF7D00}{2.} 2.  线程B,拿到锁,后面在不发生异常的情况下,线程A和线程B的事务都会正确提交;

三、解决方案

1. \color{#FF7D00}{1.} 1.  如果事务里是insert方法,可以不要锁,改成数据库表里设置唯一索引的方法;

2. \color{#FF7D00}{2.} 2.  事务和锁分开,锁提取到controller层;或者一个无事务的service方法中加锁,锁住一个有事务的方法;

Spring事务冲突失效问题是在并发环境下常见的挑战之一,可以采用以下方法来解决这个问题。 首先,对于Spring事务冲突失效问题,可以考虑以下策略: 1. 调整事务隔离级别:通过提高事务的隔离级别,如将隔离级别设置为Serializable,可以避免脏读、不可重复读和幻读等并发访问问题。 2. 使用乐观:在进行并发操作时,通过使用版本号或时间戳等机制来对数据进行控制,从而避免冲突。 3. 使用悲观:在进行并发操作时,通过对数据进行加,限制其他事务对数据的访问,避免冲突。 4. 使用分布式:在分布式环境下,通过使用分布式来控制并发访问,避免冲突。 其次,对于冲突失效问题,可以采取以下方法: 1. 减小粒度:将应用到最小的代码块,避免住不需要同步的代码部分,从而减少冲突的可能性。 2. 使用更合适的策略:在并发情况下,选择合适的策略,如公平、非公平、读写等,以提高并发访问效率。 3. 使用分布式:在分布式环境下,使用分布式来对资源进行同步处理,避免冲突失效问题。 4. 优化系统设计:通过优化系统架构和设计,尽可能减少并发访问的需求,从而降低冲突的可能性。 总之,解决Spring事务冲突失效问题需要综合考虑事务隔离级别、策略、粒度和系统设计等多个因素。通过合理选择和调整这些策略,可以有效地缓解并发环境下的问题
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

w_tt

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值