一、真正的复杂度不在“功能”,而在“组合”
很多系统失败,不是因为功能不够,而是因为:功能一旦组合,就失控
在电商中,一个看似简单的下单过程,实际包含:
- 多种营销叠加(优惠券 / 积分 / 会员价 / 活动价)
- 多状态流转(支付 / 取消 / 发货 / 售后)
- 多写操作(订单 / 库存 / 资金)
👉 所以问题本质是:如何在“组合复杂度”下,仍然保持系统可控
二、订单系统:从“数据表”到“受控状态流”
1️⃣ 为什么订单系统一定要用状态机?
大多数低质量实现:
- 用一个 status 字段
- 随意修改
👉 这会导致:
- 状态错乱(已取消还能支付)
- 并发冲突(多次更新)
- 无法追溯
2️⃣ 正确模型:有限状态机(FSM)
订单应被建模为:一组受约束的状态 + 合法迁移路径
状态定义(示例):
CREATED(已创建) PAYING(支付中) PAID(已支付) DELIVERING(履约中) FINISHED(完成) CANCELLED(已取消)状态迁移(核心约束):
CREATED → PAYING → PAID → DELIVERING → FINISHED ↓ ↓ CANCELLED TIMEOUT3️⃣ 工程实现关键点
✔ 状态迁移必须“显式定义”
boolean canTransit(State from, State to)👉 避免:
- 非法状态变更
- 逻辑分散
✔ 幂等控制(必须有)
支付回调场景:
- 重复通知
- 网络抖动
解决:
- 唯一订单号
- 状态校验
✔ 状态变更必须具备“原子性”
更新订单状态 → 再扣库存常见错误:
👉 正确方式:
- 核心操作同一事务
- 或通过事件驱动
4️⃣ 本质总结
订单系统不是“存数据”,而是“控制流程”
三、营销系统:规则引擎设计的真正难点
1️⃣ 为什么 if-else 一定会失败?
典型代码:
if (coupon) {...} if (points) {...} if (vip) {...}问题:
- 规则顺序不可控
- 无法组合
- 无法扩展
👉 当规则数量 > 5 时,系统必然失控。
2️⃣ 正确抽象:规则引擎模型
LikeShop 的核心思路是:把营销能力从“代码逻辑”抽象为“规则系统”
Rule(规则) Condition(条件) Action(执行) Priority(优先级) Constraint(约束)基本结构:
3️⃣ 真正的难点:规则选择问题(不是执行问题)
在一次下单中,可能存在:
- 多张可用优惠券
- 多种活动叠加
- 互斥规则
👉 本质问题:如何在约束条件下,找到“最优优惠组合”
4️⃣ 工程解法(核心算法思想)
❗ 不能做全量穷举
复杂度:
O(2^n)👉 直接不可用
✔ 实际策略(LikeShop思路)
Step 1:规则分层
- 商品级
- 订单级
- 用户级
Step 2:优先级排序
- 强约束规则优先
- 高权重规则优先
Step 3:逐步计算(贪心 + 局部最优)
- 逐层应用规则
- 动态调整价格
Step 4:约束校验
- 是否可叠加
- 是否冲突
👉 核心目标:在可接受复杂度内,得到“足够优”的结果
5️⃣ 为什么必须统一计算入口?
很多系统的问题:
- 商品页算一套
- 购物车算一套
- 下单再算一套
👉 结果:
- 价格不一致
- 用户投诉
- 无法排查
正确设计:所有价格计算必须进入统一 Price Engine
特点:
- 输入一致
- 输出一致
- 可追踪
四、订单 + 营销的耦合问题
真正复杂的地方在于:订单系统依赖营销结果,而营销计算依赖订单上下文
👉 典型循环依赖:
- 订单金额 → 影响优惠
- 优惠结果 → 影响订单金额
解决方案:分阶段计算
Step1:基础价格计算 Step2:应用营销规则 Step3:生成最终订单金额 Step4:锁定计算结果👉 原则:
一旦下单完成,价格不可再变
五、最终一致性与性能的平衡
- 营销 + 订单会带来:
- 高计算成本
- 高并发压力
LikeShop 的策略:
- ✔ 计算前置(在下单前完成)
- ✔ 缓存中间结果(减少重复计算)
- ✔ 下单时只做“确认操作”
👉 目标:把复杂计算从“写链路”移出
六、核心结论
电商系统的扩展性,不取决于:
- 是否微服务
- 是否分布式
而取决于:
- ✔ 订单是否可控(状态机)
- ✔ 营销是否可扩展(规则引擎)
- ✔ 计算是否一致(统一入口)
- ✔ 复杂度是否被收敛
最后
电商系统的难点,从来不在“功能实现”,而在“如何让复杂规则长期可控”。