使用乐观锁和CAS解决超卖(Overselling)

目录

背景介绍

具体实现

用乐观锁和CAS扣减库存


今天我要和大家分享的是如何在Java中使用乐观锁和CAS(Compare-And-Swap)技术来解决超卖的问题。最近我在项目中实现了这个功能,觉得非常有意思,所以决定分享出来。希望对大家有所帮助!

背景介绍

秒杀活动通常在电商平台中很常见,实现这个功能的难点在于多线程环境下如何避免超卖。为了应对这个问题,我们使用了乐观锁和CAS法,这样既避免了悲观锁的串行问题,又兼顾了高并发的性能。

具体实现

下面是实现代码的详细说明:

@Service
public class VoucherOrderServiceImpl extends ServiceImpl<VoucherOrderMapper, VoucherOrder> implements IVoucherOrderService {

    @Resource
    private ISeckillVoucherService seckillVoucherService;

    @Resource
    private RedisIdWorker redisIdWorker;

    @Override
    @Transactional
    public Result seckillVoucher(Long voucherId) {
        // 1.查询优惠券
        SeckillVoucher voucher = seckillVoucherService.getById(voucherId);
        // 2.判断秒杀是否开始
        if (voucher.getBeginTime().isAfter(LocalDateTime.now())) {
            // 尚未开始
            return Result.fail("秒杀尚未开始!");
        }
        // 3.判断秒杀是否已经结束
        if (voucher.getEndTime().isBefore(LocalDateTime.now())) {
            // 已经结束
            return Result.fail("秒杀已经结束!");
        }
        // 4.判断库存是否充足
        if (voucher.getStock() < 1) {
            // 库存不足
            return Result.fail("库存不足!");
        }
        // 5.扣减库存 - 使用乐观锁和CAS
        boolean success = seckillVoucherService.update()
                .setSql("stock = stock - 1")
                .eq("voucher_id", voucherId)
                .gt("stock", 0)  // 防止超卖
                .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 id = UserHolder.getUser().getId();
        voucherOrder.setUserId(id);
        // 6.3.设置优惠券id
        voucherOrder.setVoucherId(voucherId);
        save(voucherOrder);
        // 7.返回订单id
        return Result.ok(orderId);
    }
}

用乐观锁和CAS扣减库存

在扣减库存时,我们使用了MyBatis Plus的update方法,通过设置setSql("stock = stock - 1")和条件eq("voucher_id", voucherId)gt("stock", 0)来确保在扣减库存时不会发生超卖。CAS技术确保了操作的原子性,这让并发情况下库存扣减的操作更加可靠。

最后通过Jmeter测试,异常率为0

  • 16
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值