返回架构笔记
Arch Day 104

Arch Day 104: 遗留系统改造 — "在飞行中换引擎"

Arch Day 104: 遗留系统改造 — "在飞行中换引擎"

2026-07-12
第四阶段 - 高阶融合
遗留系统StranglerFig防腐层数据迁移系统改造渐进式迁移

日期: 2026-07-12 (Day 104) 阶段: 第四阶段 - 高阶融合 标签: #遗留系统 #StranglerFig #防腐层 #数据迁移 #系统改造 #渐进式迁移


核心概念

遗留系统改造是"在飞行中换引擎"——最难的架构挑战之一

遗留系统改造之所以被称为架构师面临的最难挑战,不是因为技术本身有多复杂(虽然确实复杂),而是因为它同时涉及技术风险、业务连续性、组织政治和人员能力四个维度的挑战。

为什么遗留系统改造如此困难?

技术维度:
├── 代码量巨大(百万级LOC,无人完全理解)
├── 文档缺失("唯一的文档就是代码本身")
├── 测试缺失("改一行代码不知道会坏什么")
├── 技术栈过时(没人会维护的语言/框架)
└── 耦合严重("动一个模块,全系统抖三抖")

业务维度:
├── 24/7不能停("银行系统不能说停就停")
├── 数据不能丢("一笔交易都不能少")
├── 功能不能降("新系统至少要和旧的一样")
└── 用户无感知("切换对用户透明")

组织维度:
├── 旧系统维护团队的抵触("你要革我命?")
├── 管理层的恐惧("万一搞砸了谁负责?")
├── 预算争夺("这个投资什么时候能回本?")
└── 人才缺乏("谁既懂老系统又懂新技术?")

2025-2026年遗留系统改造的新动力

根据行业趋势,遗留系统改造的紧迫性在加速:

  1. 大型机人才退休潮——懂COBOL的工程师越来越少
  2. AI和数据驱动业务需要现代化数据架构
  3. 云原生技术成熟,改造的技术风险降低
  4. 监管要求系统韧性和灾备能力提升
  5. 竞争对手的数字化转型压力

知识点详解

一、评估框架:改造 vs 替换 vs 封装 vs 退役

在动手之前,最重要的决策是:这个遗留系统应该怎么处理?

四种策略

┌──────────────┐     ┌──────────────┐
│   改造        │     │   替换        │
│ (Modernize)  │     │ (Replace)    │
│              │     │              │
│ 渐进式迁移    │     │ 全新系统替代   │
│ 保留核心逻辑  │     │ 推倒重来      │
│ 风险中等      │     │ 风险最高      │
└──────────────┘     └──────────────┘

┌──────────────┐     ┌──────────────┐
│   封装        │     │   退役        │
│ (Encapsulate)│     │ (Retire)     │
│              │     │              │
│ 包一层API     │     │ 关闭系统      │
│ 内部不动      │     │ 数据归档      │
│ 风险最低      │     │ 最简单       │
└──────────────┘     └──────────────┘

决策矩阵

因素改造替换封装退役
业务价值高首选可选次选不适用
业务价值低不值得不值得短期方案首选
技术风险高谨慎考虑安全选择考虑
时间紧迫不适合不适合首选可能
预算充足首选可选次选简单
预算有限分期不适合首选首选
团队能力强首选可选不需要简单
团队能力弱困难更困难首选简单

评估维度详解

评估每个遗留系统的六个维度(每项1-5分):

1. 业务价值 (Business Value): 1=低 5=核心
   └── 这个系统对业务有多重要?

2. 技术质量 (Technical Quality): 1=腐烂 5=良好
   └── 代码质量、测试覆盖、文档完整度

3. 变更频率 (Change Frequency): 1=几乎不变 5=频繁变更
   └── 多久需要修改一次功能?

4. 运维成本 (Maintenance Cost): 1=低 5=极高
   └── 维护这个系统需要多少人力/成本?

5. 风险等级 (Risk Level): 1=低风险 5=高风险
   └── 改造过程中出问题的影响有多大?

6. 技术债严重度 (Tech Debt Severity): 1=轻 5=极重
   └── 技术债对未来发展的阻碍有多大?

决策矩阵:
├── 高业务价值 + 低技术质量 + 高变更频率 → 改造(最优先)
├── 高业务价值 + 极低技术质量 → 替换(改造成本可能超过替换)
├── 高业务价值 + 低变更频率 → 封装(投入产出比最高)
├── 低业务价值 + 高运维成本 → 退役(减少浪费)
└── 高风险 + 任何策略 → 渐进式+充分测试

二、绞杀者模式(Strangler Fig Pattern)深度

模式起源

Martin Fowler受到自然界"绞杀榕"的启发提出这个模式——绞杀榕从其他树的树冠开始生长,根系逐渐包裹宿主树,最终宿主树死亡,绞杀榕取而代之。

这个比喻完美描述了遗留系统改造的理想过程:新系统逐步接管旧系统的功能,而非一次性替换。

四个阶段

阶段1: 识别(Identify)
┌─────────────────────────────┐
│         旧系统               │
│  ┌────┐ ┌────┐ ┌────┐      │
│  │ A  │ │ B  │ │ C  │ ...  │
│  └────┘ └────┘ └────┘      │
│  识别可独立迁移的功能模块      │
└─────────────────────────────┘

阶段2: 抽取(Extract)
┌──────────┐   ┌──────────────┐
│  新服务A  │   │   旧系统      │
│          │   │  ┌────┐ ┌────┐│
│  (重写) │   │  │ B  │ │ C  ││
│          │   │  └────┘ └────┘│
└──────────┘   └──────────────┘
    新建微服务重写功能A

阶段3: 重定向(Redirect)
     ┌──────────────────┐
     │   路由层/代理      │
     │   (API Gateway)  │
     └─┬──────────┬─────┘
       │          │
       ▼          ▼
┌──────────┐ ┌──────────────┐
│  新服务A  │ │   旧系统      │
│  ← 流量  │ │  ┌────┐ ┌────┐│
│          │ │  │ B  │ │ C  ││
└──────────┘ │  └────┘ └────┘│
             └──────────────┘
    流量逐步从旧系统路由到新服务

阶段4: 退役(Retire)
┌──────────┐ ┌──────────┐ ┌──────────┐
│  新服务A  │ │  新服务B  │ │  新服务C  │
│          │ │          │ │          │
└──────────┘ └──────────┘ └──────────┘
    旧系统完全退役

关键实施细节

识别阶段的方法

如何选择第一个迁移的模块?

优先选择:
├── 变更频率高的模块(迁移后收益最大)
├── 耦合度低的模块(迁移风险最小)
├── 业务边界清晰的模块(容易定义接口)
└── 团队最熟悉的模块(减少认知负担)

避免先迁移:
├── 核心交易模块(风险太高)
├── 与多个模块深度耦合的模块(牵一发动全身)
├── 数据模型最复杂的模块(数据迁移难度大)
└── 团队不了解的模块(认知风险)

路由层设计

路由层是绞杀者模式的核心组件——它决定每个请求去旧系统还是新服务:

路由策略:
├── 路径路由: /api/users → 新服务, /api/legacy/* → 旧系统
├── 百分比路由: 10%流量→新服务, 90%→旧系统(金丝雀)
├── 用户路由: 白名单用户→新服务, 其余→旧系统
├── Feature Flag: 基于功能开关切换
└── 数据路由: 新用户→新服务, 存量用户→旧系统

技术实现:
├── API Gateway (Kong/APISIX/Envoy)
├── 反向代理 (Nginx/HAProxy)
├── Service Mesh (Istio)
└── 应用层路由 (BFF)

2025-2026年绞杀者模式的最新实践

根据最新的行业实践,关键经验包括:

  1. 不要同时转换整个系统:实施增量变更,验证结果,然后有条不紊地推进
  2. 可观测性是关键:增量改造只有在能够准确测量系统健康时才有效
  3. 保守提取:从小处开始——避免大规模的初始提取。维护严格的API契约。避免遗留系统和新服务之间共享数据库
  4. 与数据流结合:使用Kafka等数据流平台实现遗留系统和新系统之间的数据同步,避免"双写"反模式

三、防腐层(Anti-Corruption Layer)设计

什么是防腐层?

防腐层是DDD中的重要模式——在新系统和旧系统之间建立一个翻译层,防止旧系统的"坏"模型"污染"新系统的设计。

                    Anti-Corruption Layer (ACL)
                    ┌───────────────────────┐
新系统              │  翻译/适配/转换         │              旧系统
(新领域模型)  ◄────▶│                       │◄────▶  (旧数据模型)
                    │  ├── Model Translator │
                    │  ├── Facade           │
                    │  └── Adapter          │
                    └───────────────────────┘

防腐层的三个组件

1. Facade(外观)
   └── 为旧系统提供简化接口
   └── 隐藏旧系统的复杂性

2. Adapter(适配器)
   └── 将旧系统的接口转换为新系统期望的接口
   └── 处理协议差异(SOAP→REST, CSV→JSON等)

3. Translator(翻译器)
   └── 将旧系统的领域模型翻译为新系统的领域模型
   └── 处理概念差异(旧系统的"客户"≠新系统的"用户")

防腐层实现示例

# 旧系统的数据模型(COBOL系统产生的格式)
class LegacyCustomerRecord:
    CUST_NO = "0012345"        # 7位客户号
    CUST_NM = "ZHANG SAN    "  # 固定长度,大写
    ACCT_BAL = "000123456"     # 9位整数,单位分
    CUST_STS = "A"             # A=Active, I=Inactive
    OPEN_DT = "20200115"       # YYYYMMDD格式

# 新系统的领域模型(现代设计)
@dataclass
class Customer:
    id: str                    # UUID
    legacy_id: str             # 保留旧ID用于追溯
    name: str
    balance: Decimal
    status: CustomerStatus     # Enum
    created_at: datetime

# 防腐层 - Translator
class CustomerTranslator:
    def from_legacy(self, record: LegacyCustomerRecord) -> Customer:
        return Customer(
            id=str(uuid4()),
            legacy_id=record.CUST_NO.strip(),
            name=record.CUST_NM.strip().title(),  # "ZHANG SAN" → "Zhang San"
            balance=Decimal(record.ACCT_BAL) / 100,  # 分→元
            status=self._map_status(record.CUST_STS),
            created_at=datetime.strptime(record.OPEN_DT, "%Y%m%d")
        )

    def to_legacy(self, customer: Customer) -> LegacyCustomerRecord:
        record = LegacyCustomerRecord()
        record.CUST_NO = customer.legacy_id.zfill(7)
        record.CUST_NM = customer.name.upper().ljust(15)
        record.ACCT_BAL = str(int(customer.balance * 100)).zfill(9)
        record.CUST_STS = self._reverse_map_status(customer.status)
        record.OPEN_DT = customer.created_at.strftime("%Y%m%d")
        return record

    def _map_status(self, legacy_status: str) -> CustomerStatus:
        mapping = {"A": CustomerStatus.ACTIVE, "I": CustomerStatus.INACTIVE}
        return mapping.get(legacy_status, CustomerStatus.UNKNOWN)

# 防腐层 - Facade + Adapter
class LegacyCustomerService:
    """隐藏旧系统的SOAP接口复杂性"""

    def __init__(self, soap_client, translator):
        self.client = soap_client
        self.translator = translator

    def get_customer(self, customer_id: str) -> Customer:
        # Adapter: SOAP → Python对象
        legacy_record = self.client.call("GetCustomer", CUST_NO=customer_id)
        # Translator: 旧模型 → 新模型
        return self.translator.from_legacy(legacy_record)

四、渐进式数据迁移

数据迁移是遗留系统改造中最复杂也最容易出错的部分。

双写→同步→切换→清理

阶段1: 双写(Dual Write)
┌──────────┐
│ 新服务    │──写──▶ 新数据库
│          │──写──▶ 旧数据库(通过ACL)
└──────────┘
⚠️ 风险: 两个写入不是原子操作,可能不一致
解决: 使用事件驱动(写新库→发事件→旧库消费事件)

阶段2: 数据同步
┌──────────┐          ┌──────────┐
│ 旧数据库  │──CDC──▶  │ 新数据库  │
│ (Source)  │  (Debezium)│ (Target) │
└──────────┘          └──────────┘
├── Change Data Capture捕获旧库变更
├── 实时同步到新库
└── 定期一致性校验

阶段3: 切换读写
┌──────────┐
│ 新服务    │──读写──▶ 新数据库 (主)
│          │──只读──▶ 旧数据库 (备)
└──────────┘
├── 新库成为主数据源
├── 旧库保持只读同步(回滚用)
└── 监控数据一致性

阶段4: 清理
┌──────────┐
│ 新服务    │──读写──▶ 新数据库
└──────────┘
├── 停止向旧库同步
├── 旧数据库数据归档
├── 旧数据库退役
└── 保留归档数据(合规要求)

双写的危险和替代方案

"双写"是最常见但也是最危险的数据迁移反模式:

双写反模式:
App → 写新库 (成功)
App → 写旧库 (失败!) ← 数据不一致!

更安全的替代方案:

方案1: 事件驱动双写
App → 写新库 → 发布事件 → 旧库消费者写旧库
优点: 最终一致性保证
缺点: 旧库数据有延迟

方案2: CDC(Change Data Capture)
App → 写旧库(不改现有逻辑)
旧库 → CDC工具(Debezium) → 新库
优点: 零代码改动,最安全
缺点: 新库数据有延迟

方案3: 事务性发件箱(Transactional Outbox)
App → 在同一事务中写业务表+发件箱表
定时任务 → 读发件箱 → 同步到新库
优点: 数据一致性最强
缺点: 实现复杂

数据一致性校验

校验策略:
├── 实时校验: 每次写入后比较新旧库
│   └── 适合: 关键交易数据
│
├── 定期校验: 每小时/每天全量比对
│   └── 适合: 大量数据
│
└── 采样校验: 随机采样N%数据比对
    └── 适合: 海量数据(全量比对太慢)

校验维度:
├── 计数校验: 新旧库记录总数一致
├── 聚合校验: SUM(amount)等聚合值一致
├── 明细校验: 逐条比对关键字段
└── 哈希校验: 对数据块计算哈希值比对

五、功能剥离策略

按域剥离(Domain-based)

旧单体系统:
┌──────────────────────────────────┐
│  用户管理 │ 订单管理 │ 支付 │ 库存 │
└──────────────────────────────────┘

剥离顺序(按DDD限界上下文):
Phase 1: 用户管理 → User Service
Phase 2: 库存管理 → Inventory Service
Phase 3: 订单管理 → Order Service
Phase 4: 支付处理 → Payment Service(最后,因为最核心)

按能力剥离(Capability-based)

不是按业务域,而是按技术能力剥离:
Phase 1: 通知能力 → Notification Service(影响最小)
Phase 2: 报表能力 → Reporting Service(只读,低风险)
Phase 3: 搜索能力 → Search Service(Elasticsearch替代数据库全文搜索)
Phase 4: 认证能力 → Auth Service(安全关键,需谨慎)

按流量剥离(Traffic-based)

高流量路径优先迁移(收益最大):
Phase 1: 首页/搜索(>50%流量)→ 新系统
Phase 2: 商品详情 → 新系统
Phase 3: 购物车 → 新系统
Phase 4: 下单/支付 → 新系统(最后,最关键)

按风险剥离(Risk-based)

低风险模块先迁移(积累经验和信心):
Phase 1: 帮助中心/FAQ(零风险试水)
Phase 2: 用户设置/偏好(低风险)
Phase 3: 通知/消息(中低风险)
Phase 4: 交易/支付(高风险,有了经验再动)

六、遗留系统改造的组织挑战

技术挑战只占30%,组织挑战占70%

政治因素

常见政治挑战:
├── "这是我建的系统"综合症
│   └── 旧系统维护者视改造为威胁
│   └── 对策: 让旧团队成员加入新团队,而非替换
│
├── "什么都不要动"恐惧
│   └── 管理层害怕改造风险
│   └── 对策: 渐进式改造+每步展示结果+快速回滚能力
│
├── "先做新功能"优先级之争
│   └── 业务永远觉得新功能比技术改造重要
│   └── 对策: 将改造与业务目标绑定("改造后新功能开发速度提升3x")
│
└── "这次肯定能一步到位"幻想
    └── 管理层期望一次性解决所有问题
    └── 对策: 明确改造是持续过程,展示分阶段路线图

预算挑战

改造预算的获取策略:

1. 量化当前成本:
   "现在每个新功能需要2个月,改造后只需要2周"
   "每年维护旧系统的人力成本是X万"
   "旧系统的故障每次损失Y万"

2. 渐进式投资:
   不是申请"3000万全面改造"
   而是"先投100万做PoC,证明可行后再分期投入"

3. 绑定业务目标:
   "改造不是为了技术,而是为了支撑明年的业务翻倍增长"
   "新系统支持的XX功能能带来Y%的收入增长"

4. 风险驱动:
   "旧系统最后一个懂的人明年退休"
   "监管要求明年必须具备X能力,旧系统做不到"

人才挑战

人才困境:
├── 懂旧系统的人不想学新技术
├── 会新技术的人不愿接触旧系统
└── 两者都懂的人极度稀缺

对策:
├── 组建"桥梁团队": 旧系统专家 + 新技术专家配对
├── 知识传承计划: 在改造过程中记录旧系统的业务规则
├── 激励机制: 参与改造的人有技术成长和认可
└── 外部专家: 必要时引入有改造经验的咨询团队

对比分析

改造策略全面对比

维度绞杀者模式Big Bang替换封装(Wrap)重构(Refactor)
风险低-中极高最低
时间长(月-年)中(如果成功)
成本中高
业务中断最小可能很大
技术债清理彻底彻底不清理部分
推荐度首选最后手段权宜之计特定场景

数据迁移策略对比

策略一致性复杂度停机需求适用数据量
停机迁移最强最低有停机小-中
双写弱(风险)
CDC最终一致中高
事件驱动最终一致
蓝绿数据库最高极短

架构设计实操:设计"核心银行系统"改造路线图

场景

某城商银行的核心系统运行了15年,基于IBM大型机+COBOL,日均处理100万笔交易。面临的问题:COBOL人才稀缺、新功能开发周期6个月、无法支撑移动端业务增长、运维成本每年递增20%。

阶段0:评估(2个月)

assessment:
  current_state:
    technology: "IBM z/OS, COBOL, DB2, CICS"
    codebase: "~200万行COBOL代码"
    modules:
      - name: "存款"
        business_value: 5
        change_frequency: 4
        coupling: "高"
        risk: 5
      - name: "贷款"
        business_value: 5
        change_frequency: 3
        coupling: "高"
        risk: 5
      - name: "客户信息"
        business_value: 4
        change_frequency: 4
        coupling: "中"
        risk: 3
      - name: "报表/查询"
        business_value: 3
        change_frequency: 2
        coupling: "低"
        risk: 1
      - name: "渠道接入"
        business_value: 4
        change_frequency: 5
        coupling: "中"
        risk: 2

  decision:
    报表_查询: "先迁移(低风险+低耦合)"
    渠道接入: "次迁移(业务收益大+耦合中等)"
    客户信息: "第三迁移(为后续核心模块铺路)"
    存贷核心: "最后迁移(风险最高,需要充分经验)"

阶段1:基础设施准备+报表迁移(6个月)

目标: 建立新技术基础设施 + 迁移低风险模块

┌──────────────────────────────────────────┐
│              路由层 (API Gateway)          │
│  ├── /api/reports/* → 新报表服务           │
│  └── /* → 旧核心系统                      │
└──────────────────────────────────────────┘

新建:
├── Kubernetes集群(阿里云ACK/AWS EKS)
├── 新数据库(OceanBase/PostgreSQL)
├── CDC管道(旧DB2 → Debezium → 新数据库)
├── 报表服务(Java/Spring Boot)
├── API Gateway(APISIX)
└── 监控体系(Prometheus+Grafana)

迁移:
├── 报表数据CDC同步(旧DB2 → 新库)
├── 报表查询功能重写
├── 新旧报表结果比对验证
└── 流量逐步切到新报表服务

成果:
├── 报表查询速度提升10x
├── 团队积累改造经验
├── 验证CDC+路由层方案可行
└── 管理层看到初步成果

阶段2:渠道层迁移+API化(6个月)

目标: 将旧系统的渠道接入层迁移到新平台

┌──────────────────────────────────────────┐
│              API Gateway                  │
│  ├── /api/reports/* → 新报表服务           │
│  ├── /api/mobile/* → 新渠道服务            │
│  ├── /api/online/* → 新渠道服务            │
│  └── /* → 旧核心系统                      │
└──────────────────────────────────────────┘

新建:
├── BFF层(为移动端/网银提供API)
├── 防腐层(ACL)(翻译旧系统数据模型)
└── 新的移动端/网银前端

关键设计:
├── 新渠道服务通过ACL调用旧核心系统
│   └── 新系统用现代API设计,ACL负责翻译为旧系统协议
├── 旧系统对外接口不变(不修改旧代码)
└── 新功能只在新渠道服务上开发

成果:
├── 新功能开发周期从6个月缩短到2周
├── 移动端体验显著提升
├── 为后续核心迁移建立ACL基础
└── 业务侧看到明显价值

阶段3:客户信息域迁移(6个月)

目标: 迁移客户信息管理,为核心域迁移铺路

数据迁移策略:
1. CDC同步: DB2客户表 → Debezium → OceanBase新客户表
2. 双读验证: 新旧库同时读取,比对结果(持续2周)
3. 切换写入: 新库成为主写入源
4. 反向同步: 新库 → 旧库(旧核心系统还需要读客户数据)
5. 最终清理: 旧核心系统改为从新客户服务读取

关键挑战:
├── 客户数据模型差异大(旧系统用编号,新系统用UUID)
├── 旧系统多处硬编码了客户表结构
└── 需要在旧系统代码中增加路由逻辑

阶段4:存贷核心迁移(12-18个月)

目标: 最终将存贷款核心迁移到新平台(最高风险阶段)

策略: 极致谨慎的金丝雀迁移
├── 先迁移"定期存款"(相对简单)
│   └── 新建定期存款微服务
│   └── 新客户→新服务,存量客户→旧系统
│   └── 验证3个月无问题
│
├── 再迁移"活期存款"(最核心)
│   └── 金丝雀: 1%客户→新系统
│   └── 验证1个月 → 扩大到10% → 50% → 100%
│
├── 最后迁移"贷款"
│   └── 同样的金丝雀策略
│
└── 旧系统退役
    └── 所有功能确认迁移完成
    └── 数据归档(保留7年+)
    └── 旧大型机退役

总时间线: 约30-36个月

AI增强

AI在遗留系统改造中的应用

  1. 代码理解

    • AI分析百万行COBOL代码,生成业务规则文档
    • 自动识别代码中的隐含业务逻辑
    • 生成旧系统的依赖关系图
  2. 代码翻译

    • COBOL → Java/Python的AI辅助翻译
    • 注意:AI翻译需要人工审查,不能盲信
    • 适合低复杂度模块的批量翻译
  3. 测试生成

    • AI根据旧系统行为生成测试用例
    • 自动发现旧系统的边界条件和异常处理
    • 生成新旧系统的对比测试
  4. 风险评估

    • AI分析代码变更影响范围
    • 预测迁移可能的风险点
    • 推荐迁移顺序

2025-2026年的新趋势

大型机COBOL系统改造正在借助AI加速——但完全自动化的翻译仍然不现实。AI最大的价值在于理解旧代码生成测试,而非直接替换人类的设计决策。


Web3关联

智能合约的"遗留问题"

区块链世界也有遗留系统问题:

  • 不可变性:智能合约部署后无法修改,"遗留合约"永远存在
  • 代理模式:通过Proxy合约实现"可升级",本质上就是"封装旧系统"
  • 迁移挑战:从V1合约迁移到V2,需要迁移所有状态数据和用户

Uniswap V2→V3的迁移就是一个典型的"绞杀者模式":V3逐步接管流动性,V2继续运行但不再开发新功能。


今日思考

遗留系统改造是一场"持久战"而非"闪电战"。Martin Fowler的绞杀者模式之所以成为行业标准,是因为它尊重了一个基本事实:你不能停下业务来做技术改造

最大的教训来自组织层面——技术方案可以设计得很完美,但如果没有管理层的支持、团队的参与、业务的理解,改造必然失败。

2025-2026年的新变化:AI正在降低理解和翻译旧代码的成本,CDC工具(Debezium等)让数据迁移更加安全,云原生平台让新系统的搭建更加快速。改造的门槛在降低,但核心挑战——组织和文化——仍然需要人来解决。


面试题

Q1: 如何推动遗留系统改造?

30秒回答:三步走——第一,量化痛点(运维成本X万/年、新功能周期6个月、人才流失风险);第二,渐进式方案(不是大爆炸替换,而是绞杀者模式分期改造);第三,快速展示价值(先迁移低风险模块,用结果说服管理层继续投资)。

2分钟详细回答

推动遗留系统改造需要同时解决技术和组织两方面的问题:

说服管理层

  • 量化当前成本:每年运维X万、新功能周期6个月、每次故障损失Y万
  • 量化风险:最后一个懂系统的人明年退休、监管要求无法满足
  • 提出渐进方案:先投100万做PoC,3个月出结果
  • 绑定业务目标:改造后支撑移动业务增长

技术策略

  • 绞杀者模式:新系统逐步接管旧系统功能
  • 从低风险模块开始:积累经验、建立信心
  • 防腐层隔离:新旧系统互不污染
  • CDC数据同步:避免停机迁移

关键成功因素

  • 让旧系统团队参与(而非被替换)
  • 每个阶段都有可度量的成果
  • 随时可以暂停(不是不可逆的决策)

Q2: 绞杀者模式的关键步骤?

30秒回答:四步——识别(选择低风险、低耦合的模块先迁移)→ 抽取(用新技术重写该模块为独立服务)→ 重定向(通过路由层将流量从旧系统切到新服务)→ 退役(确认无误后关闭旧系统对应模块)。

2分钟详细回答

  1. 识别:优先选择变更频率高+耦合度低+团队熟悉的模块。避免先动核心交易模块
  2. 抽取:用新技术栈重写,建立防腐层翻译新旧模型。新服务的API应面向未来设计,不要复制旧系统的设计
  3. 重定向:通过API Gateway/反向代理做路由。可以按路径、百分比、用户维度灰度切换。金丝雀策略逐步切量
  4. 退役:确认新服务稳定后,停止旧模块。数据归档保留。更新文档

关键经验:

  • 保守提取,从小处开始
  • 可观测性是关键——没有监控就不要切流量
  • 避免双写反模式,用CDC或事件驱动做数据同步
  • 整个过程可能需要数年,需要持续的组织承诺

学习资源


明日预告

明天我们将学习技术债管理(高级)——技术债是"今天的捷径,明天的利息",但不是所有技术债都该还。我们将学习Ward Cunningham四象限分类、SQALE量化方法论、以及如何把技术债翻译成管理层能理解的语言。