News Hacker|极客洞察

21 184 天前 prisma.io
🥪Expand and Contract 模式:迁移三明治、双写与零停机实践
要零停机就非得做三天迁移吗?

🎯 讨论背景

讨论源自如何在不影响线上可用性的前提下变更数据库 schema,中心思想是先扩展新结构再收缩旧结构(expand-and-contract)。Martin Fowler 的 Parallel Change(并行变更)被作为学术/实践参考,社区常用比喻如 “migration sandwich” 或直接采用“dual writing”和蓝绿式类比来讲解流程。实际操作会用到 alembic(Python 的数据库迁移工具)等迁移工具,也必须面对云环境例如 AWS RDS(Amazon 的托管关系型数据库服务)在短时间窗口内频繁部署的限制。评论中既有对名称和概念的澄清,也有来自大规模 SaaS 的实战经验与对长时间迁移窗口(如 72+ 小时)与运维复杂度的提醒。

📌 讨论焦点

命名与比喻

评论中对同一模式有多种称呼并带有教学或幽默色彩:有人在培训里把它称为“migration sandwich”(迁移三明治),借用“idiot sandwich”梗来形象化多步迁移;也有人直接称之为“dual writing”(双写)或把它类比为一种 schema 层面的 blue-green type deployment(蓝绿式部署)。Martin Fowler 的 Parallel Change(并行变更)被频繁引用作为概念来源,成为“先扩展再收缩”说法的权威出处。这种命名多样性反映出实践者用不同比喻来讲解同一套操作步骤,既有技术性定义也有便于传播的教学比喻。

[来源1] [来源2] [来源3] [来源4] [来源5]

模式细节与实现步骤

实际操作通常分为两步:先 expand(扩展)——向表添加新列或新增表并实现与旧结构的兼容(比如双写或兼容读取),在新结构通过验证后再 contract(收缩)——移除旧列和兼容逻辑。评论指出文章的图示有时画成用独立替代 schema 的样子,但很多实践场景实际上是在现有表上就地变更(例如用 alembic 之类的迁移工具修改列),因此容易产生概念混淆。Strangler Fig Pattern(逐步替换旧系统的模式)与此有交集,但其侧重点在逐步替换整个应用或服务边界,而不是仅针对数据模型的并行变更和双写验证。

[来源1] [来源2] [来源3] [来源4] [来源5]

运行挑战与实践经验

运营者关心的主要问题是迁移耗时与部署窗口:有人提问在 AWS RDS(Amazon 的托管关系型数据库服务)里如何实现每天多次、每次耗时仅几分钟的迁移;现实案例也存在迁移耗时超 72 小时、将数据拆分到数十张表再重构的极端情形,需要在扩展态并行工作数周。另一条实践经验来自大型 SaaS,表明在数千库、数万应用服务器与百万级活跃用户规模下采用 expand-and-contract 确实能实现平滑零停机升级,但代价是更高的运维复杂度、长期并行数据结构与一致性控制。总体上该模式可行但需要在部署窗口、回滚策略与测试能力之间做权衡。

[来源1] [来源2] [来源3]

📚 术语解释

Expand and Contract: 一种并行变更策略:先扩展新字段/表并保持与旧结构兼容(expand),通过双写或流量回放验证后再移除旧字段/兼容代码(contract),用于实现零停机的 schema 迁移。

dual writing: 同时把写入流量写入旧结构和新结构以保持两套数据一致并验证新 schema 的技术手段,便于回滚但需解决写入顺序与冲突问题。

blue-green deployment: 蓝绿部署:通过维护两套并行环境并切换流量来实现零停机升级的策略,在 schema 迁移语境中常被类比为同时存在新旧结构并逐步切换流量。

Strangler Fig Pattern: Strangler Fig Pattern(榕树缠绕/逐步替换模式):一种逐步替换旧系统的架构策略,通常用于从单体迁移到微服务,侧重于按功能逐步替换而非单纯的数据结构变更。