订单系统设计-基础篇

1. 电商基础架构

1.1 订单模块作用

电商所有模块中,订单系统作为最为核心的模块,决定了整个流程能不能顺畅的执行,起着承上启下的作用(下单、支付、履约、售后、清结算、营销活动)。

1.2 架构设计图

订单系统设计-基础篇_第1张图片
这个是我们正在迭代完善的B2B2C的SaaS电商架构设计,可以看出来订单模块的重要性,我在项目中主要负责是订单中心、商品中心和活动中心,本次重点分享订单中心设计和相关问题。

1.3 订单系统核心组成

订单系统的设计主要需要考虑订单字段、业务流程、状态机三大个方面,这些内容决定了订单系统稳定性与扩展性。

2. 订单字段

2.1 订单字段内容

订单系统设计-基础篇_第2张图片

2.2 订单字段说明

商品信息
商品信息属于订单系统的上游端,所有订单都是从商品演进而来,从商品到订单,订单系统必须搜集相关的商品信息,包括店铺信息,商品id,商品规格,商品数量,商品价格。获取到的商品信息将在订单详情页内展示,形成订单信息后供仓库方便拣货,包装。
由于我们产品特殊性,商户是可以对商品改价,则这里订单绑定的商品价格有2种:商户成本价格(平台给到商户的成本价格,作用于B端用户)、商品销售价格(商户调价后商品价格,作用于C端用户)。
用户信息
用户信息包括购买用户的ID,收货人,收货地址,联系方式。
金额信息
因为金额信息的特殊性,所以独立出来讲,理论上金额信息应归属商品信息。金额信息的特殊性在于其不止一种金额,其涉及到商品金额,优惠金额,支付金额。而优惠金额中涉及到的信息较复杂,像有自营和第三方入驻的电商平台,都会有商家优惠和跨店优惠,而这些优惠又分不同类型,例如现金扣减,消费券扣减,积分获取,礼品卡扣减,或者以上几种的组合使用。想要涉及好这一块内容,需要根据目前自己公司的业务情况,列出所支持的优惠类型,再枚举出各种组合下的优惠类型,才能保证流程的完整性。
我们SaaS电商产品 支持C端用户用 积分、优惠券、余额、福利卡和现金多种混合方式支付,在设计订单计算和订单退款时也相当麻烦,下次再分享。
时间信息
记录各个卡点下的时间,一是记录,二也是方便售后验证和客户分析。订单时间是根据订单状态改变而改变的,比如:我们常见的用户下单未付款、待发货状态、待收货状态、交易完成状态、待退款状态、交易关闭-用户取消、交易关闭-仅退款、交易关闭-退货退款(包含部分仅退款)等。
订单信息
订单信息在订单系统最为核心,订单信息最重要的又是订单状态,那到底什么是订单状态机?
我个人的理解是:在订单中,通过各种购物情景,触发订单状态,将订单的流转可视化,是订单状态机的一种具体呈现形式,而它实质就是在描述订单状态的转换。

3. 订单流程

3.1 订单业务流程图

订单系统设计-基础篇_第3张图片
订单流程是指从订单产生到完成整个流转的过程,其中包括正想流程和逆向流程。正向流程就是一个正常的网购步骤:订单生成–>支付订单–>卖家发货–>确认收货–>交易成功。而逆向流程则是如上图虚线部分各种退款流程。

3.2 订单正向流程

订单系统设计-基础篇_第4张图片
以上就是订单正向流程图,订单从一个状态到另一个状态都会触发相关业务事件,通过转换变更为另一种状态,以上流程也可以看成是订单状态的正向流程。
其中待支付–>待发货这个事件比较特殊,涉及到支付业务,且第三方支付都是异步回调通知给业务方,而要考虑到第三方支付或业务系统异常时导致用户支付成功了但是订单状态却是已取消状态(用户提交订单后系统会发30min延迟消息去自动取消订单释放相关资源)。
为了解决以上问题,我们可以参考BASE理论(它是对CAP定理的补充)中的软状态概念,在本地事件处理成功+发起第三方支付成功后将本地订单状态变更为 支付中 这个中间状态,支付中状态不允许用户重复支付且不允许延迟消息对订单状态变更,则可以解决以上所描述问题,支付中订单可以根据支付回调结果做转换(成功 由支付中–>待发货;失败 由 支付中 -->订单取消)。

3.3 订单逆向流程

订单系统设计-基础篇_第5张图片
从以上逆向流程可以看出来关于售后有3种情况:

  1. 用户未支付取消订单

订单取消–>交易关闭

  1. 用户支付商家未发货

用户售后–>直接退款–>交易关闭

  1. 用户支付商家已发货

用户售后–>售后中–>直接退款–>交易关闭
商家已发货后用户再发起售后 ,哪怕是用户未收到货,也是需要用户先收到货之后,再发按照商家要求将货快递给商家,考虑到商家退货的地址可能和发件地址不一样,则该场景下一定要让用户先收到货且支付额外运费(直接拒收包裹业务是有问题的),此时订单状态为售后中,待商户收到货之后才能退款。

4. 订单状态机

4.1 订单状态机

订单系统设计-基础篇_第6张图片
状态机表示了一笔订单的生命周期,按照一定的方向通过触发不同的事件产生数据流转的过程(包括正向流程和逆向流程所有的订单状态流转)。

4.2 订单状态机升级

随着业务快速发展,如 我们商品有了虚拟商品、实物商品、自营商品,还有订单拆单、父子订单状态不一致等,让我们的订单状态机不堪重负,我们主要遇到以下问题:

  1. 订单状态为了满足更多业务导致状态膨胀;
  2. 事件业务过于复杂,耦合性非常高。

为了解决这两个问题,我们采用大状态+小状态的设计。主、子订单上只维护大状态流转,抽象出售后这个领域去维护自己小状态。这样保证了主子订单上的状态不会特别多,同时又可以通过小状态去满足业务需求。
主、子订单变更规则:

  1. 正向状态是当全部子订单向前流转时,主订单才会向前走;
  2. 逆向状态是当子订单全部变成(售后中) 主订单才变售后中. 子订单全部变成(售后完成)主订单才变售后完成 子订单全部变成(取消)主订单才变取消;

4.3 订单状态推送

我们系统是B2B2C架构,则会有3端用户(平台运营端、商户B端、用户C端),订单是由C端用户生产,但是平台运营端和商户B端看到订单状态又和用户看到订单状态不太一致,为了解决这个问题我们采用的是在订单状态机处理完事件后再同步给另外2端,这种方案就存在2个问题:

  1. 订单数据同步可靠性
  2. 订单数据查询一致性

问题1 订单数据推送可以使用集群MQ保证消息可靠性+同步日志(类似于MySQL的redolog)+定时任务补偿+人工兜底,运营端可以查看并手动操作异常同步数据。
问题2 在C端推送到其他端时将订单信息记录到redis缓存(key:订单id,value:版本号),其他端通过对比redis中版本号来判断是读取本地数据还是从C端pull最新数据。

暂时写这么多,下篇再更新订单状态机设计和代码实现。

你可能感兴趣的:(架构,系统架构,状态模式)