踩坑记录: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方法中加锁,锁住一个有事务的方法;

猜你喜欢

转载自blog.csdn.net/qq_36514197/article/details/122365481