1. 课程导入
欢迎进入《Market Data多源去重与主键设计实战》。在真实行情系统中,我们很少只对接一个数据源:交易所直连、第三方聚合商、内部缓存、历史归档库、甚至人工补录文件,都会同时向同一套行情服务供数。数据一多,问题就不再是“有没有数据”,而是“同一条行情到底以谁为准、如何识别、如何合并、如何追溯”。本课程要解决的,正是这个从多源接入到可信主键落地的完整链路。
学习目标
完成本课程后,你应当具备三项可验证的能力。第一,能够识别多源行情数据中的重复形态,包括完全重复、字段冲突重复、时间窗口重复和跨源语义重复。第二,能够为不同资产类别设计可落地的主键方案,并解释为什么某些场景必须用复合主键、某些场景需要引入代理键。第三,能够把去重规则、优先级策略和主键约束写成可执行的工程配置,而不是停留在文档层面的“原则上”。
- 理解行情数据的唯一性边界:什么算“同一条”行情。
- 掌握主键、候选键、代理键、业务键在行情场景中的取舍。
- 能够设计多源优先级与冲突消解规则,并处理迟到数据。
- 能够用日志和指标验证去重效果,避免“看起来去重了,实际还在重复”。
核心概念:唯一性不是天然存在的
很多初学者会默认“一条行情记录”天然有唯一标识。但在多源环境下,唯一性是被定义出来的。以逐笔成交为例,交易所可能提供成交编号,但第三方源可能只给时间戳、价格、数量;同一笔成交在A源是 trade_id=88123,在B源可能被拆成两条部分成交,在C源可能因网络重传出现两次。此时,业务键(如 symbol + exchange + trade_id)和代理键(如内部生成的 market_seq)承担不同职责:前者用于跨源对齐,后者用于内部存储与幂等写入。
去重也不是简单的 DISTINCT。它至少包含三个层次:精确去重处理字节级或字段级完全相同的记录;近似去重处理时间戳微差、价格精度差异导致的“几乎相同”;语义去重处理同一市场事件被不同源以不同粒度表达的情况。课程后续章节会分别展开,但导入阶段必须先建立这个分层意识。
关键判断:去重前先问“唯一性由谁定义”。如果唯一性来自交易所,就尊重交易所编号;如果来自内部聚合逻辑,就必须显式设计主键并写入元数据,否则下游无法复现。
整体框架:一条行情从入到用的四道关
本课程按“接入—标准化—去重—主键固化”四道关组织。接入层负责多源连接与缓冲;标准化层统一时间、精度、枚举和字段命名;去重层执行窗口匹配、优先级裁决和冲突标记;主键固化层把最终唯一记录写入存储,并保留血缘信息。下面这张图展示了四层之间的数据流与关键控制点。
案例场景:同一笔成交为何出现三次
假设某期货合约在上午10:00:00.123成交,价格3500,数量10手。A源(交易所直连)给出 trade_id=T1001;B源(第三方聚合)因网络延迟在10:00:00.456才到达,且没有trade_id,只有时间戳和价格数量;C源(内部缓存)因重传机制把同一条记录发了两次。如果直接入库,下游会看到三条记录,成交量被放大到30手。
正确的处理路径是:标准化层先把B源时间戳对齐到交易所时钟,并生成候选业务键 symbol + exchange + trade_time + price + volume;去重层在500毫秒窗口内匹配到A源记录,按优先级保留A源,把B源标记为“低优先级重复”;C源的两条记录因携带相同内部序列号,在写入前被幂等键拦截。最终只落一条记录,并保留A源为主、B源为参考的血缘信息。
-- 去重规则配置示例(YAML)
dedup:
window_ms: 500
business_key:
- symbol
- exchange
- trade_time
- price
- volume
source_priority:
- exchange_direct
- third_party_agg
- internal_cache
conflict_policy: keep_highest_priority
late_data_policy: mark_and_merge
idempotent_key: "md:{symbol}:{exchange}:{trade_time}:{price}:{volume}"
常见误区与复盘
误区一:用全字段做唯一键。行情字段多且精度不一,全字段做主键会导致“几乎相同”的记录无法去重,且索引膨胀。正确做法是区分业务键与代理键。
误区二:只去重不记录冲突。直接丢弃低优先级记录会丢失数据质量线索。应保留冲突标记和源信息,便于事后审计。
误区三:忽略迟到数据。行情乱序是常态,窗口设置过小会漏去重,过大则增加状态开销。需要根据资产类别和源延迟分布调参。
| 层次 | 核心问题 | 关键产出 | 常见失败模式 |
|---|---|---|---|
| 接入层 | 多源如何稳定进入 | 缓冲队列、重放日志 | 源断连导致数据缺口 |
| 标准化层 | 字段与时间如何对齐 | 统一Schema、时钟校准 | 精度截断、枚举错配 |
| 去重层 | 什么算重复、谁优先 | 窗口规则、优先级策略 | 窗口过大、优先级倒置 |
| 主键固化层 | 如何唯一且可追溯 | 代理键、血缘、幂等写入 | 主键冲突、重复写入 |