4. 数据补录核心概念
断点续传解决的是“连接中断后如何接着传”,而数据补录解决的是“已经缺失的数据如何找回来、补进去、且不污染已有数据”。在行情采集系统中,补录不是简单的重跑任务,它涉及缺口识别、时间边界、回补方式、数据对齐与去重五个相互咬合的核心概念。理解它们之间的关系,才能设计出可靠的补录链路。
一、补录场景:什么时候必须补录
补录并非只在“采集失败”时才发生。实际生产环境中,以下场景都会触发补录需求:
- 网络中断或超时:采集进程与行情源断开,期间数据未落库。
- 源端延迟发布:行情源在收盘后修正或补发某段时间的数据。
- 服务重启或宕机:采集节点崩溃,内存中未持久化的数据丢失。
- 解析或校验失败:数据已到达但格式异常被丢弃,需要重新拉取。
- 历史数据迁移:新系统上线,需要从旧库或文件回填历史区间。
不同场景对应不同的补录优先级和窗口策略。例如网络中断通常只需补最近几分钟,而历史迁移可能跨越数月,必须分批处理。
二、缺失数据识别:先找到缺口,再谈补录
补录的第一步不是“拉数据”,而是“确认缺了什么”。行情数据通常具有明确的时间序列特征,识别缺口的核心方法是时间轴比对:以预期的时间粒度(如1秒、1分钟)生成完整时间序列,与已落库数据的时间戳集合做差集。
-- 以分钟线为例,识别缺失时间窗口
SELECT expected.ts
FROM generate_series(
'2024-06-01 09:30:00'::timestamp,
'2024-06-01 11:30:00'::timestamp,
'1 minute'
) AS expected(ts)
LEFT JOIN market_bars b ON b.ts = expected.ts
WHERE b.ts IS NULL
ORDER BY expected.ts;
除了时间戳缺失,还要识别记录数异常和字段空值。例如某分钟应有200条逐笔,实际只有50条,说明部分数据丢失;某条记录的成交量字段为NULL,说明解析不完整。识别结果应输出为“缺口清单”,包含起始时间、结束时间、缺失类型和影响范围。
三、时间窗口:补录的边界与粒度
时间窗口决定了补录请求的起止范围。窗口划分过粗,会拉取大量已存在的数据,浪费带宽和计算资源;窗口划分过细,会产生大量小请求,增加源端压力。常见策略有三种:
| 策略 | 窗口划分方式 | 适用场景 | 注意事项 |
|---|---|---|---|
| 固定窗口 | 按固定时长(如5分钟)切分 | 缺口分散、源端支持批量查询 | 窗口边界需对齐交易日历 |
| 动态窗口 | 根据缺口连续段自动合并 | 缺口集中、连续缺失 | 单窗口不宜超过源端限制 |
| 滑动窗口 | 以当前时间为终点向前回溯 | 实时补录、最近数据修复 | 需设置最大回溯深度 |
无论采用哪种策略,都必须处理交易日历问题。非交易时段不应生成补录窗口,否则会产生大量无效请求。同时,窗口边界要与源端的时间语义对齐,避免因时区或毫秒截断导致重复拉取。
四、回补策略:怎么补、补到什么程度
回补策略决定了补录请求的发起方式和失败处理逻辑。常见策略包括:
- 全量回补:对缺口窗口重新拉取全部数据,简单可靠,但可能覆盖已有正确数据。
- 增量回补:只拉取缺失的时间点或记录,依赖源端支持精确查询。
- 优先级回补:按业务重要性排序,先补关键品种或关键时段。
- 退避重试:补录失败后按指数退避重试,避免频繁冲击源端。
回补过程中要记录每次请求的批次号、窗口范围、源端响应状态和写入结果,形成可追溯的补录日志。这样在出现数据异常时,可以快速定位是哪次补录引入的问题。
五、数据对齐与去重:补录的最后一道防线
补录数据写入前,必须与已有数据做对齐和去重。对齐是指时间戳、品种代码、字段结构要与主表保持一致;去重是指同一时间点、同一品种的记录只能保留一条。
去重的核心是确定唯一键。行情数据通常以“品种代码 + 时间戳 + 周期”作为唯一键。写入时可采用以下方式:
-- 使用唯一索引 + ON CONFLICT 实现幂等写入
INSERT INTO market_bars (symbol, ts, open, high, low, close, volume)
VALUES ('IF2406', '2024-06-01 09:31:00', 3600.2, 3601.0, 3599.8, 3600.5, 1200)
ON CONFLICT (symbol, ts) DO UPDATE
SET open = EXCLUDED.open,
high = EXCLUDED.high,
low = EXCLUDED.low,
close = EXCLUDED.close,
volume = EXCLUDED.volume
WHERE market_bars.updated_at < EXCLUDED.updated_at;
对于逐笔数据,唯一键可能更复杂,需要结合成交编号或序列号。去重时还要注意数据版本问题:源端可能对同一时间点发布修正值,此时应保留最新版本而非简单丢弃。
六、常见误区与复盘要点
在实际补录实践中,以下误区最容易导致数据质量问题:
- 只补不验:补录完成后没有校验记录数和时间连续性,缺口依然存在。
- 窗口重叠:多个补录任务窗口重叠,导致同一时间段被重复拉取和写入。
- 忽略时区:源端使用UTC,本地使用北京时间,窗口边界偏移导致漏补或重补。
- 覆盖修正值:全量覆盖时把源端已修正的数据覆盖回旧值。
- 无批次追踪:出问题后无法定位是哪次补录引入的异常数据。
复盘时建议重点关注三个指标:补录成功率、补录后缺口残留率、重复数据发生率。这三个指标能直接反映补录链路是否健康。如果补录成功率低,检查源端限流和重试策略;如果缺口残留率高,检查窗口划分和交易日历;如果重复数据发生率高,检查唯一键设计和写入冲突处理。