商城设计要点-库存超卖
...大约 2 分钟
商城设计要点-库存超卖
1. 简介
2. 库存扣减方式
2.1 下单减库存
即当买家下单后,在商品的总库存中减去买家购买数量。下单减库存是最简单的减库存方式,也是控制最精确的一种,下单时直接通过数据库的事务机制控制商品库存,这样一定不会出现超卖的情况。但是你要知道,有些人下完单可能并不会付款。
2.2 付款减库存
即买家下单后,并不立即减库存,而是等到有用户付款后才真正减库存,否则库存一直保留给其他买家。但因为付款时才减库存,如果并发比较高,有可能出现买家下单后付不了款的情况,因为可能商品已经被其他人买走了。
2.3 预扣库存
这种方式相对复杂一些,
- 买家下单后,库存为其保留一定的时间(如 30 分钟),超过这个时间,库存将会自动释放
- 释放后其他买家就可以继续购买
- 在买家付款前,系统会校验该订单的库存是否还有保留:
- 如果没有保留,则再次尝试预扣;
- 如果库存不足(也就是预扣失败)则不允许继续付款
- 如果预扣成功,则完成付款并实际地减去库存。
Mall 商城采用的方式类似于这种预扣库存的,
- 下单锁定库存
- 付款才真正减库存
- 超时付款时加库存
3. 解决方案
采用哪一种减库存方式更多是业务层面的考虑,减库存最核心的是大并发请求时保证数据库中的库存字段值不能为负数。
3.1 方案一:行级锁校验库存
通常在扣减库存的场景下使用行级锁,通过数据库引擎本身对记录加锁的控制,保证数据库的更新的安全性,并且通过where
语句的条件,保证库存不会被减到 0
以下,也就是能够有效的控制超卖的场景。
update ... set amount = amount - 1 where id = $id and amount - 1 >=0
- mall 商城项目未采用该方案
- Mall 商城并没有校验库存数量
3.2 **方案二:**数据库无符号整数
设置数据库的字段数据为无符号整数,这样减后库存字段值小于零时 SQL 语句会报错。
- mall 商城项目未采用该方案
- 数据库存储字段是int
stock int default 0 null comment '库存', lock_stock int default 0 null comment '锁定库存',
参考文章
赞助