目录
订票系统逻辑顺序
下单减库存
支付减库存
预扣库存
订票系统逻辑顺序
我们就要想明白一件事:通常订票系统要处理【生成订单】、【减扣库存】、【用户支付】这三个基本的阶段。
这三个阶段的先后顺序该怎么分配才更加合理呢?
会有这个疑问?
1、订单系统是“先下单(创建订单)再减库存”,还是“先减库存再下单”?
答案:按常理是:先下单再减库存?
2、 一个人买了2件A商品,那么会生成几个订单?1个还是2个?
答案:1个订单;
下单减库存
这种顺序是我们一般人首先会想到的解决方案,这种情况下也能保证订单不会超卖,因为创建订单之后就会减库存,这是一个原子操作。
但是这样也会产生一些问题:
- 在极限并发情况下,任何一个内存操作的细节都至关影响性能,尤其像创建订单这种逻辑,一般都需要存储到磁盘数据库的,对数据库的压力是可想而知的。
- 如果用户存在恶意下单的情况,只下单不支付这样库存就会变少,会少卖很多订单,虽然服务端可以限制 IP 和用户的购买订单数量,这也不算是一个好方法。
支付减库存
如果等待用户支付了订单在减库存,第一感觉就是不会少卖。但是这是并发架构的大忌,因为在极限并发情况下,用户可能会创建很多订单。
当库存减为零的时候很多用户发现抢到的订单支付不了了,这也就是所谓的“超卖”。也不能避免并发操作数据库磁盘 IO。
预扣库存
请求----redis减库存----创建订单----支付
从上边两种方案的考虑,我们可以得出结论:只要创建订单,就要频繁操作数据库 IO。
那么有没有一种不需要直接操作数据库 IO 的方案呢,这就是预扣库存:我们采用 Redis 存储统一库存,因为 Redis 的性能非常高,号称单机 QPS 能抗 10W 的并发;
先扣除了库存,保证不超卖,然后异步生成用户订单,这样响应给用户的速度就会快很多;
那么怎么保证不少卖呢?用户拿到了订单,不支付怎么办?
我们都知道现在订单都有有效期,比如说用户五分钟内不支付,订单就失效了,订单一旦失效,就会加入新的库存,这也是现在很多网上零售企业保证商品不少卖采用的方案。
订单的生成是异步的,一般都会放到 MQ、Kafka 这样的即时消费队列中处理,订单量比较少的情况下,生成订单非常快,用户几乎不用排队。