Skip to content

升级与回滚 ​

运维如何安全地升级或降级 —— 8 case 升级矩阵、finalize 语义、降级前置检查。

事实来源: 升级矩阵是冻结设计,不是实现状态。每个 case 都是发布门禁:矩阵红 = 阻断发布,不接受「文档里加个脚注」这种处理。

先定方向:我在往哪边走 ​

  • 兼容档内升级(F1、F2、F4、F5、F6)→ 滚动升级,一次一台;复制协议取 min(双方版本)。
  • 跨不兼容档升级(F3)→ 单向。旧二进制拒绝读新 segment,而不是猜着读;这个拒绝本身就是安全特性。
  • 降级(R1、R2)→ 必须先过下面的前置检查。只要存在不可逆的元数据变更,R2 就拒绝,并告诉你是哪一条。

8 case 矩阵 ​

#旧格式新格式方向期望行为诊断要求来源依据
F1segment format_version=1segment format_version=1同版本正常读写—基线
F2segment format_version=1segment format_version=2(兼容档)v1 读 v0必须可读;golden 测试锁定字节级行为—Kafka 降级规则(无 metadata 变更才可降级)
F3segment format_version=1segment format_version=2(不兼容档)v0 读 v1拒绝启动或拒绝该 segment;SEGMENT_VERSION_TOO_NEW错误必须含文件路径 + version 值NSQ LoadMetadata 解析失败报错先例
F4metadata log MMML v1MMML v2v0 读 v1同 F3;未知 record type 按 version 规则处理同 F3Kafka MetadataVersion 布尔位
F5client protocol v0broker protocol v1旧客户端协商降级,或以 UNSUPPORTED_VERSION(0x0004)拒绝错误码必须可行动(RocketMQ #504 教训)—
F6混合滚动中的 brokerleader v1 / follower v0复制流复制协议取 min(双方版本);记录 deprecation 警告警告必须点名双方版本Kafka 滚动升级逐台先例(upgrade.md:94)
R1兼容档v2 → v1回滚允许;先跑降级前置检查—RabbitMQ COMPATIBILITY 区间记法;Kafka upgrade.md:96
R2不兼容档v2 → v1回滚拒绝,并点名哪些 metadata 变更不可逆必须列出不可逆项KIP-848(采用新协议后只能降级到 3.4.1+);Kafka upgrade.md:294

最该读懂的两个方向 ​

F3 才是关键。 不兼容读不是「先把数据写坏再说」,而是一次拒绝,而且这次拒绝必须可行动:不给文件路径和版本号,运维面对 64 MiB 的 segment 根本不知道是哪一个出问题。这就是为什么「诊断要求」是硬性要求而不是锦上添花。

R2 是诚实边界。 不是每次降级都可能,假装可以正是集群被搞挂的方式。R2 按设计拒绝,并点名不可逆变更 —— 与威胁模型里「诚实边界」是同一套纪律。

finalize 语义 ​

占位:复制流的 finalize 规则尚未定义;升级是两阶段的(Kafka 滚动升级模型)。

降级前置检查 ​

  • [ ] wire_version 未递增
  • [ ] segment / 元数据 format_version 仍在兼容档内
  • [ ] 没有残留的 quarantine/ 目录
  • [ ] 档位边界之后没有新增的 metadata record type(否则 R2 在这一行就该拒绝)

目前还没有代码

今天没有二进制可以升级。这张矩阵是发布门禁 —— 升级矩阵脚本落地后,这 8 个 case 进 CI,任一行红就阻断发布。