题干与适用场景
这次迁移同时改变字段名与业务语义:total_cents 默认美元,amount_minor 则必须配合明确币种使用。Avro alias 只能帮助名称解析,不能证明旧的“美分”语义已正确迁移为“货币最小单位”。
面试官考察点
- 是否先扩展 reader,再让 producer 写新字段。
- 是否把结构兼容检查与金额语义校验分开。
- 是否为 90 天历史重放保留旧 Schema 和转换规则。
- 是否用消费证据决定退役,而非按日历直接删字段。
回答前需要澄清的问题
确认事件格式、注册中心兼容模式、每个消费者能否忽略未知字段、金额是否始终整数最小单位、币种字段是否已存在,以及最慢消费者和回放任务的升级周期。还要确认是否允许建立 v2 topic;语义无法双向表达时需要新边界。
30 秒回答框架
我会先新增可选 amount_minor 和 currency,旧 producer 仍写 total_cents。所有消费者先升级为“优先读新字段,否则回退旧字段”,并对美元事件校验两值相等。覆盖率达标后 producer 双填,随后停止新业务读取旧字段。保留历史 Schema 与回放转换 90 天以上;只有 producer 停写、消费者与离线依赖停读,并且完整的 90 天回放验证通过后,才注册移除旧字段的版本。
分步骤深入解答
第一阶段只做兼容扩展。注册中心在选定的兼容策略下阻止不合规 Schema;CI 还运行跨版本 reader/writer 矩阵。消费者升级后能够读取旧事件,并在新字段存在时使用 amount_minor + currency。
第二阶段 producer 双填。美元事件要求 amount_minor == total_cents 且 currency == USD;其他币种只把真实最小单位写入新字段,不能伪装成 cents。按 producer 版本、消费者和币种统计新字段覆盖率、回退次数与语义差异。
第三阶段停止旧字段业务依赖,但继续保留兼容读取和历史 Schema。回放器根据 writer schema ID 选择转换,不能用今天的默认值重写历史含义。若新语义无法在原 subject 中保持所需兼容性,发布 v2 topic 和显式转换器,双跑并对账后迁移。
最后以证据退役:所有 producer 停写、消费者回退为零、90 天重放通过、死信与离线作业完成盘点。删除前保留回滚 Schema 和转换代码的发布版本。
高质量示范回答
我会采用 expand-migrate-contract。先扩展 Schema,消费者兼容读新旧字段;再让 producer 双填并进行金额语义对账。alias 不能验证币种,因此 CI 和运行时都校验美元等价关系,并让非美元流量始终使用新契约。
切换后旧字段仍保留一个完整重放窗口,每个历史事件按 writer schema ID 解码并转换。美元双写不一致时冻结扩量,该批次暂以 total_cents 为准并修复 producer;非美元事件继续以 amount_minor + currency 为准,暂停新增流量或转入 v2 topic,不能伪造 cents 回退值。旧字段退役后,两个新字段成为必填运行时不变量。生产者、消费者、离线任务和回放全部关闭旧路径后,才进入 contract 阶段。
常见错误
- 一次提交直接把旧字段改名。
- 认为 Avro alias 会完成金额语义转换。
- producer 先发布,旧消费者尚未准备好。
- 用当前默认币种解释 90 天历史事件。
- 只查在线消费者,遗漏回放和离线任务。
追问及应对
alias 为什么不够?
它能辅助字段名称解析,不能证明 cents 与任意币种最小单位的业务含义相同。
何时必须使用 v2 topic?
新旧语义无法在一个兼容 Schema 中无歧义表达,或消费者无法按要求升级时,用新 topic 建立明确版本边界。
双写出现不一致怎么办?
美元双写不一致时停止扩量,该批次暂以 total_cents 为准,按 producer 版本隔离、修复并重放。非美元事件继续以 amount_minor + currency 为准,暂停接入或转入 v2 topic,不能回退到虚构的 cents 值。
旧字段何时可删除?
所有 producer 停写、消费者回退为零、完整历史窗口回放通过且离线依赖清单清零之后。