数据契约基础:什么是数据契约?

聊数据契约之前,我先问个问题:你团队里有没有发生过这种事?

数据生产者拍着胸脯说「这个字段我每天凌晨两点准时产出」,结果消费方早上八点跑任务,发现数据还是空的。两边一扯皮,发现根本没有书面约定——全靠口头承诺。

数据契约,说白了就是给数据生产者和消费者之间签一份「书面合同」。它把双方的权利义务写清楚:你产什么、什么时候产、质量多高、出了问题谁负责。我做了这么多年数据治理,发现很多成本问题,根源都在契约缺失上。

核心要素:Schema、SLA、Owner、血缘

一个完整的数据契约,至少包含四个要素。少了任何一个,后面都可能出大问题。

要素 含义 我踩过的坑
Schema 数据的结构定义,字段名、类型、约束、默认值 字段类型从 int 改成 string,消费方没收到通知,ETL 直接崩了
SLA 服务等级协议,包括产出时间、延迟容忍度、可用性 曾经约定「每天凌晨产出」,结果对方凌晨 3 点才跑完,我们 2 点的调度全挂了
Owner 数据资产的责任人,出了问题能找到人 有一次数据延迟,打了 5 个电话才找到负责人,中间浪费了 2 小时
血缘 数据的上下游依赖关系,谁产了谁、谁消费了谁 改了一个上游表,下游 20 个任务全挂,没人知道影响范围

Schema:契约的「语法」

Schema 定义了数据长什么样。字段名、数据类型、是否可为空、枚举值范围……这些都得写清楚。

我个人习惯在契约里把 Schema 写成类似这样的形式:

{
  "table": "order_detail",
  "version": "1.2.0",
  "fields": [
    {"name": "order_id", "type": "string", "nullable": false, "comment": "订单唯一标识"},
    {"name": "user_id", "type": "string", "nullable": false, "comment": "用户ID"},
    {"name": "amount", "type": "decimal(10,2)", "nullable": false, "comment": "订单金额"},
    {"name": "status", "type": "string", "nullable": true, "enum": ["pending", "paid", "cancelled"], "comment": "订单状态"}
  ],
  "partition": ["dt"],
  "update_frequency": "daily"
}

嗯,这里要注意:版本号一定要带上。我见过太多团队改了 Schema 不更新版本,消费方还在用旧结构解析,结果全是乱码。

SLA:契约的「时间线」

SLA 不只是「几点产出」这么简单。它应该包含:

  • 产出时间:最晚几点必须可用
  • 延迟容忍:允许延迟多久,超时怎么处理
  • 数据完整性:行数波动范围、空值率上限
  • 可用性:月度/季度可用百分比

举个例子,我参与过的一个实时数仓项目,SLA 是这样约定的:

SLA 条款:
- 每日产出截止时间:T+1 02:00(北京时间)
- 延迟容忍:最多 30 分钟,超时自动告警
- 数据完整性:行数波动不超过前 7 日均值的 ±5%
- 空值率:关键字段(order_id, user_id)空值率 < 0.01%
- 可用性:月度 99.5%,季度 99.9%

为什么要把空值率写进去?我曾经遇到一个情况,上游某天程序 bug,order_id 字段 30% 是空值,下游的报表全算错了。因为没有空值率约束,上游觉得「数据产出了就算完成」,责任全在下游没做校验。

Owner:契约的「责任人」

Owner 不是随便填个名字就完事。它要包含:

  • 数据 Owner:对数据质量负责的人
  • 技术 Owner:负责数据管道维护的人
  • 备份 Owner:前两者不在时的替代联系人
  • 联系方式:即时通讯、电话、邮箱,至少两种

我建议每个数据资产至少有两个联系人。有一次凌晨 3 点数据延迟,主 Owner 在飞机上,还好有备份联系人,10 分钟定位了问题。

血缘:契约的「地图」

血缘关系告诉你:这份数据从哪来,被谁用过。没有血缘,改一个字段就像拆盲盒——你永远不知道会炸到谁。

血缘信息在契约里可以这样表达:

血缘关系:
- 上游依赖:ods_order_raw(表), user_profile(表)
- 下游消费:dws_order_daily(表), report_dashboard(看板)
- 依赖类型:强依赖(ods_order_raw 不可用则本表不可用)
- 消费方式:实时订阅(dws_order_daily),离线 T+1(report_dashboard)

核心观点:血缘不是事后追溯的工具,而是事前变更的「影响范围说明书」。每次 Schema 变更前,先看血缘,再动手。

契约 vs 传统数据治理

传统数据治理什么样?我经历过。一堆文档、一堆流程、一堆审批。但实际执行起来,文档没人看,流程走形式,审批靠刷脸。

数据契约和传统治理的区别,我用一个表格说清楚:

维度 传统数据治理 数据契约
约定方式 文档、邮件、口头 结构化、版本化、可编程
执行保障 靠人自觉、事后追责 自动化校验、事前阻断
变更流程 审批流、邮件通知 契约版本升级、兼容性检查
问题定位 人工排查、扯皮 契约违约告警、自动定位
成本视角 关注治理成本 关注数据质量引发的浪费

说白了,传统治理是「出了事再处理」,数据契约是「事先说好,自动执行」。我见过一个团队,用了契约之后,数据质量问题从平均每周 5 起降到了每月不到 1 起。为什么?因为契约把「模糊的承诺」变成了「可验证的规则」。

一个小建议:刚开始推行数据契约时,别贪多。选 3-5 个核心数据资产试点,把 Schema 和 SLA 先定下来。跑通一个流程,比设计一套完美方案有用得多。

数据契约的核心逻辑

下面这张图,是我自己总结的数据契约运作逻辑。它不是一个静态文档,而是一个持续运行的闭环。

数据契约核心逻辑图 数据契约核心运作逻辑 数据契约 Schema SLA Owner 血缘 契约定义与注册 自动化校验与告警 违约处理与升级 反馈闭环:违约驱动契约优化 契约不是一次性文档,而是持续演进的「活规则」

这个闭环怎么理解?

  • 定义阶段:生产者和消费者一起敲定 Schema、SLA、Owner、血缘,形成契约文件
  • 执行阶段:系统自动校验数据是否满足契约,不满足就告警
  • 优化阶段:根据违约记录,调整契约条款,让它更贴近实际

你想想看,传统治理里,这三个阶段是割裂的。文档归文档,执行归执行,优化基本靠「出了大事才想起来」。数据契约把它们串成了一个闭环。

避坑提醒:我曾经在一个项目里,把契约定义得过于严格——字段空值率要求 0%,产出时间精确到分钟。结果呢?每天告警几十条,全是误报。团队疲于处理告警,最后把契约功能关了。契约要「够用就好」,别追求完美主义。

小结

数据契约不是什么高深的概念。它就是一份「数据供需双方的书面约定」。四个要素——Schema、SLA、Owner、血缘——缺一不可。和传统治理相比,它的核心优势是:把模糊的承诺变成可验证的规则,把事后追责变成事前预防。