订单管理子系统:订单生命周期管理

做市商系统里,订单管理子系统可以说是最核心的模块之一。我这些年做过的系统,但凡订单管理设计得不好,后面基本都要返工重写。今天咱们就来聊聊这块。

订单生命周期:从生到死的完整旅程

一个订单从创建到最终完成,会经历几个关键状态。我个人习惯用状态机来管理,这样逻辑清晰,不容易出bug。

状态 说明 触发条件
新单 订单刚创建,还没进入撮合引擎 用户提交订单
部分成交 订单部分数量已成交,剩余部分还在挂单 撮合引擎匹配到部分数量
完全成交 订单全部数量已成交 撮合引擎匹配到全部数量
撤单 订单被用户取消或系统强制取消 用户发起撤单或超时

核心要点:状态变更必须保证原子性。我曾经见过一个系统,订单状态更新和资金扣减不是同一个事务,结果出现部分成交但资金没扣的情况,那叫一个惨。

嗯,这里要注意。订单状态机设计时,一定要考虑并发场景。比如一个订单同时被撮合引擎匹配和用户撤单,怎么办?我建议用乐观锁或者分布式锁来解决。

订单路由策略:把单子送到最合适的地方

做市商通常会在多个交易所同时挂单。订单路由就是决定把单子送到哪个交易所去。说白了,就是找最优路径。

智能路由

智能路由的核心是动态评估每个交易所的「性价比」。我一般会考虑这几个维度:

  • 流动性深度:盘口挂单量够不够大
  • 交易成本:手续费、滑点、延迟成本
  • 成交概率:历史数据统计出来的成功率
  • 当前网络延迟:实时测量的RTT

我的经验:智能路由的权重参数不能写死。我做过一个版本,把参数写死在配置文件里,结果市场环境一变,路由策略就失灵了。后来改成动态学习,每天根据历史数据自动调整权重,效果好很多。

最优执行

最优执行算法,说白了就是「怎么把单子拆开,分批送出去,让成交价格最划算」。常用的策略有:

  1. TWAP(时间加权平均价格):把大单拆成小单,按时间均匀发送
  2. VWAP(成交量加权平均价格):根据历史成交量分布来拆单
  3. 冰山订单:只暴露部分数量,隐藏真实意图
// 一个简单的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不连续就主动请求全量快照。这个方案后来成了我们团队的标配。

订单延迟与重试机制

做市商对延迟极其敏感。你想想看,一个订单晚了几毫秒,可能价格就变了,成交机会就没了。

延迟的来源主要有三个:

  • 网络延迟:从系统到交易所的物理距离
  • 处理延迟:系统内部的处理时间
  • 排队延迟:交易所撮合引擎的排队时间

针对这些延迟,我常用的优化手段:

  1. 就近部署:把服务器放在交易所机房或者同城
  2. 零拷贝技术:减少数据在内核态和用户态之间的拷贝
  3. 预分配内存:避免运行时频繁GC

重试机制这块,要特别注意「幂等性」。同一个订单如果重试两次,不能导致重复成交。我一般会在订单ID里加入唯一标识,交易所那边也做去重处理。

核心原则:重试策略要区分「可重试」和「不可重试」的错误。网络超时可以重试,但订单已成交就不能重试了。这个判断逻辑一定要严谨。

知识体系总览

下面这张图展示了订单管理子系统的核心模块和它们之间的关系:

订单管理子系统核心架构 订单生命周期 订单路由策略 订单簿管理 延迟与重试 新单 部分成交 完全成交 撤单 智能路由 最优执行 TWAP VWAP 全量快照 增量更新 网络延迟 处理延迟

这张图把四个核心模块的关系画清楚了。订单生命周期是基础,路由策略决定去向,订单簿提供市场数据,延迟重试保证可靠性。四个模块缺一不可。

最后说一句:订单管理子系统的设计,一定要从实际业务场景出发。不要为了追求技术炫酷而过度设计。我见过太多系统,功能堆得很全,但真正用到的就那几个。先跑通核心流程,再逐步优化,这才是正道。

专注资料整理