2、数据契约的核心要素:Schema定义、语义约束、SLA承诺、版本管理
数据契约这东西,说白了就是一份双方都认的「数据君子协定」。我见过太多团队上来就写契约,结果写出来的东西没人看得懂,更没人执行。为什么会这样?因为核心要素没抓住。
我个人习惯把数据契约拆成四个支柱:Schema定义、语义约束、SLA承诺、版本管理。缺一个,这契约就是废纸。
核心观点:数据契约不是文档,是可执行的约定。四个要素必须同时落地,缺一不可。
2.1 Schema 定义:契约的骨架
Schema 是数据契约最基础的部分。你想想看,连字段名、类型、长度都没说清楚,后面谈什么约束和 SLA?
我在项目中遇到过最坑的事:生产者和消费者对同一个字段的理解完全不一样。生产者传的是「用户等级编码」,消费者以为是「用户等级名称」。结果数据一落地,全是乱码。
一个合格的 Schema 定义,至少包含这些:
- 字段名:统一小写蛇形命名,别搞驼峰和帕斯卡混用
- 数据类型:精确到子类型,比如
decimal(18,2)而不是number - 是否必填:
required还是optional - 默认值:空值时的兜底策略
- 枚举范围:如果字段值有限,列出来
我的习惯:Schema 定义用 Protobuf 或 Avro 写,别用 JSON Schema。前者有强类型校验,后者太灵活,容易出幺蛾子。
举个例子,一个用户信息表的 Schema 定义:
syntax = "proto3";
message UserInfo {
string user_id = 1; // 用户ID,必填
string user_name = 2; // 用户名,必填
int32 age = 3; // 年龄,可选
string email = 4; // 邮箱,必填
UserLevel level = 5; // 用户等级,枚举
string created_at = 6; // 创建时间,ISO8601格式
}
enum UserLevel {
LEVEL_UNKNOWN = 0;
LEVEL_NORMAL = 1;
LEVEL_VIP = 2;
LEVEL_SVIP = 3;
}
2.2 语义约束:契约的灵魂
Schema 只说了「长什么样」,语义约束才告诉你怎么用。嗯,这里要注意——很多团队把语义约束写在文档里,而不是代码里。这等于没写。
语义约束包括:
- 业务规则:比如「订单金额必须大于0」、「年龄必须在0-150之间」
- 关联约束:比如「如果用户等级是VIP,积分不能低于1000」
- 时序约束:比如「创建时间不能晚于更新时间」
- 唯一性约束:比如「同一个订单号不能出现两次」
我曾经在一个金融项目中吃过亏。生产者说「交易金额是正数」,消费者以为「交易金额可以是负数(退款)」。两边都没在契约里写清楚,结果线上对账差了300多万。排查了三天,最后发现是语义约束没落地。
避坑指南:语义约束必须写在契约定义里,用断言或校验规则表达。别指望口头约定或 Wiki 文档,人脑靠不住。
语义约束的写法,我推荐用 JSON Schema 的 if-then-else 或者 Protobuf 的 custom option:
{
"type": "object",
"properties": {
"order_amount": { "type": "number" },
"order_status": { "type": "string", "enum": ["pending", "paid", "cancelled"] }
},
"if": {
"properties": { "order_status": { "const": "paid" } }
},
"then": {
"properties": { "order_amount": { "minimum": 0.01 } }
}
}
2.3 SLA 承诺:契约的牙齿
没有 SLA 的数据契约,就像没有牙齿的老虎——看着吓人,咬不了人。
SLA 承诺要回答三个问题:
- 数据多久到?——延迟要求
- 数据准不准?——质量要求
- 数据能不能用?——可用性要求
我建议用表格把 SLA 指标写清楚:
| SLA 维度 | 指标 | 典型值 | 衡量方式 |
|---|---|---|---|
| 延迟 | P99 延迟 | < 5 秒 | 端到端时间戳 |
| 吞吐 | 每秒处理条数 | > 1000 TPS | 监控系统 |
| 数据质量 | 空值率 / 异常率 | < 0.1% | 质量巡检 |
| 可用性 | 服务可用时间 | 99.9% | 健康检查 |
关键点:SLA 必须可量化、可监控、可追责。写「尽快送达」这种模糊词,等于没写。
我个人习惯在契约里加一个 SLA 违约条款:比如连续3个周期不达标,消费者有权暂停消费,生产者必须在24小时内修复。别怕写得狠,契约就是用来约束双方的。
2.4 版本管理:契约的生命线
数据契约不是写一次就完事的。业务在变,Schema 在变,约束在变。怎么管?
版本管理要解决三个核心问题:
- 向前兼容:新版本能不能被老消费者消费?
- 向后兼容:老版本的数据能不能被新消费者处理?
- 版本演进:怎么从 v1 平滑过渡到 v2?
我记得有一次,团队直接改了生产者的 Schema,把字段类型从 int 改成了 string。消费者那边没收到通知,结果消费端全部报错。这就是典型的版本管理缺失。
我推荐的版本管理策略:
- 语义化版本号:
MAJOR.MINOR.PATCHMAJOR:不兼容变更(删字段、改类型)MINOR:向后兼容的新增(加可选字段)PATCH:内部修复(改注释、改约束描述)
- 版本共存期:大版本升级时,新旧版本至少共存 2 个发布周期
- 废弃通知:废弃字段要提前 3 个版本标记
deprecated
我的习惯:用 Schema Registry 管理版本。每次变更自动生成 diff,通知所有消费者。别靠人工发邮件,人总会忘。
版本管理的代码示例(Protobuf 版本标注):
message UserInfo {
string user_id = 1;
string user_name = 2;
int32 age = 3 [deprecated = true]; // 废弃,改用 birth_date
string email = 4;
UserLevel level = 5;
string created_at = 6;
string birth_date = 7; // v2.0.0 新增
}
小结一下
四个要素,各有各的用处:
- Schema 定义——让数据长什么样,双方看得见
- 语义约束——让数据怎么用,双方说得清
- SLA 承诺——让数据好不好,双方量得出
- 版本管理——让数据怎么变,双方控得住
你想想看,这四个要素都落地了,数据契约还会是一纸空文吗?