供应链-OMS设计

一、概述

订单系统作为电商系统的“纽带”贯穿了整个电商系统的关键流程。其他模块都是围绕订单系统进行构建的。订单系统的演变也是随着电商平台的业务变化而逐渐演变进化着,接下来就和大家一起来解析电商平台的“生命纽带”。

订单系统的作用是:管理订单类型、订单状态,收集关于商品、优惠、用户、收货信息、支付信息等一系列的订单实时数据,进行库存更新、订单下发等一系列动作。订单系统业务的基本模型涉及用户、商品(库存)、订单、付款,订单基本流程是下订单——>减库存,这两步必须同时完成,不能下了订单不减库存(超卖),或者减了库存没有生成订单(少卖)。超卖商家库存不足,消费者下了单买不到东西,体验不好;少卖商家库存积压或者需要反复修改商品信息,反复麻烦,体验也不好。

订单管理就是从电商平台上获取买家订单,对订单进行一些处理后,将订单分配给仓库发货。电商订单的整个链路大致如下图所示,在复杂的商业模式下,商家订单类型多样,不同类型的订单的处理不尽相同。本文将探讨OMS系统关于B2C订单处理的产品设计思路。

二、订单基本概念

设计订单系统时包含几个大的方向需要考虑,这些内容决定了订单系统的稳定性和可持续性。

订单的多样性特点

主要由来源和操作的多样导致了订单多样性点。

订单字段

订单字段包含了订单中需要记录的信息,他的作用主要用于沟通其他系统,为下游系统提供信息依据。

订单信息

订单号作为订单识别的标识,一般按照某种特定规则生成,根据订单的增加进行自增,同时在设计订单号的时候考虑订单无序设置(防止竞争者或者第三方来估算订单量)。订单号后续用作订单唯一标示用于对接WMS(仓存管理系统)和TMS(运输管理系统)时的订单识别。

订单状态

订单状态在下面章节会详细描述

用户信息

指买家的相关信息,包括名称、地址、手机号。O2O还会多一种情况就是自提点,这样地址则会变为自提点的地址。地址信息在后续会作用在WMS和TMS上用于区分区域和配送安排。

商品信息

商品的基本信息和库存,金额由于比较特殊所以我把金额独立在商品信息以外说,不过逻辑上其实都属于商品信息范畴。商品信息主要影响库存更新和WMS产生。

金额信息

订单产生的商品信息,这里面除了要记录最终的金额,过程金额也需要记录。比如商品分摊的优惠金额、支付金额,应付金额等。在后续的订单结算、退换货、财务等环节都需要使用。

时间信息

记录订单每个状态节点的触发时间。

  1. 用户信息:用户帐号,用户等级。
  2. 订单基础信息:父订单与子订单、订单编号、订单状态。
  3. 收货信息:收货地址、收货人姓名、联系电话、邮编,
  4. 商品信息:SKU信息、规格、商品数量、价格、商品图片、所属商家。
  5. 优惠信息:优惠券、促销活动、虚拟币抵扣金额,
  6. 支付信息:支付方式、支付单号、商品总金额、实付金额、运费、虚拟币抵扣金额,促销优惠金额、优惠卷优惠金额、总优惠金额。
  7. 物流信息:物流公司、物流单号、物流状态。
  8. 其他信息:发票信息、下单平台、分销渠道。

三、订单流程

订单流程是指整个订单从产生到完成整个流转过程,包括了正向和逆向流程的过程。

正向流程

商品下单后流程:

  1. 在订单过程中进行安全校验,主要是检测用户是否在黑名单上, 用户购买的行为是否正常等,当检测到不正常时,终止下单。
  2. 从商品中心获取商品信息(SKU、规格、价格等信息)
  3. 从营销中心获取商品、订单促销信息(优惠券、促销活动、判断是否满足优惠条件,计算出优惠金额)。
  4. 在会员中心获取会员权益,例如平台抵扣积分,折扣条件等。
  5. 在调度中心校验销售层库存,按照规则锁定库存区域。
  6. 根据拆单规则(商家,仓库,订单类型)将订单拆分为若干子订单。
  7. 根据运费模板计算运费,根据商品金额,运费,优惠金额计算应付金额。
  8. 生成订单,订单状态为待付款 。

在存储订单信息中,主要包含以下内容:用户信息、订单基础信息、收货信息、商品信息、优惠信息、支付信息、物流信息、其他信息等等。

订单内容复杂精细,在存储时,除了表结构的设置,还应该注意信息冗余 。特别是商品信息,由于商品的内容不断发生编辑变化,要保存下单快照,避免过长时间后,商品信息丢失。

这里面主要是涉及主流电商系统中的通用订单流程,部分细节可以根据自己平台的特殊性进行调整。

需要注意的地方

  1. 订单生成环节存在超时未支付自动取消的过程,库存的占用会在订单取消后释放。
  2. 如果选择COD(货到付款)则支付环节相应转移到订单配送之后,而过程中所有与款项相关的逻辑变为只操作金额数字,不对结算和账户进行打退款操作。
  3. 金额分摊需要到商品
  4. 订单系统审核主要对恶意用户或者刷单情况进行处理。系统可根据白名单、黑名单、消费频次、促销品购买量方面做风控规则。如果后续会进入到人工审核,则规则上可以适当从宽。当触发规则需要进行订单退订的行为。此处设计时要小心对用户体验的损害,往往前台文案上说明当前节点是审核状态或者是等待接单。
  5. 传统电商则是通过关联第三方物流的物流信息进行跟踪。
  6. 预售等货和移仓需要做成SOA服务,以便在交易页面计算预计时间和预计到货时间。移仓处理依赖仓库的情况,也会涉及到后续拆分和合并包裹的逻辑。
  7. 订单产生时先要判断报缺情况,如果出现报缺问题则要考虑整单报缺、部分报缺、换货或者换转退的情况(库存,仓促调拨和退款)。报缺情况分为系统报缺和实物报缺,这是承接但相对独立的两个环节。
  8. 电商系统要考虑7天无理由退货的情景,即订单状态完成后申请退货。此时主要涉及的是金额上的计算以及一些财务程序(如发票等)问题的处理。
  9. 父订单和子订单:

如果从购物车选中多件商品时,例如选中三个商家的商品,会将这次购买行为拆分为三个订单,这次整体购买行为记录在父订单下。当系统首次提交订单结算时,会合并自订单,针对父订单进行结算,当提交提交订单后 ,结算中断,或者结算之后,系统在更新订单状态,物流跟踪,针对的是子订单。

逆向流程

逆向流程指订单发生取消、退货等情况时引发的订单流程过程。

触发逆向流程的触发主要有几种情况:

关注点

  1. 订单状态(某一节点后如订单产生后不允许取消订单)
  2. 当退单被商家拒绝后需要转入客服仲裁的环节
  3. 部分退的订单促销一般保持享用状态,但金额按照分摊的金额进行退款

订单状态

从订单状态设计目的和存在价值去分析和理解它背后设计机制:维度及维度颗粒度大小。

正向和逆向流程维度

服务对象维度

订单推送

当状态发生变化时,需要将对应的变化情况告知给相关人员以便了解当前订单的情况,这就是订单推送的作用。

订单推送的触发依赖于状态机的变化,涉及到的信息包括

四、履约单

商城订单支付后,同步订单信息生成履约单;通过业务相关节点(打标签、物流商匹配、报关规则匹配、拆合单、配货)处理后推送履约订单至WMS内进行履约流程。

五、订单系统设计的挑战和实践

订单系统需求演变

第一步:实现购买流程

  1. 实现订单的创建、发货、确认等信息闭环
  2. 支持订单审核(初期可支持人工审核即可)
  3. 支持用户端显示订单相关信息
  4. 支持促销金额的计算

第二步:提供服务

  1. 提供订单分布式服务
  2. 支持跨平台交易单生成(即同一个大交易单内既有商家商品又有自营商品或者是多个商家的商品)
  3. 支持拆单、合并逻辑(配送单、支付单等)
  4. 提供更丰富的订单推送服务,完善订单状态

第三步:支持不同营销手段下的订单类型

平台发展到足够大的规模,提效、稳定变成一个重要的话题。可以提供不同营销场景下的订单,如:团购、预购等。

订单系统架构的演变

最佳实践

实践1: 重试和补偿

实践2: 幂等性

实践3: 一致性实践

系统优化

数据库读写分离

基本的原理是让主数据库处理事务性查询,而从数据库处理SELECT查询。数据库复制被用来把事务性查询导致的变更同步到集群中的从数据库。 当然,主服务器也可以提供查询服务。使用读写分离最大的作用无非是环境服务器压力。

好处

  1. 增加冗余
  2. 增加了机器的处理能力
  3. 对于读操作为主的应用,使用读写分离是最好的场景,因为可以确保写的服务器压力更小,而读又可以接受点时间上的延迟。

数据库分库分表

不管是采用何种分库分表框架或者平台,其核心的思路都是将原本保存在单表中太大的数据进行拆分,将这些数据分散保存到多个数据库的多个表中,避免因为单表数据量太大给数据的访问带来读写性能的问题。所以在分库分表场景下,最重要的一个原则就是被拆分的数据尽可能的平均拆分到后端的数据库中,如果拆分的不均匀,还会产生数据访问热点,同样存在热点数据因为增长过快而又面临数据单表数据量过大的问题。

而对于数据以什么样的纬度进行拆分,大家看到很多场景中都是对业务数据的ID(大部分场景此ID是以自增长的方式)进行HASH取模的方式将数据进行平均拆分,这个简单的方式确实在很多场景下都是非常合适的拆分方法,但并不是在所有的场景中这样拆分的方式都是最优的选择。也就是说数据如何拆分并没有所谓的金科玉律,更多的是需要结合业务数据的结构和业务场景来决定。

下面以大家最熟悉的电商订单数据拆分为例,订单是任何一个电商平台都有的业务数据,每个平台用户提交订单都会在平台后端生成订单相关的数据,一般记录一条订单数据的数据库表结构如下:

订单数据主要由三张数据库表组成,主订单表对应的就是用户的一个订单,每提交一次都会生成一条主订单表的数据。在有些情况下,用户可能在一个订单中选择不同卖家的商品,而每个卖家又会按照该订单中自己提供的商品计算相关的商品优惠(如满100元减10元)以及按照不同的收货地址设置不同的物流配送,所以会出现子订单的相关概念,即一个主订单会由多个子订单组成,而真正对应到具体每个商品订单信息,则保存在订单详情表中。

如果一个电商平台的业务发展健康的话,订单数据是比较容易出现因为单个数据库表中的数据量过大而造成性能的瓶颈,所以需要对他进行数据库的拆分。此时从理论上对订单拆分是可以由两个纬度进行的,一个纬度是通过订单ID(一般为自增长ID)取模的方式,即以订单ID为分库分表键;一个是通过买家用户ID的纬度进行哈希取模,即以买家用户ID为分库分表键。

方案

  1. 每个订单指定唯一的订单号,订单号哈希除以32取余,存到相应的库和表;
  2. 用户端,建立user_order中间表,根据用户ID分表,此表字段:用户ID,订单号,时间。用户查询时,在此表查询分页排序,再根据订单号去相应的订单表查询详情;
  3. 商户端,建立merchant_order中间表,字段:商家ID,订单号,时间。商家查询时,查此表分页排序,获取订单号再去相应的订单表查询;
  4. 站点运营人员,如果想根据商户查,就用3,如果像根据用户查,就用2,如果想要全部订单按照时间排序,也根据时间建立中间表time_order,字段:时间,订单号,在这里查好后再根据订单号去查订单详情。

所以从对『数据尽可能平均拆分』这条原则来看,按照订单ID取模的方式看起来更能保证订单数据的平均拆分,但我们暂时不要这么快下结论,也要根据不同的业务场景和最佳实践角度多思考不同纬度带来的优缺点。

六、总结

电商平台的需求一直在变化,随之订单系统的架构也会随之变化,架构设计就是一个持续改进的过程,这篇文章还有好多细节未提及,如果你想把订单系统做的更好,需要更加深入系统的每一个环节,比如:容灾、灾备、分流、流控都需要慢慢雕琢,在架构中没有完美的架构只有平衡的架构,不要追求单点的完美,而是要追求多点的平衡。

展开阅读全文

页面更新:2024-05-09

标签:商品信息   金额   订单   流程   状态   商品   数据   用户   系统   信息

1 2 3 4 5

上滑加载更多 ↓
推荐阅读:
友情链接:
更多:

本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828  

© CopyRight 2008-2024 All Rights Reserved. Powered By bs178.com 闽ICP备11008920号-3
闽公网安备35020302034844号

Top