服务器迁移的中场:MySQL 主从复制 + Redis REPLICAOF 持续同步方案
背景:某交易系统需要从老集群(日本某云厂商)迁移到新集群(某公有云)。MRD 评审已通过,进入详设阶段。
迁移最难的不是搬家,是搬家期间数据还在变。本文复盘 W0.5 数据持续同步的详细设计。
为什么需要持续同步
一次性导出导入(mysqldump → scp → source)有两个致命问题:
- 导入耗时:几 GB 数据导入可能需要数十分钟,这期间老集群还在写入
- 切换窗口长:停服 → 导数据 → 导入 → 启动,服务中断时间不可控
正确做法:先建立持续同步通道,让新集群跟跑一段时间,确认数据一致后再切换流量。 这就是 W0.5 的价值——它不是在搬数据,是在搭一条传输带。
这跟广告系统的索引分发一模一样:全量索引构建完成后,增量索引通过 binlog 持续同步到检索节点,检索节点永远有一个”跟得上的副本”。切换时直接读副本,不需要停服重建。
架构
老集群 (日本) ──autossh隧道──► 新集群 (公有云)
:13306 ──────────────────► :3306 MySQL (binlog ROW 复制)
:16379 ──────────────────► :6379 Redis (REPLICAOF)
三个组件:
| 组件 | 作用 | 为什么选它 |
|---|---|---|
| autossh | SSH 隧道保活 | 断线自动重连,比 ssh -R 裸跑可靠 |
| MySQL binlog ROW 复制 | 数据库增量同步 | ROW 格式比 STATEMENT 精确,不会因函数导致不一致 |
| Redis REPLICAOF | 缓存增量同步 | Redis 自带的主从协议,简单够用 |
三步实施
1. SSH 隧道
# 老集群上
autossh -M 0 -N -R 13306:localhost:3306 -R 16379:localhost:6379 user@新集群
搭配 systemd 保活:进程挂了自动拉起,机器重启后自动建立隧道。
隧道是整个方案的地基——没有隧道,后面两步都跑不起来。所以验收第一项就是:kill -9 autossh 后 30 秒内自动恢复。
2. MySQL 主从复制
关键决策:只同步业务库,不同步系统库。
-- 老集群 my.cnf
binlog-do-db=business_db_1
binlog-do-db=business_db_2
为什么不全库同步?mysql、information_schema、performance_schema 这些系统库在新集群上应该独立存在,同步它们会覆盖新集群的用户权限和系统配置。
另一个关键决策:slave read-only=1 对 root 用户无效。 这意味着迁移后的服务仍然可以直接写老集群——哨兵模式。新集群慢慢切流量,老集群始终可读写,切换过程不需要”停服”。
3. Redis REPLICAOF
比 MySQL 简单得多。新集群 Redis 直连隧道端口 16379,一条命令:
redis-cli -p 16379 REPLICAOF 127.0.0.1 6379
不需要像 MySQL 那样配 binlog 格式、server-id、复制用户。Redis 的主从就是一条命令的事。
切换与回滚
切换策略:
- 保持 slave 运行,直到全部服务迁移完成
- 最后一步:
STOP SLAVE+REPLICAOF NO ONE——新集群正式独立 - 期间新集群的服务仍然写老集群(read_only=1 对 root 无效),所以切换窗口为零
回滚策略:
回滚零成本。因为老集群的 MySQL 和 Redis 从未停止写入,新集群只是跟着读。如果出问题,DNS 切回老集群即可——数据一直在那里。
这是这个方案最优雅的地方:主从同步的方向决定了回滚的代价。如果新集群是 master、老集群是 slave,回滚需要反向同步。但老集群一直是 master,回滚就是一次 DNS 切换。
验收标准
| # | 验收项 | 标准 |
|---|---|---|
| 1 | 隧道连通 | telnet 端口通 |
| 2 | 复制运行 | SHOW SLAVE STATUS 正常 |
| 3 | 数据一致 | 延迟 < 1s |
| 4 | 断线恢复 | kill autossh 后 30s 内恢复 |
| 5 | 重启恢复 | 重启任一端后自动恢复 |
| 6 | 24h 稳定 | 跑 24 小时无中断 |
元结构映射:广告索引的主从同步
做索引系统出身的同学看这个方案应该很熟悉:
| 概念 | 广告索引系统 | 本次迁移 |
|---|---|---|
| 全量同步 | 全量索引构建 | mysqldump 初始化 |
| 增量同步 | binlog 订阅 → 索引增量 | MySQL binlog ROW 复制 |
| 分发通道 | 消息队列 / RPC | SSH 隧道 |
| 切换策略 | 检索节点切读新索引 | DNS 切新集群 |
| 回滚 | 检索节点切回旧索引 | DNS 切回老集群 |
| 数据一致性校验 | checksum 对比 | pt-table-checksum |
本质上都是:主节点持续写入 → 传输通道分发 → 从节点保持热备 → 切换时秒级生效。
教训
三条:
1. 迁移项目最危险的是”最后一切”之前的准备阶段。 数据导完了但服务还在老集群写——这段时间越长,数据不一致的风险越大。W0.5 的持续同步就是把这个风险压到零。
2. 方向决定成本。 老集群做 master、新集群做 slave 是最优选择——因为回滚零成本。反过来就需要双向同步,复杂度指数级上升。
3. 验收标准要量化。 ”< 1s 延迟""30s 内恢复""24h 稳定”——没有数字的验收等于没有验收。这跟广告系统的 SLA 一样:CTR 下降 > 5% 才报警,不是”下降了就报警”。
一句话:迁移的本质不是搬运数据,而是在搬运过程中保持两个集群的数据一致——主从复制 + 隧道转发,简单、可靠、可回滚。