库存扣减超卖和少卖解决方案(数据库机制/redis自减)

☁️博客首页:CSDN主页 搖了我吧的主页
📜 欢迎大家关注! ❤️


前言

所谓“超卖”指的就是商品卖多了,一般我们在商品扣减库存的时候,都会先判断库存够不够,如果够在进行扣减,不够则直接返回下单失败。但是,如果在高并发场景中,可能存在以下情况:

在这里插入图片描述

当有两个并发线程,同时查询库存,这时数据库中库存剩余1,所以两个线程都得到1的库存,然后经过库存校验之后分别开始进行库存扣减,最终导致库存被扣减成负数。

之所以会发生以上问题,主要是因为并发导致的,所以,解决超卖的问题本质上是解决并发问题。以上问题,最终就是要实现库存扣减过程中的原子性和有序性。

原子性:库存查询、库存判断以及库存扣减动作,作为一个原子操作,过程中不会被打断,也不会有其他线程执的。
有序性:多个并发操作需要排队执行。

商品一般分为普通商品和秒杀商品,这里结合业务采用不同的解决方案来防止库存超卖。


一、普通商品

普通商品的特点:

1、购买的时间相对分散
2、可以一次购买多个

根据普通商品的特点,我们可以借助数据库自己执行引擎的顺序执行机制,只要保证库存不要扣减成负数就行了,那么可以通过SQL语句就能控制:

update inventory
set quantity = quantity - #{count}
where sku id = '123' and quantity >= #{count}

也就是说,如果上述SQL可以执行成功的话,是可以确保库存余量大于等于0的,这就避免了超卖的发生。

看到这里,有些大牛会站出来说了,你这个方案不好。这种方案完全依赖数据库,并且高并发情况下,多个线程同时update inventory 的时候会发生阻塞,不仅会很慢,还会把数据库拖垮的。巴拉巴拉……
这里我想说,如果你普通订单的下单能把mysql搞跨,那应该不至于没钱升级数据库吧。其实想不依赖数据库也可以通过其他技术来解决超卖,但他们都缺乏可靠性,而且还会增加业务的复杂度。咱考虑业务的同时也要考虑实际情况,对不对?要是我的系统因为这条语句把数据库跑垮了我做梦都得笑醒~

二、秒杀商品

秒杀商品的特点:

1、购买的时间相对集中
2、正常一次只能购买一个
3、需要设置秒杀商品和库存数量

一般来说,秒杀商品是需要在后台添加的,所以我们要编写两个接口:

1、添加秒杀商品

    /**
     * 添加秒杀商品
     * @author LiChangRui on 2024/3/15 13:59
     */
    @Operation(summary = "添加秒杀商品")
    @PostMapping("/createInstantGoods")
    public Result<?> createInstantGoods() {
        redisService.set("instantGoods:" + "这里是商品id", 这里是库存数量);
        return Result.ok();
    }

2、购买秒杀商品

    /**
     * 购买秒杀商品
     * @author LiChangRui on 2024/4/25 13:38
     */
    @Operation(summary = "购买秒杀商品")
    @Parameters({
            @Parameter(name = "goodsId", example = "1"
            , description = "商品id", required = true, in = ParameterIn.QUERY)
    })
    @GetMapping("/buyInstantGoods")
    public Result<?> buyInstantGoods(@RequestParam("goodsId") String goodsId) {
        Long decr = redisService.decr("instantGoods:" + goodsId, 1);
        if (decr < 0) {
            redisService.incr("instantGoods:" + goodsId, 1);
            System.out.println("库存不足");
            return Result.error500("库存不足");
        }

        return Result.ok();
    }

总结

如果您发现错误,还望及时提醒,共同进步。

  • 8
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值