对变更分类
修改模式前先分类:增量可选、增量必填、类型变更、重命名或删除。增量可选字段通常向后兼容;必填新增、重命名和删除需要迁移期。分类决定发布顺序,以及旧数据是否需要 upcast。
{
"version": 2,
"fields": [
{ "name": "id", "type": "string" },
{ "name": "total", "type": "long" },
{ "name": "currency", "type": "string", "default": "USD" }
]
}
示例增加了带默认值的可选字段。不认识该字段的消费者会忽略它;省略该字段的生产者仍能满足消费者。
按兼容顺序发布
对于向后兼容的新增,先部署消费者,或确保它们容忍未知字段,再部署生产者。对于破坏性变更,过渡期同时运行两个版本:写入新旧两种形状,迁移读取方,然后移除旧形状。这与数据库列的 expand-contract 纪律相同。
用 upcasting 保留历史
事件存储保留旧事件。不要重写它们;upcaster 在读取时把旧事件版本转换成当前内存表示。upcaster 必须确定性,并针对真实历史负载测试。原始事件保持不变,供审计和重放。
何时使用
只要独立团队或长期数据共享同一模式,就应显式演进模式。优点是安全、增量的变更;代价是版本和兼容工作。与无版本 JSON 契约相比,模式演进变更更慢,但更不容易悄悄破坏消费者。