数据迁移、扩缩容方案

数据迁移、扩缩容方案

为什么数据迁移如此棘手

分库分表后,数据迁移是一个绕不开的问题。当数据量增长超过预期、分片策略需要调整、或者硬件需要升级时,都需要对已有数据进行迁移。

主要挑战在于:
数据量大:可能已经积累了数十 TB 的数据
服务不能停:业务需要 7×24 运行
一致性要求高:不能丢失或重复数据

常见的扩缩容场景

场景 原因 动作
分片扩容 数据量超过预期 从 64 个分片 → 128 个分片
分片缩容 业务下线或合并 减少分片数
分片键变更 原分片键不合理 切换为新分片键
数据库迁移 硬件升级、机房搬迁 从旧集群迁移到新集群
版本升级 MySQL 大版本升级 数据导出导入

设计方案一:停服迁移

步骤

  1. 发布停服公告,停止所有写操作
  2. 导出旧表数据
  3. 导入新表并建立索引
  4. 验证数据一致性
  5. 切换 DNS/配置到新数据源
  6. 恢复服务

优点

  • 实现简单,不需要复杂的同步逻辑
  • 数据一致性好,迁移期间没有变更

缺点

  • 服务不可用时间较长(数小时甚至数天)
  • 对于 7×24 业务不可接受

设计方案二:双写迁移

步骤

阶段一:双写 + 全量同步
1. 新、旧两套分片集群同时启动
2. 应用代码修改:写入操作同时写入旧集群和新集群
3. 开启历史数据全量同步(从旧集群批量导入新集群)
4. 持续校验数据一致性

阶段二:增量追平
1. 全量完成后,新旧数据差异只有双写阶段的增量
2. 通过对比差异表或 binlog 同步补全
3. 确认新旧集群数据完全一致

阶段三:切换
1. 将读流量逐步切到新集群(灰度切量)
2. 观察监控:延迟、错误、慢查询
3. 确认无误后关闭双写旧集群
4. 下线旧集群

优点

  • 零停机,业务无感知
  • 支持灰度验证,风险可控

缺点

  • 实现复杂,代码需要支持双写
  • 双写期间写入性能下降(每次写操作翻倍)
  • 需要额外的数据校验工具

设计方案三:binlog 同步迁移

步骤

  1. 搭建新集群
  2. 使用 Canal / Maxwell 订阅旧集群的 binlog
  3. binlog 实时同步到新集群(本质是 MySQL 复制)
  4. 历史数据通过 select 批量导入
  5. 全量同步完成后,binlog 会追平增量
  6. 追齐后切换读写流量

示意图

旧集群(源) ←写入← 应用
   │
   ├── 全量同步(SELECT INTO + INSERT)
   │   ↓
新集群(目标) ←接收← Canal binlog 增量
   │
   └── 校验一致后,应用切换到新集群

优点

  • 代码零侵入(不需要改应用代码)
  • 支持实时同步,延迟可控在秒级

缺点

  • 需要部署 Canal 等同步组件
  • 需要额外处理 DDL 变更的同步
  • binlog 格式必须是 ROW 模式

哈希分片扩容的特殊问题

范围分片扩容简单——新加的分片分配新的 ID 范围即可,旧分片完全不动。

哈希分片扩容则棘手得多。假设从 64 个分片扩容到 128 个分片:

旧规则:shard = id % 64
新规则:shard = id % 128

原来分在 0 号分片的记录,新规则下可能分到 0 或 64 号分片,需要重新计算并迁移。

解决方案

  1. 一致性哈希:减少迁移量
  2. 虚拟分片法:提前分成 1024 个虚拟分片,物理上映射到 64 个库;扩容时调整映射关系,只迁移部分虚拟分片
  3. 先按余数分片再二级映射:分片编号不变,底层迁移部分数据

数据一致性校验

无论哪种方案,迁移后都需要校验数据一致性。

校验工具
全量校验CHECKSUM TABLE 对比
抽样校验:按 mod 取一定比例的数据对比
差量校验:对比新旧集群的最后修改时间

最佳实践建议

  1. 尽可能避免迁移:一开始就预留足够的分片数(如 128 或 256),而非频繁扩容
  2. 先按 2 的幂次分片:后续扩容时可以从 128 → 256,迁移邻居表相对可控
  3. 灰度切换:不要一刀切,先切 1% 流量验证,逐步放大到 100%
  4. 回滚预案:切换前保留旧集群,一旦发现问题随时切回
  5. 观察期:切换后至少观察一天再下线旧集群

总结

数据迁移的核心挑战在于不停机数据一致性。双写迁移和 binlog 同步是最常用的不停机方案,各有优缺点。与其追求完美的迁移方案,不如在一开始就做好分片数量的规划和预估,尽量减少迁移次数。

© 版权声明
THE END
喜欢就支持一下吧
点赞15 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容