【Redis】高并发场景下秒杀业务的实现思路(单机模式)

一、超卖问题

业务要求:

实现一个对优惠券限时抢购的功能。

你可能会想,啥抢购啊,说白了不就是买东西吗,先判断一下是否在抢购时间,然后在买的时候判断一下是否还有库存不就行了。如果有,说明优惠券还没抢完,则让订单生效,并让库存减一;如果没有,说明已经抢完了,直接返回异常提示就好了。很容易就能得到下图中的流程:

这业务逻辑感觉好像没啥毛病,接着就可以根据这个流程编写代码了:

    @Transactional  //事务
    public Result seckillVoucher(Long voucherId) {
        //1.查询优惠券
        SeckillVoucher voucher = seckillVoucherService.getById(voucherId);
        //2.判断秒杀是否开始
        LocalDateTime beginTime = voucher.getBeginTime();
        if(LocalDateTime.now().isBefore(beginTime)){
            //秒杀还未开始,返回提示信息
            return Result.fail("秒杀还为开始!");
        }
        //3.判断秒杀是否结束
        LocalDateTime endTime = voucher.getEndTime();
        if(LocalDateTime.now().isAfter(endTime)){
            //秒杀已经结束,返回提示信息
            return Result.fail("秒杀已经结束!");
        }
        //4.判断库存是否充足
        Integer stock = voucher.getStock();
        if(stock<=0){
            //优惠券已经抢完,没有库存了
            return Result.fail("优惠券已被抢完!");
        }
        //5.扣减库存
        boolean success = seckillVoucherService.update()
                .setSql("stock = stock-1")
                .eq("voucher_id", voucherId).update();
        if(!success){
            //数据库更新失败
            return Result.fail("优惠券已被抢完!");
        }
        //6.创建订单
        VoucherOrder voucherOrder=new VoucherOrder();
        //6.1.订单id
        long orderId = redisIdWorker.nextId("order");
        voucherOrder.setId(orderId);
        //6.2.用户id
        Long userId = UserHolder.getUser().getId();
        voucherOrder.setUserId(userId);
        //6.3.代金券id
        voucherOrder.setVoucherId(voucherId);
        save(voucherOrder);
        //7.返回订单id

        return Result.ok(orderId);
    }

好像已经把业务要求成功实现了,是不是万事大吉了?然而,现实场景中,由于秒杀的限时限量的特性,往往会吸引大量用户参与,就会给系统带来并发压力。让我们用jmeter模拟一下高并发场景下的运行情况:

 

 设置200个线程发送秒杀请求,而数据库中存放了100张优惠券。正常情况下,最后应该有100个线程抢券成功,另一百个线程则返回异常信息,

评论 73
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值