作者:vivo官网商城开发团队 – Xu Yi、Yan Chao

本文是vivo商城系列文章,首要介绍vivo商城库存体系开展进程、架构规划思路以及应对事务场景的实践。

一、事务布景

库存体系是电商产品办理的中心体系,本文首要介绍vivo商城库存中心开展进程、架构规划思路及应对各种事务场景的实践。

vivo商城原库存体系耦合在产品体系,考虑到相关事务逻辑复杂度越来越高,库存做了服务拆分,在可售库存办理的根底上新增了什物库存办理、秒杀库存、物流时效 、发货约束、分仓办理等功用,满意了商城库存相关事务需求。

本文将介绍vivo商城库存体系架构规划经验以及一些问题的处理计划。

二、体系架构规划

2.1 vivo大电商库存架构

依据vivo大电商的出售途径与事务场景能够将库存事务架构分为3个层级:库房层、调度层以及出售层。

库房层对应实体库房,包含自营库房、顺丰仓等第三方库房以及WMS体系、ERP体系等;调度层担任库存调度与订单发货办理;出售层包含多个服务终端,vivo官方商城、vivo门店、第三方电商分销途径等。其分层结构如图所示:

vivo全球商城:库存系统架构设计与实践

本文讨论的vivo官方商城库存架构规划,从整个vivo大电商库存架构来看,vivo官方商城库存体系触及出售层内部架构以及出售层与调度层的交互。

2.2 商城库存体系架构演变

前期商城的库存冗余在各事务体系中,如可售库存在产品体系、活动库存在营销体系等,库存流通也只要扣减与开释,无法针对库存进行整合与事务立异,存在诸多约束:

  • 不能进行精细化办理,库存未分层,无法针对什物库存、分仓战略、活动库存进行精细化办理。

  • 没有分仓战略,无法提前获取产品收发地址,物流时效无法估算。

  • 无法针对区域、产品等进行发货管控。

  • 实时性差,无法及时同步什物库存以及分仓战略。

  • 功用弱,与其他体系耦合大,不能灵活扩展。

依据上述约束与产品期望,21年库存体系完结初版架构规划,此后体系不断迭代完善,形成当时的体系架构:

vivo全球商城:库存系统架构设计与实践

库存体系供给两个中心才能:交易才能和库存办理。上层事务方能够调用供给的API完结库存查询、库存扣减等操作;办理台能够按成分仓战略、库存同步等操作。

三、体系事务架构

3.1 库存类型&分仓办理

3.1.1库存类型结构

库存体系总共包含4类库存:可售库存、什物库存、预占库存、活动库存。

  • 可售库存:运营装备的普通产品库存,产品维度到SKU。

  • 什物库存:由仓储体系同步到库存体系的什物库存,细化到详细库房。

  • 预占库存:用户下单完结库存预占,仓储体系发货后开释预占库存,预占库存能够监控已下单未发货库存量。

  • 活动库存:用于秒杀、抢购等各类营销活动的产品库存。

依据不同类型库存,能够构建一个简略的库存分层体系:

vivo全球商城:库存系统架构设计与实践

3.1.2 分仓办理

库存中心还维护了库房信息、分仓战略、库房什物库存信息等等:

  • 库房信息:库房根底信息,包含库房地址、类型、编码等。

  • 分仓战略:库房功用信息,库房可发货区域、无什物库存后的备选库房;订单依据收货地址对应优先发货的库房,争夺尽快发货尽早到货。

  • 库房库存:库房什物库存,由库房调度体系同步到商城库存体系。

3.2 商城库存流通计划

产品库存流通触及两个首要操作:正向库存扣减、逆向库存回退,整套库存改变流程如下:

vivo全球商城:库存系统架构设计与实践

3.2.1 正向库存扣减流程

关于库存扣减,现在常见有两种库存扣减计划:

(1)下单时扣库存。

  • 长处是:实时扣库存,防止付款时因库存缺乏而阻断影响用户体会。

  • 缺点是:库存有限的情况下,歹意下单占库存影响其他正常用户下单。比方说有100台手机,假如没有约束下单数量,这100个库存或许被一个用户歹意占用,导致其他用户无法购买。

(2)付出时扣库存。

  • 长处是:不受歹意下单影响。

  • 缺点是:当付出订单数大于实践库存,会阻断部分用户付出,影响购物体会。比方说只要100台手机,但或许下了1000个订单,但有900个订单在付出时无法购买。

从用户体会考虑,咱们选用的是下单时扣库存 + 回退这种计划。

下单时扣减库存,但只保存一段时刻(比方15分钟),保存时刻段内未付出则开释库存,防止长期占用库存。

3.2.2逆向库存回退流程

库存回退依据库存改变日志逐个回退。

库存回退基本流程:订单出库前用户恳求退款,回退可售库存、回退预占库存、软删除扣减日志、添加回退日志;一旦产品出库,用户恳求退货走处理机流程,可售库存和什物库存均不回退。

vivo全球商城:库存系统架构设计与实践

3.3精细化发货管控

库存体系还供给了一系列定制辅佐功用:分仓战略、发货约束、物流时效等等。

(1)分仓战略

为了给用户更快的发货,咱们选用的是分仓战略,即由最近的库房(存在优先级)给用户发货;一起存在备选库房,当所有库房无什物库存时可走备选库房。

3.3.1发货约束

发货约束分区域约束时刻约束。

  • 区域约束:依据收货地址批量设置部分区域无法发货等规则,粒度到省市区维度。

  • 时刻约束:库房的发货时效办理,包含每天的发货时段、大促发货时段、以及特别情况下的停发时段。

3.3.2物流时效预估

依据用户收货地址,依据分仓战略确认发货地址,再依据发货时效确认发货时刻,提高用户体会。

vivo全球商城:库存系统架构设计与实践

四、体系架构技能要点

4.1 库存扣减防重

订单重复提交会导致库存重复扣减,比方用户误提交、体系超时重试等,针对此类问题有如下常见处理计划:

  1. 订单提交按钮单击置灰,防止重复提交。注:关于按钮置灰这种计划,能够减少用户误触重复提交的或许性,但不能从根本上处理库存被重复扣减的问题,比方经过脚原本刷扣减库存的接口,仍旧造成库存的重复扣减。

  2. 确保库存扣减接口的幂等性。注:确保接口幂等的计划有许多,比方每次扣减库存时,带上仅有的流水号,使用数据库的仅有索引确保幂等等。

  3. 选用令牌机制。用户提交订单会进行令牌校验,校验经过才能提交订单。注:这种计划确保每次提交的订单是仅有的,假如用户多次下单,那么会产生多个订单。

本体系选用的是确保接口幂等性的计划。

在库存扣减接口入参中添加订单序列号作为仅有标识,库存扣减时添加一条扣减日志。当接口重复恳求时,会优先校验是否现已存在扣减记载,假如已存在则直接回来,防止重复扣减问题,详细流程如下:

vivo全球商城:库存系统架构设计与实践

4.2 防超卖与高并发扣减计划

4.2.1惯例途径防超卖计划

惯例下单途径流量小且对超卖风险讨厌度极高,常用的防超卖计划有:

计划一:

直接数据库扣减。经过sql判别剩下库存是否大于等于待扣库存,满意则扣减库存。该计划使用乐观锁原理即update的排他性确保事务性,防止超卖。

伪代码sql:

sqlupdate store set store = store - #{deductStore } where (store-#{deductStore }) >= 0

该计划的长处是:

  • 实库实扣,不会呈现超卖;

  • 数据库乐观锁确保并发扣减一致性;

  • 数据库事务确保批量扣减正常回滚。

该计划的缺点是:

  • 行级锁的原因存在功用瓶颈,高并发会呈现恳求堵塞超时问题;

  • 直连数据库,每次扣库存都是写操作,接口功用较低。

计划二:

使用分布式锁,强制串行化扣减同一产品库存。

该计划的长处是:

减轻数据库压力,一起还能确保不会超卖。

该计划的缺点是:

每次只能有一个恳求抢占锁,不能应对高并发场景。

关于惯例途径,库存扣减是后置逻辑,流量不高,咱们选用的是直接数据库扣减,且针对弊端做了一些办法

  • 前置校验严格,一起针对刷单场景会有严格限流,确保终究扣减库存的流量可控;

  • 库存体系读写分离,减少数据库的压力。

4.2.2高并发库存扣减计划

针对高并发库存扣减,比方秒杀,一般选用的是缓存扣减库存的方法(redis+lua脚本完结单线程库存更新)作为前置流程,替代数据库直接更新。

在redis中扣减库存尽管功用高,能够大大减轻数据库压力,但需求确保缓存数据能完好、正确的入库,以确保终究一致性。

针对缓存数据更新至数据库,现在干流计划有两种:

计划一:Redis数据直接异步更新至数据库。

vivo全球商城:库存系统架构设计与实践

长处:简略、没有复杂的流程。

缺点:redis宕机或者故障,或许会造成缓存内库存数据的丢掉。

计划二:Redis扣减库存时,同步在事务数据中insert库存信息。

vivo全球商城:库存系统架构设计与实践

这里咱们或许会有两个疑问:

  1. 有数据库的刺进操作,功用怎样确保?

  2. 有数据库的操作,又有redis的更新,事务性怎样确保?

  3. 异步更新事务库存在推迟,库存逆向回退怎么确保?

关于疑问1:因为数据库insert比update功用优,insert是在表的结尾直接刺进,没有寻址的过程,能够确保功用比较快。

关于疑问2:计划2不同于缓存直接扣减,而是把缓存扣减放在数据库insert的事务内,经过数据库的事务确保全体的事务。

insert的表被称为库存使命表,其间保存了库存扣减的信息,库存使命表结构能够规划的十分简略,主键 + 库存信息(json字符串)就能够了。

后续经过异步使命,从库存使命表表中查询出库存更新信息,将其同步到详细的库存表中,完结终究一致性,这种计划能够防止数据的丢掉。

关于疑问3:库存回退是依据事务库中扣减记载进行回退的,因为异步更新事务库必定存在推迟(推迟极低,数秒以内),所以极端场景会存在走退款逆向流程时事务库的库存扣减记载还未更新。

针对这种情况库存回退设置推迟重试机制,假如再极端点达到重试阈值仍旧没有扣减记载,则回来回退成功,不做阻断。

现在咱们针对秒杀库存扣减,选用的是计划2。但毕竟触及数据库的更新,为了防止风险,在前置流量校验上做了约束,确保流量的可控:

vivo全球商城:库存系统架构设计与实践

4.2.3库存热门问题

什么是热门问题?热门问题便是因热门产品导致的redis、数据库等功用瓶颈。在库存体系中,热门问题首要存在

  • 选用直接扣减库存数据库的方法,存在数据库的行锁问题。惯例途径的库存扣减,咱们选用的便是的便是这种方法。

  • 选用缓存扣减库存的方法,大流量的情况下,热门产品扣减库存操作会打向redis单片,造成单片功用颤动,从而呈现redis功用瓶颈。

关于第1种热门问题,在vivo商城常见的场景是:新发的爆品手机,在准点售卖时会有抢购效应,简略造成库存数据库单行的瓶颈问题。针对这种热门问题,咱们的处理计划是“分而治之”:

vivo全球商城:库存系统架构设计与实践

关于潜在的热门爆款手机,咱们会将库存平均分为多行(比方M行),扣减库存时,随机在M行中选取一行库存数据进行扣减。该计划突破了数据库单行锁的瓶颈约束,处理了爆款产品的热门问题。

关于第2种redis单片热门问题,处理计划也是分而治之。将数据库中的库存数据同步到redis时,把key值打散,涣散在多个redis单片中。注:咱们现在线上的流量峰值还达不到会造成redis单片瓶颈的问题,为防止过度规划,只做了前置限流,没有进行key值的打散。

4.3 库存同步计划

库存体系存在一些库存同步场景:

  • 对接仓储体系,完结什物库存同步。

  • 兼容历史架构,产品体系库存的可售库存同步等。

(1)什物库存同步:

什物库存同步,对接的是仓储体系,经过接口来获取产品的实践库存。什物库存同步分红两种:守时全量同步、指定单品更新。

  • 守时全量同步:每天守时全量拉取库存调度渠道的什物库存进行全量同步。

  • 制定单品:运营也能够手动触发单个sku的产品即时同步什物库存。

(2)产品体系库存同步:

因为库存体系多个场景触及库存改变,运营手动修改、用户下单退款导致库存扣减回退,还有产品体系内修改库存数据也会导致库存改变(曾经库存体系未独立,库存数据维护在产品体系)。一起许多事务在查询库存时,参阅的仍旧是产品体系的库存数据。

这里有一个问题:库存体系现已独立出来,为什么还会依靠产品体系的库存数据?

这有两点原因

  • 商城多个事务的后台有产品挑选的需求,产品挑选会有库存数量的挑选项。产品数量许多,挑选是分页的,假如将库存数据悉数替换成库存体系的,那么存在跨体系分页问题,分页挑选会存在问题;

  • 历史遗留问题,许多事务方依靠的是产品体系的库存数据(包含依靠产品库存离线表的事务方),悉数切换到库存体系,成本和影响范围大。

因而,咱们需求确保产品体系和库存体系两边库存数据的一致。

库存改变场景多,为了降低事务复杂度、选用简略的方法完结库存同步,咱们使用了团队自研的CDC体系(鲁班渠道),全体流程如下:

vivo全球商城:库存系统架构设计与实践

库存数据库发生改变后,鲁班渠道经过binlog收集获取库存改变日志,再经过自定义规则挑选,然后发送mq改变消息,最终产品体系消费消息完结库存同步改变。

五、总结及展望

最终对库存体系进行一个总结

库存体系完结服务拆分,在单一的可售库存扣减功用根底上拓展了许多功用,赋能事务的开展。

完结库存架构分层,笼统多个库存类型,更灵活地满意当时事务需求。

针对库存扣减防重、高并发场景下的库存扣减、库存热门问题、库存同步等技能问题,咱们依据事务实践情况规划合理计划。

展望

现在vivo商城库存体系渠道化才能缺乏,部分才能涣散在其他体系中,未来咱们期望能为vivo新零售供给一体化的库存办理计划。