业务场景题——秒杀系统如何避免库存超卖?

在秒杀场景下,高并发可能导致库存超卖问题。本文分析了问题原因并提出了四种解决方案:1) 使用Redisson分布式锁;2) 通过MySQL行锁确保每次查询的库存是最新的;3) 采用乐观锁,利用版本号控制更新;4) 在SQL中进行库存检查和扣减。这些方法在保障数据一致性的同时,也考虑了用户体验和系统性能。
摘要由CSDN通过智能技术生成

先看问题

首先上一串代码

public String buy(Long goodsId, Integer goodsNum) {
    //查询商品库存
    Goods goods = goodsMapper.selectById(goodsId);
    //如果当前库存为0,提示商品已经卖光了
    if (goods.getGoodsInventory() <= 0) {
        return "商品已经卖光了!";
    }
    //如果当前购买数量大于库存,提示库存不足
    if (goodsNum > goods.getGoodsInventory()) {
        return "库存不足!";
    }
    //更新库存
    goods.setGoodsInventory(goods.getGoodsInventory() - goodsNum);
    goodsMapper.updateById(goods);
    return "购买成功!";
}

我们看一下这串代码,逻辑用流程图表示如下:

从图上看,逻辑还是很清晰明了的,而且单测的话,也测试不出来什么bug。但是在秒杀场景下,问题可就大发了,100件商品可能卖出1000单,出现严重资损,这下就真的需要杀个程序员祭天了。

问题分析

正常情况下,如果请求是一个一个接着来的话,这串代码也不会有问题,如下图:

不同的时刻不同的请求,每次拿到的商品库存都是更新过之后的,逻辑是ok的。

那为啥会出现超卖问题呢? 首先我们给这串代码增加一个场景:商品秒杀(非秒杀场景难以复现超卖问题)。 秒杀场景的特点如下:

  • 高并发处理:秒杀场景下,可能会有大量的购物者同时涌入系统,因此需要具备高并发处理能力,保证系统能够承受高并发访问,并提供快速的响应。
  • 快速响应:秒杀场景下,由于时间限制和竞争激烈,需要系统能够快速响应购物者的请求,否则可能会导致购买失败,影响购物者的购物体验。
  • 分布式系统: 秒杀场景下,单台服务器扛不住请求高峰,分布式系统可以提高系统的容错能力和抗压能力,非常适合秒杀场景。

在这种场景下,请求不可能是一个接一个这种,而是成千上万个请求同时打过来,那么就会出现多个请求在同一时刻查询库存,如下图:

如果在同一时刻查询商品库存表,那么得到的商品库存也肯定是相同的,判断的逻辑也是相同的。

举个例子,现在商品的库存是10件,请求1买6件,请求2买5件,由于两次请求查询到的库存都是10,肯定是可以卖的。 但是真实情况是5+6=11>10,明显有问题!这两笔请求必然有一笔失败才是

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值