秒杀都是先保存后更新,保存成功,但是更新不一定会成功
dynamicQuery.save(killed);
nativeSql = "UPDATE seckill SET number=number-1 WHERE seckill_id=? AND number>0";
dynamicQuery.nativeExecuteUpdate(nativeSql, new Object[]{seckillId});
如果更新语句执行完成就不会超卖了 redis分布式锁情况下
nativeSql = "UPDATE seckill SET number=number-1 WHERE seckill_id=? AND number>0";
int i = dynamicQuery.nativeExecuteUpdate(nativeSql, new Object[]{seckillId});
if (i > 0) {
SuccessKilled killed = new SuccessKilled();
killed.setSeckillId(seckillId);
killed.setUserId(userId);
killed.setState((short)0);
killed.setCreateTime(new Timestamp(new Date().getTime()));
dynamicQuery.save(killed);
}
调整更新和保存调用的顺序和判断应该就是保证了:一笔秒杀处理的原子性。
此时把redis分布式锁拿掉也是可以的。
针对RR级别隔离,不管是分布式锁,内存锁,都务必将锁提到事务开启前。
事务开启后才加锁,存在这样的情景:
在两个事务里分别获取到锁时,读取的是同一份数据,
然后两个线程在线程已安全的错觉下不再额外判断数据仅做业务处理时,
对相同的数据进行同样的业务处理,就会出现数据覆盖的问题,就是这里的超卖问题。
既然加了锁就不要加一个没实际作用的锁,加锁也是有成本的,特别是高并发下,加锁成本还是蛮高的
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。
登录 后才可以发表评论