结论:大型 CMS 迁移的对外停机时间可以压到 5 分钟以内。办法是先把数据搬运和流量切换彻底分开,让停机只发生在“最后一次增量追平并改指向”的瞬间,而不是提升拷贝速度。
停机时间到底消耗在哪里?
结论:迁移过程中浪费的时间,多数是切换后才暴露的“数据没追平、附件没同步、缓存没预热”导致的二次返工,并非花在拷文件上。
一个内容量在几十 GB 级的 CMS,全量打包、传输、解压本身就要几小时,但这段时间站点仍在对外服务,不产生停机。真正消耗停机时间的是:新站起来后发现数据库少了几百条评论、附件目录差几百 MB、伪静态规则没带过来、缓存全空导致首页首屏慢。所以迁移方案要设计成“重活全部提前做,切换只做一次改指向”。
迁移前 48 小时必须做完哪三件事?
结论:把 DNS TTL 降到 300 秒、搭好带增量同步的从库、把附件用 rsync 预热到位,这三件事做完,切换才可能以分钟计。
- 降 TTL:提前 48 小时把域名 A 记录 TTL 从 3600 或 86400 调到 300 秒。这一步不做,切完之后回滚要等几小时,整个迁移就没有退路。
- 起从库:用
mysqldump --single-transaction --master-data=2 做全量导出(InnoDB 下不锁表),导出文件头里会记录 binlog position,用它在新库上 CHANGE MASTER TO 追增量。
- 同步附件:CMS 的附件目录往往是体积最大的一块,按本站规则单附件上限 10MB、图片 5MB,一个运营三年的站有几万附件很正常。用
rsync -a --delete 反复跑,第一遍传全量,之后每遍只传增量,切流前再跑最后一遍,通常几十秒完成。
数据库如何做到切换瞬间不丢数据?
结论:靠“全量 + binlog 增量”把延迟追到 0 秒,再短暂锁写,而不是靠停机锁表导出。
操作顺序是:全量导入完成后启动从库复制,观察 SHOW SLAVE STATUS 里的 Seconds_Behind_Master,正常应稳定在 0~3 秒。切换时先把 CMS 后台切到维护模式,或把数据库置为只读(SET GLOBAL read_only=ON),等 Seconds_Behind_Master 归零、SHOW MASTER STATUS 与 SHOW SLAVE STATUS 的位点一致,再执行提升为主库。这一步的锁写窗口通常只有 30~120 秒,前台用户看到的是维护提示页,而不是报错。
切流按什么顺序执行?
结论:顺序必须是“先锁写、再追平、再改配置、最后改指向”,任何一步颠倒都会造成数据回灌或用户看到错版本。
- 开启维护页,前台只读;
- 追平 binlog,确认位点一致;
- 修改新库的
siteurl、home 两个配置项(WordPress 类是 wp_options 表里的两条记录),重建缓存;
- 有反向代理的,把 upstream 权重从 0 切到 100,这一步是秒级;没有代理的,改 DNS 的 A 记录;
- 关闭维护页,观察 15 分钟错误日志和慢查询。
改配置这一步最容易被忽略:域名写死在数据库里的 CMS,切流后所有内链会跳回旧域名,用户点两下就跳出。
出问题怎么在 5 分钟内回滚?
结论:回滚能力来自三样东西——旧机保留 72 小时且可随时恢复写入、TTL 已经降到 300 秒、新机上的增量数据有导出脚本。
回滚时把旧机的只读状态解除,DNS 改回原 IP,5 分钟内全网生效。如果新机上已经产生了新数据,用 mysqldump 按时间范围导出这几小时的增量表,回灌到旧库,避免用户发现自己的帖子“消失”。旧机不要急着关,至少留 3 天,磁盘成本远低于一次数据事故。
迁移完成后要核验哪些项?
结论:迁移后的验收要看数据一致性、抓取链路、缓存命中三组指标,不能只看首页能不能打开。
- 数据:比对源库和目标库的表数量、
COUNT(*) 行数,抽查 10 张大表的 CHECKSUM TABLE;
- 文件:
du -s 对比附件目录,数量差异应为 0;
- 抓取:检查 sitemap、RSS 订阅地址、robots.txt 是否仍可访问,旧域名做 301 全站跳转;
- 缓存:预热首页、列表页、热门详情页,避免切流后第一批用户全部穿透到数据库;
- 留档:把这次迁移的时间点、配置变更、故障修复写进站点的更新日志,运营团队下次换机可以直接照单执行——像 GJ 站长论坛把功能迭代、规则调整、配置变更和线上故障修复统一记进「站点更新日志」的做法,迁移这种大动作更该留一份可回溯的记录。
一句话收尾:把停机当成“一次改指向的动作”而不是“一次搬运工程”,迁移的风险就落在可回滚的分钟级窗口里,而不是几小时的黑箱。