个人随笔
目录
架构设计学习:订单系统的简单考虑
2025-06-19 22:43:20

如果要设计一个订单系统,要考虑哪些呢,我们要考虑订单的模块划分和设计原则以及表结构设计,下单流程的设计。

一、设计前奏

1、模块划分

订单主要分为订单管理模块、支付模块、库存模块、物流模块、售后模块、数据分析和报表模块。

2、设计原则

设计原则主要有模块化、扩展性、高可用性。对于高可用性之前也知道很多,比如提高组件的可靠性、冗余设计和容错、负载均衡和故障切换 、服务拆分、监控告警、过载保护等等。

3、电商基本概念

SPU (Standard Poduct Unit)标准产品单元,比如iphone6s,白色体恤。
SKU(Stock Keeping Unit)最小库存单元。比如256G 白色 iphone6s,对应的是用户下单的某个产品。

二、编码设计

目的:学会唯一标识设计,以及如何校验唯一标识

1、SPU编码

SPU编码通常包含以下部分:

类别代码:用于表示商品所属的大类别,如服装、电子产品等。
品牌代码:用于表示商品所属的品牌.
系列代码:用于表示商品所属的产品系列。
序列号:用于表示同一类商品的不同型号或版本。
例如,假设我们为一款电子产品指定SPU编码。类别代码为“01”(表示电子产品),品牌代码为“02”(表示品牌B),系列代码为“03”(表示系列C),序列号为“0001”。则该商品的SPU编码为:0102030001.

2、SKU编码

SKU编码中包含对应商品的SPU编码,以便于关联和查询。

属性代码:用于表示商品的各种规格属性,如颜色、尺寸等。
属性代码可以分为多个字段,分别表示不同的属性。
序列号:用于表示同一商品规格的不同批次或生产日期等信息。
例如,假设我们为上述电子产品的某个规格(颜色为红色,尺寸为大)指定SKU编码。属性代码为“01”(表示红色)和“02”(表示大尺寸),序列号为“0001”。则该商品规格的SKU编码为:0102030001-01020001,其中“-”不是必须的,只要约定好位数即可。

3、校验码

我们可以根据编码的数字,按照一定的规则比如如下规则
步骤1、从右向左,将奇数位置的数字相加,然后乘以3。
步骤2、再从右向左,将偶数位置的数字相加。
步骤3、将步骤1和步骤2的结果相加,得到一个总和 。
步骤4、找到一个最小的整数(包括0),使其(校验位)与总和相加能够被10整除。
这个整数就是校验位。

比如69码最后一位就是校验位,通过这个计算过程,我们可以得到一个校验位。当条形码被扫描时,扫描设备可以通过使用同样的计算方法检查校验位是否正确。如果计算出的校验位与扫描到的校验位不匹配,那么说明条形码数据可能存在问题,需要重新扫描或者检查数据。总之,69码中的校验位是用于确保条形码数据的正确性和完整性,防止扫描错误和数据传输问题导致的错误。

三、商品的设计

商品是订单的基础,有些商品是实物商品,有些是虚拟商品,比如会员这些,道具这些,不同系统中商品是不一样的,正常商品可能会包括:类别、品牌、属性、规格、税率、生产信息。

比如电子产品(类目),iphone(品牌),颜色:白色(属性),内存:8g(规格),税率:3%(税率),郑州富土康(生产信息)。

1、类目的设计

category_id:类目ID,是每个类目的唯一标识,通常设为主键。
category_name:类目名称,是用户在界面上看到的类目名字。
parent_id:父类目ID,用来表示这个类目的上一级类目。如果这个类目是最顶级的类目,那么这个字段可以为空或者设为0。
level:类目级别,用来表示这个类目在类目层级中的位置。最顶级的类目的级别为1,其下一级的类目级别为2,以此类推。
status:类目状态,用来表示这个类目是否可用。例如,可以设为1表示可用,0表示不可用。
sort_order:排序顺序,用来表示在同一级别的类目中,这个类目的排序位置。

通常在类目的设计中,类目的名称可能会有两个字段,一个是后台管理看的名称,一个是前端用户看的名称。比如棉裤,后台看到的是【棉裤】,前端用户看到的是【冬季爆款棉裤】。

对于这种有层级关系的设计,其实可以做自关联自解释的设计,比如省市县,机构等。

0010000(广东省)
0010100(广州市)
0010101(白云区)
0010102(天河区)
0010200(韶关市)
0010201(乳源县)

我们拿到0010201(乳源县)
,根据前面几位就知道肯定是0010200(韶关市),也知道是0010000(广东省)。自己关联自己的父级,自己进行解释。

2、品牌的设计

brand_id:品牌ID,每个品牌的唯一标识符,通常设为主键。
brand_name:品牌名称,用于显示的品牌名。
brand_logo:品牌Logo的URL,用于在页面上展示品牌的Logo。
brand_website:品牌的官方网站URL。
brand_description:品牌描述,一段简短的文字来描述这个品牌的特点和历史等信息。
brand_status:品牌状态,例如,可以设为1表示品牌可用,0表示品牌不可用。
sort_order:排序顺序,用来控制品牌在页面上的显示顺序。

要注意的是,因为品牌是会变化的,所以如果有变更,需要保持历史变更的内容,这样后续可以追溯,简单的方法就是有个变更记录表即可。根据时间和品牌ID就可以找到一整条变更时间线。

3、属性的设计

attribute_id:属性ID,为每个属性的唯一标识符,通常设置为主键。
attribute_name:属性名称,描述属性的类型(如颜色、尺寸等)。
attribute_type:属性类型,用于描述属性值的类型,例如文本、数字、日期等。
category_id:分类ID,表示此属性与哪个商品类别相关联。这个字段可以帮助你将相应的属性分配给对应的商品类别。毕竟不同的商品类别,属性有可能完全不同,比如手机有尺寸,但是桶装水就没有尺寸。

上面只是保证这个商品类目有哪些属性,但是具体到某个商品的属性内容需要有个商品属性值表(ProductAttribute Value Table)。这个表可能包含product id(商品ID)、attribute_id(属性ID)和value(值)等字段,用于存储每个商品具有的特定属性值。

4、规格的设计

specification_id:规格ID,为每个规格的唯一标识符,通常设置为主键。
specification_name:规格名称,例如”屏幕尺寸”、”存储容量”等。
specification_values:规格值,一般以字符串数组或者其他形式存储可能的值,例如”32寸”、”64寸”等。
status:状态,表示这个规格是否可用。可以设为1表示可用,0表示不可用

规格是属性的一种,是从属性里面提炼出来的,作用是为了促进消费的体验。满足不同商品销售需求。可以用于检索,可以用于选择。让业务更好的服务于业务。

5、生产信息设计

production_id:生产信息ID,为每个生产信息的唯一标识符,通常设置为主键。
manufacturer_id:制造商ID,关联到制造商信息。
manufacturing_date:生产日期。
expiration_date:过期日期,如果适用的话。
batch_number:批次号,用于识别同一批次的商品
location:生产地点,可以是具体的工厂或者城市等。
quality_control_result:质量控制结果,记录该批次商品的质量检测结果,
inspection_certification:检验证明,如果有相关的质量检验证明文件,可以记录其文件编号或者链接.
status:状态表示该生产信息是否有效或者当前的状态,例如在生产,已完成等。

上面这些都要商品表中要预留关联字段,当然每个系统对商品的设计都不一样,不一定都需要有这些东西,有些可能简单点的就只有一个商品表,没有属性,没有生产信息,没有类目都可能。

四、订单流程设计

1、订单流程

一个订单系统涉及到很多环节,但是并不是所有环节都需要,下面是比较全的环节流程。
下单【订单中心】->安全检验【风控中心】->获取商品信息【商品中心】->获取优惠券信息【营销中心】->获取会员权益【会员中心】->锁定库存【调度中心】->运费计算【物流中心】->订单生成【订单中心】->订单支付【支付中心】->订单下发【订单中心】->发货调度【调度中心】->订单出库【仓储中心WMS】->物流跟踪【物流中心】->用户签收【订单中心】/评论【客服中心】->退货申请【订单中心】->售后审核【客服中心】->退货入库【仓储中心WMS】->库存更新【调度中心】->订单售后状态更新【订单中心】->退款【支付中心】->退款成功【订单中心】。

2、用户下单流程

商品列表->商品详情->购物车->选择配送地址和支付方式->创建订单->生成支付凭据->调起支付->支付成功->支付结果通知->后端主动查询状态->对账。

3、要考虑的功能

商品列表:搜索,过滤,排序,展示,个性化推荐,分页,缓存,压缩,好的项目是优化出来的。

商品详情:目的是针对目标用户,让他们全面了解目标信息,最终做出购买决策。要考虑图片压缩,js压缩,css压缩,浏览器解压,减少请求,把计算能力转移到客户端,cdn,动静分离,异步加载,懒加载,前后端缓存。

购物车设计:存储(未登录用户存储在前端,登录用户存储在后端),商品加个变化可以让用户进入购物车重算,也可以点击下单再重算并提醒用户加个变化。

创建订单:要考虑商品库存,分布式锁,库存太大可以考虑分段锁,拆单,订单ID(唯一性,可读性,安全性)。

支付设计:支付凭据获取,重复通知,幂等,回调,主动查询,订单状态变更。

订单状态:待支付,支付中(可以没有),已支付,待发货,已发货、已签收、已完成、申请退款、退货、退款、退货中、已退款、已退货,已取消等。状态变更要连贯性,待发货前面肯定是要已支付。可以设计两个字段,比如1开头是取消,10是用户取消,11是管理员取消,12是系统超时取消,这样可以增加可读性。

库存扣减方案:下单扣库存会有些下单不买占据库存,付款口库存会增加纠纷,已经付款了库存没有了。所以可以考虑预存库存,就是下单扣库存,10分钟不支付就自动取消。

订单拆单:由于商家归属,物流限制,仓库位置,商品属性(不同问区)等等原因可能要考虑超拆单,主要是父子订单表的设计比如

  1. 父订单:订单ID、用户ID、实付金额、支付时间
  2. 子订单:子订单ID、父订单ID、商家ID、仓库ID、物流公司、运费

用户再订单列表页面仅显示父订单,下单时间等,还有全局状态比如部分发货,若子订单状态不一致,则按最滞后显示。
订单详情页要分层结构显示,比如

  1. 父订单信息(订单号、总金额)
  2. ├─ 子订单A [商家X](状态:已发货)
  3. ├─ 商品1 ×1
  4. ├─ 物流单号:JD123
  5. ├─ 子订单B [商家Y](状态:待发货)
  6. ├─ 商品2 ×2
  7. ├─ 预计发货:2025-07-01

若是部分取消或者退款,则仅关闭对应子订单,父订单变更为部分退款。不同子订单物流分离咱是,用户可分别跟踪。在设计上要考虑父子订单需强关联,子订单独立管理履约流程。

扣减库存设计:要分层实现,比如销售层主要是查询锁定库存,给用户提供实时的库存信息,调度层主要是基于各个仓库的库存进行调度,仓库层管理具体的sku.这里还要考虑调度层是否存数据,如果不存就要每次多个仓库实时查询,增加调用消耗,存的话就要考虑调度层和仓库层的库存一致性的问题。

结束!

 9

啊!这个可能是世界上最丑的留言输入框功能~


当然,也是最丑的留言列表

有疑问发邮件到 : suibibk@qq.com 侵权立删
Copyright : 个人随笔   备案号 : 粤ICP备18099399号-2