3. 实时数据链路概览

在金融实时数据系统中,回放与补数并不是两个孤立功能,而是贯穿整条数据链路的“时间一致性能力”。要理解它们,必须先看清数据从交易所行情源到策略终端的完整路径。本节以端到端视角,拆解采集、传输、存储、计算、回放与补数六个环节的职责边界、关键组件与协作方式。

一、核心原理:六段链路与两类时间

实时数据链路可以抽象为六个连续阶段。采集层负责从交易所、行情商或内部系统获取原始报文;传输层负责低延迟、可追溯地把数据送达下游;存储层负责持久化并保留事件时间;计算层负责指标加工、聚合与信号生成;回放层负责按历史时间轴重放数据流;补数层负责在缺口发生后重新拉取并修复数据。

贯穿这六段的核心是两类时间:事件时间(数据在交易所实际发生的时刻)和处理时间(系统收到并处理该数据的时刻)。回放与补数之所以复杂,正是因为两者在实时链路中天然存在偏差。若存储层只记录处理时间,回放时就无法还原真实市场节奏;若补数时忽略事件时间,修复后的数据会与实时流产生错位。

关键原则:实时链路中每一跳都应携带并保留事件时间戳,回放与补数才有统一的时间基准。

二、方法流程:从采集到补数的协作机制

下面以一条典型的股票Level-2行情链路为例,说明各环节的协作流程。

  1. 采集:行情网关通过TCP/UDP接收交易所二进制报文,解析为标准化结构,并打上采集时间戳。常用组件包括C++行情网关、Python采集适配器。
  2. 传输:通过Kafka、Pulsar或Aeron等消息中间件传输。Kafka适合高吞吐与持久化,Aeron适合极低延迟场景。传输时需保证分区有序,通常以证券代码或频道作为分区键。
  3. 存储:原始报文写入对象存储或时序数据库,加工后数据写入ClickHouse、Doris或KDB+。存储层需同时保留事件时间与序列号,便于缺口检测。
  4. 计算:Flink、Spark Streaming或自研流计算引擎消费消息,生成快照、指标与信号。计算层需支持按事件时间窗口聚合,避免处理时间偏差。
  5. 回放:回放服务从存储层读取历史数据,按事件时间排序后重新注入消息队列或直接推送给策略。回放速度可调,支持倍速、暂停与跳转。
  6. 补数:当检测到序列号缺口或数据异常时,补数服务向行情商或交易所历史接口发起请求,拉取缺失区间,经校验后写回存储并触发下游重算。
# 典型缺口检测与补数触发逻辑(伪代码)
last_seq = redis.get("seq:600519")
current_seq = message.seq
if current_seq != last_seq + 1:
    gap = (last_seq + 1, current_seq - 1)
   补数任务队列.push({
        "symbol": "600519",
        "start": gap[0],
        "end": gap[1],
        "event_time_range": message.event_time
    })
redis.set("seq:600519", current_seq)

三、案例场景:盘中缺口修复与盘后回放

假设某策略在盘中依赖逐笔成交数据。上午10:15,监控系统发现某只股票的逐笔序列号出现跳跃,缺失约200毫秒的数据。补数服务立即向行情商历史接口请求该区间数据,同时通知计算层暂停该股票的窗口聚合。补数数据到达后,先与前后序列号做连续性校验,再写回Kafka对应分区,计算层从缺口起点重新消费并修正指标。整个过程在秒级完成,策略无感知。

盘后回放场景则不同。研究员需要验证策略在历史某日的表现,回放服务从ClickHouse读取当日全部行情,按事件时间排序,以10倍速注入模拟撮合引擎。此时存储层中保留的事件时间成为回放节奏的唯一依据,任何处理时间偏差都不会影响回放结果。

金融实时数据链路:采集→传输→存储→计算→回放/补数 采集层 行情网关/适配器 传输层 Kafka/Pulsar 存储层 ClickHouse/对象存储 计算层 Flink/Spark 回放层 事件时间重放 补数层 缺口检测 → 历史拉取 → 校验 → 写回 事件时间 → 采集 传输 存储 计算 缺口

四、关键组件清单与选型对比

不同环节对组件的要求差异明显。下表列出常见选型及其适用场景。

环节 关键组件 核心要求 典型选型
采集 行情网关、协议解析器 低延迟、高吞吐、协议兼容 C++网关、Python适配器
传输 消息队列、流总线 有序、持久化、可重放 Kafka、Pulsar、Aeron
存储 时序库、对象存储 事件时间保留、高压缩比 ClickHouse、KDB+、S3
计算 流计算引擎 事件时间窗口、Exactly-Once Flink、Spark Streaming
回放 回放服务、模拟撮合 倍速控制、事件时间排序 自研回放器、历史注入器
补数 缺口检测、历史拉取 自动触发、连续性校验 补数服务、对账任务

五、误区与复盘

误区一:只存处理时间,不存事件时间。回放时无法还原真实市场节奏,补数后数据与实时流错位。必须在采集入口就记录事件时间并贯穿全链路。

误区二:补数只补数据,不触发下游重算。缺失区间修复后,计算层若未重新消费,指标仍然错误。补数完成应发布重算事件。

误区三:回放与实时共用同一套消费逻辑,但忽略速度差异。回放可能以10倍速注入,若计算层未做背压或时间对齐,会产生大量乱序与重复。

复盘建议:定期对存储层做序列号连续性扫描,统计缺口分布;对补数任务记录耗时与成功率;对回放结果与实时结果做抽样比对,验证时间一致性。这三项检查能覆盖链路中大部分隐性故障。