一、增量更新原理:从全量快照说起

做量化交易的朋友都知道,订单簿就是市场的「心跳」。我刚开始接触高频交易系统时,第一反应是:把订单簿全量数据存下来不就行了?嗯,理论上没错,但实际跑起来你会发现——这玩意儿根本扛不住。

全量快照:简单但粗暴

全量快照,说白了就是每隔一段时间,把整个订单簿的买盘、卖盘、价格、数量全部拍一张「照片」。比如每秒拍一次,每次大概几百KB到几MB不等。

听起来还行?我们来算笔账:

频率 单次大小 每日数据量(6小时)
每秒1次 500KB 约10.5GB
每100ms 1次 500KB 约105GB
每10ms 1次 500KB 约1TB

我在项目中遇到过一家交易所,要求订单簿更新延迟低于1毫秒。你想想看,如果每秒拍1000次全量快照,光网络带宽就撑爆了。更别提存储和回放的成本了。

⚠️ 注意: 全量快照还有一个致命问题——数据冗余。相邻两次快照之间,90%以上的数据其实没变化。你每次都在重复传输那些没变过的订单,纯粹浪费资源。

增量更新:只传变化的部分

增量更新的思路其实很简单:只告诉系统「什么变了」,而不是「现在长什么样」

比如订单簿原来有1000个买单,突然有人撤单了。全量快照会把1000个买单重新发一遍,而增量更新只发一条消息:「删除订单ID #12345」。你说哪个更高效?

我个人习惯把增量更新比作「差分备份」——就像你修改Word文档时,只保存修改的部分,而不是每次Ctrl+S都重新存一遍整个文件。

为什么需要增量更新?

说白了,就三个字:快、省、准

  • :增量消息通常只有几十字节,传输延迟极低。我见过最快的增量更新系统,从事件发生到客户端收到,延迟不到50微秒。
  • :带宽占用减少90%以上。对于做市商来说,带宽就是钱啊。
  • :增量更新可以做到「事件级」精确。每一笔成交、每一次撤单都能追踪到。

我曾经帮一家量化基金优化过订单簿系统。他们原来用全量快照,每100ms拉一次,结果策略跑出来的信号总是慢半拍。换成增量更新后,延迟从100ms降到了2ms,策略收益直接翻了一倍。嗯,这就是差距。

核心设计思想

增量更新的核心设计思想,我总结为三点:

  1. 事件驱动:每个订单簿的变化都是一个事件。新增订单、撤销订单、成交、修改价格……把这些事件按时间顺序串起来,就是完整的市场行为。
  2. 状态重建:客户端收到增量事件后,在本地维护一个订单簿副本。每次收到增量消息,就更新这个副本。这样你永远拥有最新的订单簿状态。
  3. 容错机制:增量更新最怕丢消息。一旦丢了一条,本地订单簿就和服务器对不上了。所以必须配合「快照+增量」的混合模式——定期发一个全量快照作为基准,中间用增量消息衔接。
💡 核心公式:
最新状态 = 基准快照 + 所有后续增量事件的累积效果

这个公式看着简单,但实现起来坑不少。比如增量事件乱序怎么办?重复收到同一条消息怎么办?这些我们后面会详细讲。

一张图看懂增量更新流程

下面我用SVG画了一张流程图,展示增量更新的核心逻辑。你一看就明白了:

订单簿增量更新核心流程 交易所撮合引擎 增量事件流 新增/撤单/成交/修改 本地订单簿副本 基准快照(定期) 每5分钟或每100万笔事件 状态重建 快照 + 增量 = 最新状态 容错机制 丢消息时重新请求快照 数据源 增量数据 基准数据 计算过程 异常处理
💡 我的经验: 实际生产环境中,基准快照的频率要动态调整。市场活跃时(比如开盘、收盘),事件量暴增,快照间隔要缩短。市场冷清时,可以拉长间隔。我曾经用这个策略,把快照带宽消耗又降了30%。

增量更新的挑战

说了这么多好处,增量更新也不是银弹。我踩过几个坑,分享给你:

  • 消息顺序问题:网络传输中,后发的消息可能先到。比如先撤单后成交,但客户端先收到成交消息,再收到撤单消息——订单簿就乱了。
  • 重复消息:TCP重传可能导致同一条增量消息收到两次。如果直接应用,订单簿数据就翻倍了。
  • 快照与增量的衔接:快照生成的那一刻,增量事件还在继续。如果处理不好,快照和增量之间会有「缝隙」,导致数据丢失。

这些问题都有成熟的解决方案,比如序列号机制、幂等性设计、快照时间戳对齐等。后面的章节我会逐一拆解。

📌 一句话总结:
全量快照是「拍照片」,增量更新是「录视频」。做量化交易,你需要的是视频,而不是一堆照片。

专注资料整理