Big Systems Advice — 分布式系统核心原则
来源:James Cowling (@jamesacowling) Thread, 2026-04-10
概述
在分布式系统中,没有神奇的"一次性将所有内容推送到生产环境"按钮。每个服务独立推送,服务内的节点逐步更新。如果搞砸了向前/向后兼容性,可能会导致不可恢复的故障。
五大核心原则
1. 数据与代码变更解耦
永远不要在同一个发布中同时推送改变数据存储方式和读取新数据的代码。
原因: 如果有 bug 需要回滚到旧版本代码,它无法处理新格式的新数据。
正确做法(Migration 模式):
- 先推送一个版本,以兼容新旧代码的方式改变数据(如可选字段)
- 稳定后,推送使用新数据的新代码
- 稳定后,再推送移除向后兼容性的数据变更
2. 不要同时改变两个服务
如果服务 A 调用服务 B,不能简单地给两者都添加新 API 然后一起推送。
风险:
- 有人只推送了 A 没推送 B 怎么办?
- B 有 bug 需要回滚怎么办?
正确做法:
- API 变更需要像数据变更一样处理
- 先让新 API 可用(兼容旧调用)
- 稳定后再让调用方使用新 API
3. 生产环境只允许一个版本"步进"
常见情况: 大部分节点在版本 5,但少数还在版本 4(尚未完成迁移)。
绝对禁止: 在版本 4 仍在运行时推送版本 6。
原因: 版本 4 和版本 6 之间没有直接的兼容性保证,可能导致级联故障。
4. 在发布流程中固化向前/向后兼容性
实践方法:
- 将部分节点推送到新版本
- 运行一段时间并持续监控
- 回滚这些节点
- 然后再进行完整发布
目的: 如果有人搞砸了 migration,在完整发布前就能发现。
5. 设计清晰组合的系统
核心特征:
- 简单的 API
- 轻量级客户端
- 类型安全
- 信息隐藏
- 明确表达的保证
避免: API 中任何花哨或模糊的东西。
这是维护具有多个版本共存的大型分布式系统的唯一可行方式。
社区补充观点
关于数据格式
"数据格式悄悄地成为系统中最长寿的 API。一旦数十个服务依赖它们,migration 纪律往往比功能本身更重要。" — @Mazen_AIEx
支付系统的特殊性
"在支付领域,这尤其严重。如果一半的节点在旧代码上,支付状态码的 schema 变更是灾难性的。我们因此维护每个支付事件 schema 的至少两个版本。'不可恢复'在生产环境支付中有真实的美元成本。" — @PsudoMike
生产工程师 vs 教程工程师
"向前/向后兼容性是区分生产工程师和教程工程师的东西。你可以整天 vibe code,但当你有两个服务版本在滚动部署期间同时运行时,真正的工程才开始。" — @ModernGrindTech
Convex 的自动化保障
对于 Convex 客户,大部分这些问题已经被处理:
- 强制完成 schema migration 后才能推送使用它的代码
- 内部处理版本偏移(version skew)
但仍需考虑:如果 migration 在应用后失败会发生什么?
关联
- harness-engineering/overview — Harness Engineering 概述
- harness-engineering/agent-architecture-unsentimental — AI Agent 架构的无情实用主义
- product-trends/codex-team-methodology — Codex 团队方法论