2. 核心概念与术语:父单、子单、拆分规则、拆分策略、拆分引擎
好,咱们正式开始聊订单拆分系统的核心概念。说实话,我见过不少团队,一上来就撸代码,结果做到一半发现「父单」和「子单」的关系都没理清楚,最后返工重写。嗯,这一节咱们就把这些基础概念夯实了。
2.1 父单与子单
父单,就是用户下单时生成的那个原始订单。比如你在电商平台买了3件商品,系统生成一个订单号,这就是父单。
子单,是父单经过拆分后产生的多个小订单。每个子单都有自己的订单号、状态、物流信息。
我习惯用一个比喻:父单是「总任务」,子单是「分任务」。总任务拆成几个分任务,各自执行,最后汇总结果。
关键点:父单和子单之间是一对多的关系。一个父单可以拆成N个子单,但每个子单只能属于一个父单。
举个例子:用户下单买了「手机+手机壳+充电宝」三件商品。父单是A001。拆分后可能变成:
- 子单A001-1:手机(从北京仓发货)
- 子单A001-2:手机壳+充电宝(从上海仓发货)
你看,同一个父单,因为仓库不同,拆成了两个子单。每个子单独立发货、独立结算。
避坑指南:我曾经遇到过一个项目,子单的订单号直接用父单号加后缀,结果业务量上来后,订单号长度超了数据库字段限制。建议子单号独立生成,或者用雪花算法保证唯一性。
2.2 拆分规则
拆分规则,说白了就是「按什么条件拆」。这是整个系统的核心配置。
常见的拆分规则有:
| 规则类型 | 说明 | 我见过的坑 |
|---|---|---|
| 按仓库拆分 | 不同仓库的商品拆成不同子单 | 仓库编码写死,新仓库上线要改代码 |
| 按商家拆分 | 不同商家的商品拆开 | 商家ID变更导致历史数据对不上 |
| 按物流模板拆分 | 不同物流方式的商品拆开 | 物流模板配置复杂,容易漏配 |
| 按商品类型拆分 | 虚拟商品和实物商品拆开 | 虚拟商品不需要物流,容易混淆 |
| 按金额阈值拆分 | 超过一定金额拆成多个子单 | 阈值设置不合理,导致大量小额子单 |
我个人建议,拆分规则一定要做成可配置的。别写死在代码里。你想想看,业务规则三天两头变,每次都要改代码发版,运维同学会恨你的。
2.3 拆分策略
拆分策略,是「怎么拆」的问题。它决定了多个规则同时存在时,谁先执行、谁后执行,以及冲突时怎么处理。
常见的拆分策略有:
- 顺序拆分:按规则优先级依次拆分。比如先按仓库拆,再按商家拆。
- 并行拆分:多个规则同时生效,取并集。比如同时按仓库和商家拆,结果可能是4个子单。
- 合并拆分:某些条件下,把多个子单合并成一个。比如同一个仓库、同一个商家的商品,尽量放在一个子单里。
注意:拆分策略的优先级很重要。我遇到过一个问题:先按仓库拆,再按商家拆,结果同一个仓库里不同商家的商品被拆成了两个子单,但物流成本反而更高了。后来我们调整了策略,先按商家拆,再按仓库拆,问题就解决了。
其实,拆分策略没有绝对的对错,关键看业务场景。我建议你在设计时,把策略做成可插拔的,方便后续调整。
2.4 拆分引擎
拆分引擎,是执行拆分逻辑的核心模块。它接收父单,根据拆分规则和策略,生成子单。
我画了一张图,帮你理解拆分引擎的工作流程:
拆分引擎的核心逻辑,我习惯用伪代码来描述:
function splitOrder(parentOrder):
// 1. 加载所有生效的拆分规则
rules = loadActiveRules()
// 2. 按策略排序规则
sortedRules = sortByStrategy(rules)
// 3. 逐条执行规则
childOrders = [parentOrder]
for rule in sortedRules:
childOrders = applyRule(childOrders, rule)
// 4. 生成子单
return generateChildOrders(childOrders)
你看,逻辑其实不复杂。但真正落地时,有几个细节要注意:
- 幂等性:同一个父单,多次调用拆分引擎,结果必须一致。否则会出现重复拆分的问题。
- 事务性:拆分过程中如果出错,要能回滚。不能出现父单拆了一半,子单生成了一半的情况。
- 性能:拆分引擎要能处理高并发。我见过一个系统,双十一时拆分引擎成了瓶颈,因为每次拆分都要查数据库。
我的经验:拆分引擎最好做成无状态的,方便水平扩展。另外,规则和策略的配置建议用缓存,别每次都查数据库。我曾经优化过一个系统,把规则缓存到Redis后,拆分性能提升了10倍。
2.5 小结
这一节咱们把核心概念捋了一遍。父单是源头,子单是结果。拆分规则决定「按什么拆」,拆分策略决定「怎么拆」,拆分引擎负责执行。这四个概念,是订单拆分系统的基石。
嗯,概念清楚了,下一节咱们聊聊拆分引擎的详细设计。到时候我会分享一些具体的代码实现和性能优化技巧。
公众号:蓝海资料掘金营,微信deep3321