• 互联网电商大厂库存系统设计案例讲解


    1 库存扣减

    多人同时买一件商品时(假设库存充足),每个人几乎同时下单成功,给人一种并行感觉。但真实情况, 库存只是一个数值,无论是存在mysql数据库还是redis缓存,减值时都要控制顺序,只能串行来扣减,当然为保证安全性,会设计一些锁控制。

    1.1 关键技术点

    • 同一个SKU,库存数量是共享

    • 剩余库存要大于等于本次扣减的数量,否则超卖

    • 对同一个数量多用户并发扣减时,要注意并发安全,保证数据的一致性

    • 类似于秒杀这样高QPS的扣减场景,要保证性能与高可用

    • 对于购物车下单场景,多个商品库存批量扣减,要保证事务

    • 如果有 交易退款 ,保证库存扣减可返还

      • 返还的数据总量不能大于扣减的总量
      • 返还要保证幂等
      • 可以分多次返还

    1.2 数据库扣减

    主要依赖数据库特性,保证扣减的一致性,逻辑简单,开发部署成本低。

    1.2.1 依赖的数据库特性
    • 依赖数据库的乐观锁(如版本号或者库存数量)保证数据并发扣减的强一致性
    • 事务,针对购物车下单批量扣减时,部分扣减失败,数据回滚

    最上面会查询当前的剩余库存(可能不准确,但没关系,这里只是第一步粗略校验),前置校验,如果已经没有库存,前置拦截生效,减少数据库写。毕竟读操作不涉及加锁,并发性能高。

    2 数据库表

    2.1 库存表

    create table t_inventory
    (
        sku_id        bigint null comment '商品规格 id',
        leaved_amount int    null comment '剩余可购买数量'
    );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 当用户取消订单,申请退货、退款,需将数量加回来
    • 若商家补库存,需在此基础额外加上增量库存

    2.2 流水表

    create table t_inventory_flow
    (
        id              bigint auto_increment comment '主键 id'
            primary key,
        sku_id          int        null comment '商品规格 id',
        order_detail_id mediumtext null comment '订单明细 id',
        quantity_trade  int        null comment '本次购买扣减的数量'
    );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 用于查看明细、对账、盘货、排查问题
    • 扣减后,某些场景下做返还,也还依赖流水

    2.3 单条商品的扣减SQL

    update inventory 
    set leaved_amount = leaved_amount - #{count} 
    where sku_id='123' and leaved_amount >= #{count}
    
    • 1
    • 2
    • 3

    乐观锁实现原子性,在 where 条件里判断此次购买的数量≤剩余的数量。在扣减服务的代码,判断此 SQL 的返回值,若:

    • 值为 1 ,表示扣减成功
    • 否则,返回 0 ,表示库存不足,需回滚

    2.4 扣减成功后,记录扣减的流水,并与订单明细记录关联

    1. 当用户归还数量时,需带回此编号,标识此次返还属于历史上的具体哪次扣减。

    2. 进行幂等控制。当用户调用扣减接口出现超时,因为用户不知道是否成功,用此编号进行重试或反查。在重试时,使用此编号进行标识防重

    3 数据库扣减方案:第一次升级

    极端例子:秒杀库存只有5件,活动期间峰值QPS 10W,活动结束后,上面的流水表最终只会插入5条记录,但查询QPS 10W。

    所以,数据库扣减方案第一次升级主要针对 库存前置校验 模块的优化,作为前置拦截器,承载流量很大,若将流量全部压到主库,很容易把数据压垮。

    考虑数据库架构升级:

    采用了 读写分离 方式,新增加了一套从库,借助mysql自带的数据同步能力。 库存校验时读取从数据库。

  • 相关阅读:
    通过删除字母匹配到字典里最长单词
    说几句得罪人的大实话
    Spring面试题23:Spring支持哪些事务管理类型?Spring框架的事务管理有哪些优点?你更倾向用哪种事务管理类型?
    SMOGN算法Python实现:解决回归分析中的数据不平衡
    vue指令(代码部分二)
    Javaweb之javascript的详细解析
    Hadoop运维工具箱之HDFS集群扩容与缩容-尚硅谷大数据培训
    NSA SELinux将在Linux 6.6中去品牌化为SELinux
    10 在线逻辑分析仪的使用
    Java SE 11 新增特性
  • 原文地址:https://blog.csdn.net/qq_33589510/article/details/127956142