采的数据能不能说清「从哪来、怎么变」?数据血缘的工程实践
数据出问题的时候,最难回答的问题是:「这批数据是哪次请求采的?经过了哪些加工?为什么是这个值?」 能回答这个问题,就叫有「数据血缘」(data lineage)——数据从哪来、经过什么、到哪去。这篇讲采集系统怎么建立数据血缘,核心是用 request_id 贯穿全链路。
数据血缘解决什么
三个场景,血缘的价值立现:
- 排查:报表里某个值不对,顺着血缘找到「是哪条请求、哪步加工出的错」
- 审计:合规要求「能说清数据来源」,血缘就是答案
- 信任:团队对数据的信任,来自「任何数据都可追溯」
没有血缘,排查靠猜、审计靠编、信任靠感觉——都不靠谱。
血缘的三个要素
数据血缘要记录三件事:
- 来源:这批数据来自哪次请求(request_id、时间、端点、参数)
- 加工:经过了哪些处理(清洗、归一化、聚合)
- 去向:数据进了哪些表/被谁消费
第一步:request_id 贯穿(血缘的锚点)
搜索数据接口(如 SerpBase)每个响应带 request_id——这是血缘的天然锚点,贯穿从采集到消费的每一层:
# 采集时:request_id 跟随数据落库
def collect(keyword):
data = fetch(keyword) # 响应里有 request_id
records = clean(data)
for rec in records:
rec["source_request_id"] = data["request_id"] # 数据带上来源
store(rec)
每一行数据都带 source_request_id——「这批数据是哪次请求采的」永远可查。
第二步:记录加工过程(加工血缘)
加工(清洗/归一化/聚合)会改变数据,血缘要记「怎么变的」:
# 伪代码:加工日志
def transform(records):
result = normalize(records) # 归一化
log_transform({
"input_request_ids": [r["source_request_id"] for r in records],
"operation": "normalize",
"version": "v2", # 加工版本
"output_count": len(result),
"ts": now,
})
return result
加工日志 + 版本号:能说清「这批数据用哪个版本的清洗逻辑处理的」——配合重放(重放篇),加工升级后能追溯新老数据差异。
第三步:记录去向(消费血缘)
数据被谁用了,也要留痕:
# 伪代码:消费血缘
def consume(dataset, consumer):
log({
"dataset_id": dataset.id,
"consumer": consumer, # 哪个报表/功能消费了
"request_ids": dataset.source_request_ids,
"ts": now,
})
去向记录让「报表里的数字来自哪些采集请求」可反查——报表出问题,一路查到源头请求。
血缘怎么存:一张血缘表
血缘数据本身要落库,设计一张「血缘事件表」:
CREATE TABLE lineage_events (
id bigserial PRIMARY KEY,
event_type text NOT NULL, -- collect / transform / consume
request_id text, -- 来源请求(锚点)
operation text, -- 加工操作
version text, -- 加工版本
data_ref text, -- 涉及的数据引用
ts timestamptz NOT NULL DEFAULT now()
);
CREATE INDEX idx_lineage_rid ON lineage_events (request_id);
按 request_id 索引——「一次请求 → 全部后续血缘」一条 SQL 查出来:
SELECT * FROM lineage_events WHERE request_id = 'req_01Hxxx' ORDER BY ts;
血缘的价值落地
- 排查(思否的排查系列都受益):字段缺失、数据不准、计费对不上——拿
request_id查血缘,看到全链路 - 质量(质量篇):血缘 + 质量指标,能定位「哪批数据质量差、影响谁」
- 合规(合规篇):数据来源可追溯,审计有据
- 重放(重放篇):血缘记录了加工版本,重放能对齐新旧数据
踩坑记录
坑 1:request_id 没跟到每行数据。 只记在批次,下游不知道「这一行是哪次请求」。每行都带 source_request_id。
坑 2:加工过程不留痕。 只记来源不记加工,重放/排查时不知道数据怎么变的。加工日志 + 版本号。
坑 3:血缘表无限膨胀。 每次加工都记,量大会涨。保留策略:热数据近期血缘 + 老血缘归档。
坑 4:消费端不记去向。 只知道「数据存在」,不知道「谁用了」。消费血缘补齐。
工程清单沉淀
- 每行数据带
source_request_id(来源锚点) - 加工日志 + 版本号(加工血缘)
- 消费记录(去向血缘)
- 血缘事件表 + request_id 索引
- 血缘数据设保留策略
数据血缘的本质,是「让数据的历史可回答」:从哪来(request_id)、怎么变(加工日志)、到哪去(消费记录)。对排查、审计、合规、信任,都是基础能力。
接口响应自带的 request_id 字段(作为血缘锚点)在 SerpBase 官方文档 里有说明。你的采集数据有血缘吗?评论区聊聊怎么追溯的。

浙公网安备 33010602011771号