Bootstrap

关于库存扣减方案的思考总结

文:修超

电商业务场景下,核心点主要围绕着用户(买家、卖家)、买家通过个性化的选择卖家商品,最终产生交易行为。整个电商业务流程是相当复杂的。不仅仅体现在业务上也体现在系统上,电商业务主要通过多个模块组成:比如会员、店铺、商品、交易、营销、支付、库存、物流、仓库、调度、风控等。通过各子模块领域的能力交互组合,串联出核心的交易流程。

在整个交易流程中,库存的处理是比较重要的,它包括商品的库存处理、营销权益的库存处理。从生命周期上来看有正向交易的库存扣减、逆向流程的库存回加。

在比如电商的营销场景,经常会遇到一些节日性的大促,比如双十一的红包雨的场景,该场景类似与秒杀,在整点即使上百万的用户同一时间涌入系统争抢红包。但红包本身是有限的,这就要求需要在极端的时间内对红包的数量做正确的扣减,比如每秒扣减200w次。但任何系统、机器都有其物理瓶颈存在。如何既能保证用户顺利领取到红包又不超发就成为一项非常困难的事情。

本文梳理介绍下常见库存的扣减方法

扣减的常用方案

常见的库存方案主要分为如下3种,可根据目前业务的发展情况,系统的能力诉求选择

  • 单库单记录

最常见的做法,主要存在是热点问题(大预算)、性能问题(数据库瓶颈),这种模式是得物之前的做法

  • 分库单记录

通过单库增加到多库,按照库存ID取hash均匀share的方式,提高性能,主要存在热点问题(大预算),目前得物的做法

  • 分布式多记录

库存提前分配到多个桶中,不同用户路由到不同的桶中,主要存在碎片问题、流量不均问题、动态扩容问题

不管哪种方案都是服务于业务的,选择合适的才是最好的。甚至于在个别业务场景下,库存的扣减是可以完全降级的

前面两种方案是相对比较简单的,下文主要介绍下分布式多记录情况下的扣减方案怎么做

分布式扣减方案

如果要支持上百万的TPS指标,整体的方案措施总结可以抽象做到如下三个点:

  1. 采用分片的方式(水平扩展方式解决单点),合理利用集群服务器及db的资源。在整体系统架构上解决单点性能瓶颈问题
  2. 分片后,针对单热点扣减采用一定的手段进行极致的优化(全缓存)
  1. 分片后,流量不均(预算动态分配),碎片(预算动态回收与重新分配)以及分片伸缩问题,通过master分配和slave分配的方式(主、子预算)进行解决

简单的分桶扣减

总结:存在流量不均、碎片、分片伸缩问题

桶集中管理扣减

通过增加扣减策略模块、库存调配模块(集中式管理)、请求调度策略(用户请求动态调度),三个模块的职责如下:

  • 库存策略模块:决定了库存应当如何被发放,将扣减链路中可敢于因素予以抽取,使得库存在扣减过程中能够被系统以及业务影响,从而扣减链路具备足够的扩展性,能够做到跟随业务动态变化
  • 库存调配模块:从新定义了库存分配策略,用于做个性化的按需分配,库存不在是一刀切分配在各个桶中,而是随着发放速率的变大而变大,桶流量越大给分配的库存也就越多。同时该模块实施监控整个发放链路,对库存不足以支撑发放的桶依据规则动态扩容、或者停止该桶的发放
  • 请求调度模块:能够动态调配扣减请求,以保证请求永远能够被路由到有库存的桶执行扣减

库存汇总:

目前得物这边采用的方式是分库和总库双向同步的模式汇总的。其实还有一种做法,可以通过增加“预算调度模块”,用户汇总各分库存的预算实时情况,然后借助缓存体系存入,用于使用场景的准实时读取。

总结

分布式基本是解决高并发库存扣减场景下唯一方案,不论是分桶还是将库存拉到本地执行扣减,都是这一思路。库存数据由集中式切换为分布式一定会带来更高复杂度的问题,而该问题是无法完全解决的,但我们可以采取各种方案尽力去降低该问题出现的概率,或者最大可能缓解该问题的影响面。

库存扣减涉及的技术点较多,包括远程的redis缓存、甚至本地缓存、锁机制、XTS事务,动态路由算法、最终一致性的消息通知等,还是很有技术挑战的。另外在库存扣减的策略上也很多技术的挑战点。比如基于db的扣减,调整为基于缓存的扣减,毕竟db的扣减受分表分库的最大数量限制,调整为通过缓存可以实现质的突破;另外在库存扣减提交上也可是做组提交的缓冲模式,缓冲模式一般在账务系统中是被广泛采用的方案,主要通过合并多次扣减请求,然后统一输入db的方式,这样可以有效降低热点减少锁并法。

此外库存扣减这块,限流、降级、容灾应急(借助分布式配置管理,比如nacos达到动态干预),监控、核对等稳定性运维相关的模块也是必不可少的。

;