关于抢购场景使用锁和事务防止重复领取失败

131 阅读2分钟
业务场景就是普通的抢购,每个用户最多只能抢一件,所有在这种情况下就需要用锁去保证会出现超领的问题,同时该业务场景通常都设计到订单的生成,甚至还需要去缓存用户已经抢购了的记录,所有会使用要事务。
先说下代码的逻辑思想,查询缓存中用户是否已经抢购,再到数据库中进行查询是否已经抢购,然后在锁里面的代码逻辑中再去数据库中进行查询是否已经抢购,三重判定后再进行订单之类的业务逻辑,这里就因为有锁,所有理论上不会存在超领的问题,但现实情况就是出现了超领,判定并没有生效,我一开始也非常的纳闷,为什么没有锁成功,之后通过DEBUG发现并不是锁没有成功,而是同一个人在极短时间内发送了多个相同的请求,而这些请求都各自开启了自己的事务,到这里可能已经有同学相同了,事务隔离级别,可重复读,因为上面所提到的锁只用来判断了是否已经抢购,所有到下面业务逻辑订单生成,记录生成的时候,另一个请求也在进行判断,加上上一个事务未提交,导致请求读到的数据是没有抢购过的记录,所有产生了超领。
解决方法,首先在这种情况下的查询需要用select ... for update,其次就是锁里面要包括需要处理的业务逻辑,要不然事务没提交,可重复读会导致短时间内突破幂等性的请求没有达到预期的结果。