订单管理子系统:订单生命周期管理
做市商系统里,订单管理子系统可以说是最核心的模块之一。我这些年做过的系统,但凡订单管理设计得不好,后面基本都要返工重写。今天咱们就来聊聊这块。
订单生命周期:从生到死的完整旅程
一个订单从创建到最终完成,会经历几个关键状态。我个人习惯用状态机来管理,这样逻辑清晰,不容易出bug。
| 状态 | 说明 | 触发条件 |
|---|---|---|
| 新单 | 订单刚创建,还没进入撮合引擎 | 用户提交订单 |
| 部分成交 | 订单部分数量已成交,剩余部分还在挂单 | 撮合引擎匹配到部分数量 |
| 完全成交 | 订单全部数量已成交 | 撮合引擎匹配到全部数量 |
| 撤单 | 订单被用户取消或系统强制取消 | 用户发起撤单或超时 |
核心要点:状态变更必须保证原子性。我曾经见过一个系统,订单状态更新和资金扣减不是同一个事务,结果出现部分成交但资金没扣的情况,那叫一个惨。
嗯,这里要注意。订单状态机设计时,一定要考虑并发场景。比如一个订单同时被撮合引擎匹配和用户撤单,怎么办?我建议用乐观锁或者分布式锁来解决。
订单路由策略:把单子送到最合适的地方
做市商通常会在多个交易所同时挂单。订单路由就是决定把单子送到哪个交易所去。说白了,就是找最优路径。
智能路由
智能路由的核心是动态评估每个交易所的「性价比」。我一般会考虑这几个维度:
- 流动性深度:盘口挂单量够不够大
- 交易成本:手续费、滑点、延迟成本
- 成交概率:历史数据统计出来的成功率
- 当前网络延迟:实时测量的RTT
我的经验:智能路由的权重参数不能写死。我做过一个版本,把参数写死在配置文件里,结果市场环境一变,路由策略就失灵了。后来改成动态学习,每天根据历史数据自动调整权重,效果好很多。
最优执行
最优执行算法,说白了就是「怎么把单子拆开,分批送出去,让成交价格最划算」。常用的策略有:
- TWAP(时间加权平均价格):把大单拆成小单,按时间均匀发送
- VWAP(成交量加权平均价格):根据历史成交量分布来拆单
- 冰山订单:只暴露部分数量,隐藏真实意图
// 一个简单的TWAP拆单逻辑
public class TwapExecutor {
private final long totalQuantity;
private final long totalDuration; // 毫秒
private final long sliceInterval; // 每次发送间隔
public List<Order> generateSlices() {
List<Order> slices = new ArrayList<>();
long remaining = totalQuantity;
long sliceQty = totalQuantity / (totalDuration / sliceInterval);
while (remaining > 0) {
long qty = Math.min(sliceQty, remaining);
slices.add(new Order(qty));
remaining -= qty;
}
return slices;
}
}
订单簿快照与增量更新
订单簿是市场数据的核心。每次行情变化,我们都需要更新订单簿。这里有两个方案:
| 方案 | 优点 | 缺点 |
|---|---|---|
| 全量快照 | 实现简单,不会丢数据 | 数据量大,带宽消耗高 |
| 增量更新 | 数据量小,实时性高 | 需要处理丢包和乱序 |
我建议两者结合使用。平时用增量更新,每隔一段时间发一次全量快照做校验。这样既保证了实时性,又防止了数据不一致。
避坑指南:我曾经遇到过增量更新丢包导致订单簿数据错乱的问题。后来加了一个序列号机制,每次增量更新都带一个递增的seq,接收方发现seq不连续就主动请求全量快照。这个方案后来成了我们团队的标配。
订单延迟与重试机制
做市商对延迟极其敏感。你想想看,一个订单晚了几毫秒,可能价格就变了,成交机会就没了。
延迟的来源主要有三个:
- 网络延迟:从系统到交易所的物理距离
- 处理延迟:系统内部的处理时间
- 排队延迟:交易所撮合引擎的排队时间
针对这些延迟,我常用的优化手段:
- 就近部署:把服务器放在交易所机房或者同城
- 零拷贝技术:减少数据在内核态和用户态之间的拷贝
- 预分配内存:避免运行时频繁GC
重试机制这块,要特别注意「幂等性」。同一个订单如果重试两次,不能导致重复成交。我一般会在订单ID里加入唯一标识,交易所那边也做去重处理。
核心原则:重试策略要区分「可重试」和「不可重试」的错误。网络超时可以重试,但订单已成交就不能重试了。这个判断逻辑一定要严谨。
知识体系总览
下面这张图展示了订单管理子系统的核心模块和它们之间的关系:
这张图把四个核心模块的关系画清楚了。订单生命周期是基础,路由策略决定去向,订单簿提供市场数据,延迟重试保证可靠性。四个模块缺一不可。
最后说一句:订单管理子系统的设计,一定要从实际业务场景出发。不要为了追求技术炫酷而过度设计。我见过太多系统,功能堆得很全,但真正用到的就那几个。先跑通核心流程,再逐步优化,这才是正道。