需求:修改秒杀业务,要求同一个优惠券,一个用户只能下一单

现在的问题在于:
优惠券是为了引流,但是目前的情况是,一个人可以无限制的抢这个优惠券,所以我们应当增加一层判断逻辑,让一个用户只能下一个单,而不是让一个用户下多个单。
具体操作逻辑如下:比如时间是否充足,如果时间充足,则进一步判断库存是否足够,然后再根据优惠券id和用户id查询是否已经下过这个订单,如果下过这个订单,则不再下单,否则进行下单。
java
//4.判断库存是否充足
if (voucher.getStock()<1) {
//库存不足
return Result.fail("库存不足");
}
//5.一人一单
Long userId = UserHolder.getUser().getId(); //直接从ThreadLocal获取ID
//5.1.查询订单
int count = query().eq("user_id", userId).eq("voucher_id", voucherId).count();
//5.2.判断是否村在
if(count>0){
//用户已经购买过了
return Result.fail("用户已经购买过了");
}
//6.扣减库存
boolean success = seckillVoucherService.update()
.setSql("stock=stock-1") //set stock=stock-1
.eq("voucher_id", voucherId)
.gt("stock", 0)
.update();
if(!success){
return Result.fail("库存不足");
}使用JMeter测试是否完成一人一单要求,结果是库存90,同一人下了10单,还是存在一人一单超卖问题。

这个原因其实和多线程并发下一人多单超卖成负数的问题一样,线程1查询当前用户是否有该优惠券的订单,当前用户没有订单准备下单,此时线程2也查询当前用户是否有订单,由于线程1还没有完成下单操作,线程2同样发现当前用户未下单,也准备下单,这样明明一个用户只能下一单,结果下了两单,也就出现了超卖问题。