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 和语义定义。结果数据格式对了,但数据延迟太大,或者业务含义理解错了。嗯,这些都是坑。