2. 数据契约核心要素:生产者与消费者定义、Schema定义、SLA定义、语义定义、版本管理

数据契约不是一张纸,也不是一个文档。它是一套可执行、可验证的规则。我见过太多团队把契约写成「君子协定」,结果上线第一天就出问题。

说白了,数据契约的核心就五个要素。少了任何一个,契约都会变成摆设。咱们一个一个拆开看。

2.1 生产者与消费者定义:谁生产,谁消费

这是契约的起点。你得先搞清楚数据从哪来,到哪去。

生产者(Producer):数据的提供方。通常是某个微服务、数据管道或外部系统。生产者负责保证数据的格式、质量和时效性。

消费者(Consumer):数据的使用方。可能是另一个服务、数据仓库、报表系统,甚至是机器学习模型。

我个人习惯在契约里明确标注生产者和消费者的系统标识、负责人和联系方式。为什么?因为出了问题你得能找到人。

关键字段示例:

producer:
  system: "order-service"
  owner: "张三"
  slack: "@zhangsan"
  team: "交易中台"

consumer:
  system: "data-warehouse"
  owner: "李四"
  slack: "@lisi"
  team: "数据平台"

我的经验:曾经有个项目,消费者改了消费逻辑,但生产者完全不知情。结果数据格式一变更,下游直接崩了。后来我们在契约里加了「消费者变更通知」字段,强制要求消费者变更前必须通知生产者。

2.2 Schema定义:数据的骨架

Schema 就是数据的结构。字段名、类型、是否必填、默认值……这些都得写清楚。

你想想看,如果生产者突然加了一个字段,消费者没跟上,解析就会报错。或者生产者把字段类型从 int 改成了 string,消费者还在做数学运算……嗯,这都是血泪教训。

我建议用 Avro 或 Protobuf 来定义 Schema,因为它们支持向前/向后兼容性检查。JSON Schema 也行,但兼容性检查得自己写。

Avro Schema 示例:

{
  "type": "record",
  "name": "OrderEvent",
  "fields": [
    {"name": "order_id", "type": "string", "doc": "订单唯一标识"},
    {"name": "user_id", "type": "string", "doc": "用户ID"},
    {"name": "amount", "type": "double", "doc": "订单金额"},
    {"name": "status", "type": "string", "default": "pending", "doc": "订单状态"}
  ]
}

注意:Schema 里一定要写 doc 字段。我曾经接手过一个项目,字段名全是缩写,没有任何注释。我花了三天才搞清楚每个字段的含义。别让你的同事也经历这种痛苦。

2.3 SLA定义:承诺与底线

SLA 是契约的「硬约束」。它定义了生产者必须达到的服务水平。

常见的 SLA 指标包括:

  • 数据延迟:数据从产生到可消费的最大时间间隔
  • 数据可用性:数据在指定时间窗口内的可用百分比
  • 数据完整性:数据丢失率的上限
  • 数据准确性:数据错误率的容忍范围

举个例子:

SLA 指标 承诺值 测量方式
数据延迟 ≤ 5 分钟 生产者时间戳 vs 消费者接收时间戳
数据可用性 ≥ 99.9% 每分钟健康检查
数据完整性 ≥ 99.99% 生产者发送条数 vs 消费者接收条数

避坑指南:我曾经把 SLA 定得太死,比如「数据延迟 ≤ 1 秒」。结果生产者为了满足这个指标,牺牲了数据质量,丢了一堆数据。后来我学乖了——SLA 要合理,要可测量,要有弹性。

2.4 语义定义:数据背后的业务含义

Schema 定义了数据的「形」,语义定义了数据的「意」。

举个例子:status: "1" 是什么意思?是「已支付」还是「已取消」?不同团队可能有不同理解。语义定义就是把这些歧义消除掉。

语义定义通常包括:

  • 枚举值映射:每个值的业务含义
  • 业务规则:数据之间的依赖关系或约束
  • 数据来源:数据是如何产生的,经过了哪些转换
  • 数据用途:数据可以被用于哪些场景,禁止用于哪些场景

语义定义示例:

字段: order.status
枚举值:
  0: "待支付"
  1: "已支付"
  2: "已取消"
  3: "已退款"
业务规则:
  - 状态只能从 0 -> 1 -> 2/3,不能跳转
  - 退款金额不能超过支付金额

注意:语义定义最容易出现「常识性误解」。你以为所有人都知道「1」代表「已支付」,但新来的同事可能以为是「已发货」。所以,写清楚,别靠猜。

2.5 版本管理:契约的演进与兼容

数据契约不是一成不变的。业务在变,Schema 在变,SLA 也在变。版本管理就是让这些变化可控。

我建议使用语义化版本号:

  • 主版本号:不兼容的变更(如删除字段、修改字段类型)
  • 次版本号:向后兼容的变更(如新增可选字段)
  • 修订号:文档或注释的修正

版本管理的关键是兼容性检查。每次变更都要检查:

  • 新版本是否兼容旧版本?
  • 消费者是否需要同步更新?
  • 变更是否会影响现有 SLA?

我的习惯:在契约里加一个 changelog 字段,记录每次变更的原因和影响范围。这样出了问题,你能快速回溯。

核心要素关系图

下面这张图展示了五个要素之间的关系。生产者与消费者是主体,Schema 和 SLA 是约束,语义定义是解释,版本管理是演进机制。

数据契约核心要素关系图 数据契约核心要素关系图 数据契约 生产者 消费者 Schema 定义 SLA 定义 语义定义 版本管理 生产者与消费者是主体,Schema 和 SLA 是约束,语义定义是解释,版本管理是演进机制

小结

这五个要素,缺一不可。生产者与消费者定义了「谁」,Schema 定义了「长什么样」,SLA 定义了「多快多好」,语义定义了「什么意思」,版本管理定义了「怎么变」。

我见过很多团队只关注 Schema,忽略了 SLA 和语义定义。结果数据格式对了,但数据延迟太大,或者业务含义理解错了。嗯,这些都是坑。