这个有好多文章可以读啊,我来简单总结写一下。首先根据经验,这种高频访问的服务,另起一个单独的微服务工程。
一、同步扣库存。一般不推荐。
在订单生成时直接扣库存,这种方式比较简单,会造成很多订单把库存扣除而并没有支付,这就需要后台有一个job,定时将一段时间内没有支付的订单占有的库存释放,并把订单取消掉。实时扣库存的并发性能也很差。不推荐使用。
二、异步扣库存。
支付前是扣可销售库存(在redis中),是锁定库存的过程,支付后出库是扣仓库库存(在数据库中),保证库存最终一致。
库存一般分为仓库库存和可销售库存。仓库库存一般持久化在数据库中,增减库存的操作必须在一条语句中执行,不能先select再update,这样在并发下会出现超增减的情况。可销售库存缓存在redis中,使用redis的incrby特性来增减库存。
1、当入库新增了库存,仓库库存和可销售库存都需要增加库存,这个由分布式事务来保证最终一致性,控制可销售库存和仓库库存要么全加上入库库存,要么全不加入库库存。
2、当订单生成的时候,需要先扣除可销售库存,如果可销售款库存扣除成功,则生成订单进行支付。当可销售库存扣完了,这个产品就无法下单了。
3、扣除可销售库存成功后生成订单,支付成功返回订单详情, 就会有一个出库配送的过程。出库过程一般是一个MQ异步解耦的任务队列,队列可以起到缓冲,避免请求过多,让应用程序或数据库崩溃,这个过程会扣除仓库库存,如果扣除仓库库存成功,那么出库成功进入到发货状态,如果扣除仓库库存失败,那么就会出库失败,取消订单返还可销售库存并退款给客户。
4、在极端情况下会存在可销售库存和仓库库存数据不一致。
4.1、如果可销售库存比仓库库存少,不会有超卖问题,但会存在实际有库存,但是没有卖的情况。需要同步库存机制来保证可销售库存的新鲜度。
4.2、如果可销售库存你比仓库库存多,就会超卖,超卖的订单,在出库的过程中会失败。这样总体不会出问题,数据库层的仓库库存保证库存最终不会出问题。
4.3、可销售库存和仓库库存不一致的问题,一般在一个业务低峰期或者维护期进行周期性的强行同步覆盖可销售库存=仓库库存-在途库存。12306的订票系统半夜就有一个时间段的维护期。买票的时候有个出票的弹窗过程,估计就是在扣数据库的库存。
PS:在12306经常买票的同学,应该都遇到过查询有票,但是就无法下单。也会遇到在维护期前没票了的,第二天早上又有几张票了的车次。
学海无涯,爱学习就会有收获
来电咨询