快照与增量:全量快照的定义、增量更新的概念、为什么需要增量快照重建
好,咱们接着聊订单簿的核心机制。上一章我们讲了订单簿长什么样,这一章我们来拆解一个更关键的问题:数据到底怎么存、怎么传、怎么恢复。
说白了,交易所每秒都在产生海量的订单变动。如果你每次都要把整个订单簿重新拉一遍,那带宽和延迟都扛不住。所以业界普遍采用一种策略——快照 + 增量。我当年刚接触这个模式时,也觉得不就是“全量备份 + 日志回放”嘛,但真正落地时踩的坑可不少。
一、全量快照:给订单簿拍一张“全家福”
全量快照,顾名思义,就是在某个时间点,把当前订单簿上所有挂单的完整状态拍下来。它包含所有价格档位、每个档位的总挂单量、以及每笔订单的细节(如果系统需要)。
举个例子,假设在 09:30:00.000 这个时刻,我拍了一张快照:
{
"timestamp": "09:30:00.000",
"bids": [
{"price": 100.50, "size": 2000, "order_count": 15},
{"price": 100.45, "size": 1500, "order_count": 10},
{"price": 100.40, "size": 3000, "order_count": 22}
],
"asks": [
{"price": 100.55, "size": 1800, "order_count": 12},
{"price": 100.60, "size": 2500, "order_count": 18}
]
}
这就是一张“全家福”。它完整、独立、可以直接用来重建整个订单簿。但问题也很明显——它太大了。如果每秒都拍一张,数据量会爆炸。我在项目中见过有人试图每 100ms 拍一次快照,结果磁盘 IO 直接被打满,系统延迟飙升。
二、增量更新:只记录“变化”
增量更新就聪明多了。它不记录整个订单簿,只记录从上一个状态到当前状态之间发生了什么变化。比如:
- 新订单进入(新增)
- 订单被成交(删除或减少数量)
- 订单被撤销(删除)
- 订单被修改(价格或数量变动)
每个增量消息通常包含:操作类型、价格、数量、订单ID、时间戳。像这样:
// 增量消息示例
{
"type": "ADD",
"order_id": "ORD123456",
"side": "BUY",
"price": 100.48,
"size": 500,
"timestamp": "09:30:00.050"
}
你想想看,一条增量消息可能只有几十个字节。而一张全量快照可能是几兆甚至几十兆。用增量来传输,带宽消耗能降低 99% 以上。嗯,这里要注意:增量消息必须严格按时间顺序处理,否则重建出来的订单簿就是错的。
三、为什么需要增量快照重建?
好,现在问题来了:既然增量这么好,为什么我们还需要快照?直接一直用增量不就行了?
答案很简单:增量会累积错误。
想象一下,你从 09:30:00 开始接收增量消息。到了 09:35:00,你已经处理了 10 万条增量。这期间,网络可能丢包、消息可能重复、你的程序可能有个小 bug 导致某条增量没处理对。结果就是——你本地的订单簿和交易所的真实订单簿,已经不一样了。
这就是所谓的“状态漂移”。
所以,我们需要定期用全量快照来“校准”。流程是这样的:
- 接收一个全量快照,用它初始化本地订单簿
- 从这个快照的时间点开始,接收并应用后续的增量消息
- 过一段时间(比如 1 秒或 10 秒),再接收一个新的快照
- 用新快照覆盖本地状态,然后继续应用增量
这个机制就叫增量快照重建。它既保证了数据的实时性(用增量),又保证了数据的正确性(用快照校准)。
四、核心逻辑:一张图看懂
下面我用一张 SVG 图来展示整个流程。你一看就明白了:
从图上你能看到:快照是“锚点”,增量是“过程”。每次拿到新快照,就把之前的增量全部清掉,重新开始。这样即使增量有错误,最多也只影响两个快照之间的那段时间。
五、实际应用中的权衡
在实际系统中,快照频率是个需要仔细权衡的参数:
| 快照频率 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| 高(每秒) | 错误恢复快,数据一致性高 | 带宽和存储开销大 | 高频交易、低延迟要求 |
| 中(每10秒) | 平衡了开销和恢复速度 | 增量累积较多,恢复稍慢 | 大多数交易所默认策略 |
| 低(每分钟) | 带宽和存储极省 | 增量累积巨大,恢复慢,错误风险高 | 非实时行情、历史回放 |
我个人习惯是:快照频率取 5~10 秒一次。这个频率下,增量消息通常只有几百条,重建几乎瞬间完成。同时带宽开销也在可接受范围内。
好了,这一章的内容就到这里。记住这个核心思想:没有快照的增量是危险的,没有增量的快照是笨重的。下一章我们会深入代码,看看怎么用 Python 实现一个简单的增量快照重建引擎。