前言

我们本文来聊聊常见的超卖的相关问题。

一.为什么会发生超卖的情况?

超卖: 在电商场景下100个人抢100件商品,比如其中有一个人抢2件,就会发生超卖的问题,最后库存变成负数。

出现超卖的原因:没有控制库存的手段、或者控制库存的方式有问题

例如,下面的减库存的语句就没有进行任何的控制,就会发生超卖现象:

1
update goods set amount=amount-{orderAmount} where goods_id=1;

二. 怎么减库存

第一种方案,加上限制条件(悲观锁或者乐观锁),如下例子加上悲观锁:

1
update goods set ammount=ammount-{orderAmount} where goods_id=1 and ammount>1;

第二种方案,设置amount为无符号的数值类型,当减库存amount为负数时就会抛出异常。

三. 减库存的时机

  1. 订单环节

    优点:不会发生超卖

    缺点:容易被攻击,比如竞争对手恶意下大量的单,而不支付,那么其他用户就无法下单了。

  2. 支付环节

    优点:避免了恶意用户

    缺点:会发生下单成功但付款的时候提示库存不足,那么就会发生退款现象,用户体验差

  3. 订单环节预减库存,支付环节实扣库存,设置一个n分钟的支付超时时间释放库存

我们还可以采取一些风控手段,诸如避免被恶意账号攻击,我们可以采取限制竞争对手ip、恶意账号、限制下单不付款的笔数等手段。

四. 高并发场景下减库存

高并发场景下性能的瓶颈在DB(数据库例如MySQL)。

我们常用的解决高并发场景下问题,有如下几种方案:

  1. 检查库存的逻辑前置:随机拒绝部分请求(前端直接随机拒绝或者后端随机拒绝)、放redis中缓存扣库存;

  2. 限流,超出流量提示;

  3. 可以采用消息队列等将并发请求串行化;

  4. 分片/分段的思想,比如将总量为10000的数据进行分段,10000/10,分10个,分别访问段,来减少并发问题;

  5. 隔离的思想,将秒杀商品(或预知高流量的商品)独立出来,避免影响其他商品

总结

从超卖发生的原因、如何减库存、减库存的时机、高并发情况下的减库存这四个方面来聊了聊超卖的问题。