Skip to content
DAILY QUOTE

“ ”

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

现在的问题在于:

优惠券是为了引流,但是目前的情况是,一个人可以无限制的抢这个优惠券,所以我们应当增加一层判断逻辑,让一个用户只能下一个单,而不是让一个用户下多个单。

具体操作逻辑如下:比如时间是否充足,如果时间充足,则进一步判断库存是否足够,然后再根据优惠券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同样发现当前用户未下单,也准备下单,这样明明一个用户只能下一单,结果下了两单,也就出现了超卖问题。