2. 数据契约生命周期:契约的创建、版本管理、审批流程、发布与订阅
数据契约不是写一次就完事的文档。它跟代码一样,有自己的生命周期。
我见过不少团队,上来就定义了一堆契约,结果三个月后没人维护,全成了摆设。说白了,契约的生命周期管理没做好,再好的规范也落不了地。
这一章,咱们就聊聊契约从生到死的完整流程。我把自己踩过的坑、总结的经验都放进来。
2.1 契约的创建:从哪开始?
契约的创建,通常有几种触发场景:
- 新业务上线:比如要做一个用户画像系统,需要消费订单数据。这时候,消费方就得找生产方要一份契约。
- 接口变更:老接口要加字段、改类型,不能直接改,得先更新契约。
- 数据迁移:底层表结构变了,但对外承诺的数据格式不能变,契约就是那个“中间层”。
我个人习惯,创建契约时先回答三个问题:
- 谁生产? 哪个团队、哪个系统、哪个表或 Topic。
- 谁消费? 下游有哪些应用、报表、算法模型。
- 承诺什么? 字段定义、类型、约束、SLA。
核心原则:契约的创建,必须由生产方主导,但消费方要参与评审。我曾经见过生产方自己闷头写契约,写完扔给消费方,结果字段命名对不上,类型也不匹配,来回改了五版。后来我们改成“双人复核制”——生产方起草,消费方确认,才算把这个坑填上。
一个典型的契约创建流程,大概长这样:
# 伪代码:契约创建流程
1. 消费方提交数据需求(字段列表、频率、延迟容忍度)
2. 生产方评估可行性(数据是否已有、是否需要ETL改造)
3. 双方协商字段定义(名称、类型、是否必填、枚举值范围)
4. 生产方起草契约草案(YAML/JSON格式)
5. 提交到契约仓库(Git),发起Pull Request
2.2 版本管理:契约也是代码
契约的版本管理,我强烈建议直接用 Git。别自己搞一套数据库版本号,那玩意儿追查历史太痛苦了。
为什么用 Git?
- 天然支持版本回溯:哪个版本改了啥,谁改的,一目了然。
- 分支策略灵活:可以跟代码分支对齐,feature 分支改契约,合 master 时一起合。
- Diff 对比:两个版本之间字段增减、类型变化,Git diff 看得清清楚楚。
我遇到过最头疼的事,就是生产方偷偷改了接口字段类型,没通知任何人。下游消费方第二天发现数据解析全挂了。后来我们规定:契约版本号必须遵循语义化版本。
| 版本号示例 | 变更类型 | 说明 |
|---|---|---|
| 1.0.0 → 2.0.0 | Major(不兼容) | 删字段、改类型、改必填属性 |
| 1.0.0 → 1.1.0 | Minor(兼容) | 新增可选字段、扩展枚举值 |
| 1.0.0 → 1.0.1 | Patch(修复) | 修正描述、调整示例值 |
小技巧:在契约文件的头部,用注释写明版本号和变更日志。这样即使脱离 Git,单看文件也能知道版本演进。我习惯在 YAML 文件第一行写 # version: 1.2.0,第二行写 # changelog: 2024-03-15 新增 user_level 字段。
2.3 审批流程:别让一个人说了算
契约的审批,本质上是一种“风险控制”。
你想想看,一个契约改了,可能影响几十个下游系统。如果没人把关,随便一个人改了就能上线,那不出事才怪。
我建议的审批流程分三级:
- 技术审批:检查字段定义是否合理、类型是否正确、SLA 是否可达。通常由生产方的技术负责人做。
- 业务审批:确认业务语义是否准确、枚举值是否覆盖全场景。通常由数据产品经理或业务方做。
- 安全审批:检查是否涉及敏感字段(手机号、身份证等),是否需要脱敏。通常由数据安全团队做。
这里有个常见的坑:审批流程太长,导致业务等不及,直接绕开契约改代码。我曾经在一个大厂看到,一个契约审批要走 5 个人,平均耗时 3 天。后来业务方受不了,直接在生产库上改了字段,契约成了摆设。
避坑指南:审批流程不要超过 3 级。如果超过,说明你们的组织架构或者职责划分有问题。我建议用自动化工具(比如 GitLab CI + 自定义 Bot)来跑审批,Minor 变更可以自动通过,只有 Major 变更才需要人工介入。
2.4 发布与订阅:契约的“最后一公里”
契约审批通过后,怎么让消费方知道?怎么让消费方用起来?
这就是发布与订阅要做的事。
发布,指的是把契约注册到一个中心化的服务里。我见过两种主流做法:
- Git 仓库 + Webhook:契约合入 master 后,触发 Webhook,通知注册中心更新。
- Schema Registry:像 Confluent Schema Registry 那样,专门管理 Avro/Protobuf 契约,支持兼容性检查。
订阅,指的是消费方主动或被动获取契约。我个人推荐“推拉结合”:
- 推:契约变更时,通过消息队列或邮件,通知所有订阅方。
- 拉:消费方在启动时,从注册中心拉取最新契约,本地缓存一份。
嗯,这里要注意:推模式不能保证 100% 送达。我遇到过邮件被拦截、消息队列积压的情况。所以一定要有“拉”兜底。消费方启动时如果拉不到契约,应该直接报错,不让服务启动。
最佳实践:在消费方代码里,把契约版本号写进配置。启动时对比本地版本和注册中心版本,如果不一致,强制更新。这样能避免“我以为我用的新契约,其实还是老版本”的尴尬。
2.5 生命周期全景图
说了这么多,咱们用一张图把整个生命周期串起来。这张图我画了很多次,每次给团队培训都用它。
这张图里,我特意画了一个从“变更/废弃”回到“版本管理”的虚线箭头。为什么?因为契约的生命周期不是线性的,它是一个闭环。契约发布之后,随着业务变化,一定会再次变更。每一次变更,都重新走一遍创建、版本管理、审批、发布、订阅的流程。
我的经验:很多团队把契约当成“一次性文档”,写完就不管了。实际上,契约的维护成本不比代码低。我建议每个季度做一次契约健康度检查——看看哪些契约长期没有变更、哪些契约的订阅方已经不再使用、哪些契约的 SLA 已经无法满足。该废弃的就废弃,该更新的就更新。不然,契约仓库里堆满僵尸契约,比没有契约更可怕。