采的数据能不能说清「从哪来、怎么变」?数据血缘的工程实践

数据出问题的时候,最难回答的问题是:「这批数据是哪次请求采的?经过了哪些加工?为什么是这个值?」 能回答这个问题,就叫有「数据血缘」(data lineage)——数据从哪来、经过什么、到哪去。这篇讲采集系统怎么建立数据血缘,核心是用 request_id 贯穿全链路。

数据血缘解决什么

三个场景,血缘的价值立现:

  1. 排查:报表里某个值不对,顺着血缘找到「是哪条请求、哪步加工出的错」
  2. 审计:合规要求「能说清数据来源」,血缘就是答案
  3. 信任:团队对数据的信任,来自「任何数据都可追溯」

没有血缘,排查靠猜、审计靠编、信任靠感觉——都不靠谱。

血缘的三个要素

数据血缘要记录三件事:

  1. 来源:这批数据来自哪次请求(request_id、时间、端点、参数)
  2. 加工:经过了哪些处理(清洗、归一化、聚合)
  3. 去向:数据进了哪些表/被谁消费

第一步: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:消费端不记去向。 只知道「数据存在」,不知道「谁用了」。消费血缘补齐。

工程清单沉淀

  1. 每行数据带 source_request_id(来源锚点)
  2. 加工日志 + 版本号(加工血缘)
  3. 消费记录(去向血缘)
  4. 血缘事件表 + request_id 索引
  5. 血缘数据设保留策略

数据血缘的本质,是「让数据的历史可回答」:从哪来(request_id)、怎么变(加工日志)、到哪去(消费记录)。对排查、审计、合规、信任,都是基础能力。

接口响应自带的 request_id 字段(作为血缘锚点)在 SerpBase 官方文档 里有说明。你的采集数据有血缘吗?评论区聊聊怎么追溯的。

posted @ 2026-09-19 09:00  蜘蛛人  阅读(21)  评论(0)    收藏  举报