Skip to content

第四章:编码与演化

1. 为什么要关注编码与演化

分布式系统中,数据总在跨进程、跨机器、跨时间流动。只要存在版本不一致,就会出现兼容性问题。编码格式与模式演化规则决定了系统能否平滑升级。

2. 数据编码格式

2.1 语言私有序列化

Java SerializablePython pickle,开发便利但跨语言差、安全风险高、版本演化能力弱,不适合作为长期公共协议。

2.2 文本格式

JSONXMLCSV 可读性高、生态成熟,但存在体积大、类型表达不精确、二进制字段处理笨重等问题。

2.3 二进制变体

MessagePackBSON 等在体积与性能上优于纯文本,但若仍携带字段名,压缩收益有限。

3. 基于模式的二进制协议

3.1 Thrift 与 Protocol Buffers

两者通过 IDL 定义 schema,运行时以字段编号编码,兼顾紧凑性与可演化性。

3.1.1 演化规则

  • 新增字段应为可选或具备默认值。
  • 删除字段后不应复用旧字段编号。
  • 类型变更需保证兼容转换路径。

3.2 Avro

Avro 不在数据中写字段编号,依赖写入 schema 与读取 schema 的解析规则完成兼容。

3.2.1 适用场景

  • 大数据离线文件(schema 写在文件头)。
  • 配合 Schema Registry 的事件流。
  • 动态语言与数据导出场景。

3.3 Schema 的工程价值

  • 降低协议歧义。
  • 支撑滚动升级。
  • 为自动校验、代码生成与治理平台提供基础。

4. 数据流与兼容性

4.1 经由数据库的数据流

数据库里的数据生命周期往往长于应用代码版本。滚动升级期间,旧代码可能读新数据,新代码也要读旧数据,因此通常要求同时满足前向与后向兼容。

4.2 经由服务的数据流

4.2.1 REST 与 RPC

  • REST:基于 HTTP 资源语义,调试友好,演化成本低。
  • RPC:性能更高,但不能假装“远程调用等价本地调用”,必须显式处理超时、重试、幂等与部分失败。

4.2.2 RPC 设计要点

  • 区分超时、失败与未知结果。
  • 写接口优先幂等语义。
  • 用版本化协议与兼容字段做灰度发布。

4.3 经由消息系统的数据流

消息代理在发送者和消费者之间提供缓冲与解耦,适合异步架构与削峰填谷。

4.3.1 消息格式约束

Broker 通常只处理字节,不理解业务 schema。若无统一协议治理,版本漂移会快速累积为兼容性事故。

4.3.2 Actor 模型

分布式 Actor(如 Akka)把并发与消息传递统一,但跨版本部署时同样依赖稳定消息协议。

5. 落地建议

  • 对外协议优先使用“可演化 schema + 版本治理”。
  • 为事件流建立 schema 注册与兼容检查。
  • 升级流程采用“先兼容、后切换、再清理”的三阶段策略。