服务器迁移:换机房不中断服务的完整流程
换服务器最怕的不是搬,是「搬完发现有问题,但已经切换回不去了」。把流程拆成可回滚的步骤,就能做到用户几乎无感。
一、总体顺序
1. 新机开出来,做基础加固
2. 装依赖、配服务(Nginx / 数据库 / 应用)
3. 同步数据与文件
4. 【关键】提前把 DNS TTL 调低到 300 秒
5. 【关键】用 hosts 文件预验证新机
6. 切换 DNS 解析
7. 观察 24~48 小时,旧机保留不动
8. 确认无误后再下线旧机核心思想:先让新机在「看不见」的状态下跑通,再切换流量;切换后旧机继续待命。
二、第一步:降低 TTL(提前一天做)
这是最容易被忘、也最容易导致长时间不可用的步骤。
DNS 记录有 TTL(缓存有效期)。如果你原来设的是 3600 秒(1 小时),那么切换解析后,最多要 1 小时所有用户才会看到新 IP——期间他们访问的还是马上要下线的旧机。
在切换前至少 24 小时,把 TTL 改成 300 秒(或 60),这样切换后 5 分钟内全网生效。
# 确认当前 TTL
dig example.com A | grep -A1 "ANSWER SECTION"
# 去 DNS 控制台改成 300(Cloudflare 的自动 TTL 是 300,省钱省心)三、新机准备
按本站「服务器初始化」那篇做一遍,然后装同样的软件栈。
# 记录旧机的软件版本,保证一致(尤其是数据库大版本)
nginx -v
mysql --version
node -v
python3 --version
# 在新机装相同版本
sudo apt install -y nginx mysql-server数据库大版本一定要一致。MySQL 5.7 的 dump 导进 8.0 可能报错,PostgreSQL 跨大版本更要谨慎。
四、配置文件迁移
最省事的办法:直接把旧机的配置目录打包拷过去。
# 旧机上打包
sudo tar czf /tmp/conf.tar.gz /etc/nginx /etc/ssh/sshd_config /etc/letsencrypt
# 拷到新机(在新机执行,或旧机 scp 过去)
rsync -avz -e "ssh -p 2222" olduser@OLD_IP:/tmp/conf.tar.gz /tmp/
# 新机解压(先备份自己的默认配置)
sudo cp -r /etc/nginx /etc/nginx.default
sudo tar xzf /tmp/conf.tar.gz -C /
sudo nginx -t注意 /etc/letsencrypt 拷过去后要确认路径和权限:
sudo chmod 600 /etc/letsencrypt/live/*/privkey.pem
sudo nginx -t也可以在新机重新签一份证书(certbot 更容易,推荐)。
五、数据迁移
文件
# rsync 直接同步,保留权限
rsync -avz --delete -e "ssh -p 2222" \
olduser@OLD_IP:/var/www/baize/ /var/www/baize/
sudo chown -R www-data:www-data /var/www/baize数据库
# 旧机导出
mysqldump -u root -p --single-transaction --routines --triggers baize_db \
| gzip > /tmp/db.sql.gz
# 传到新机并导入
rsync -avz -e "ssh -p 2222" /tmp/db.sql.gz newuser@NEW_IP:/tmp/
gunzip < /tmp/db.sql.gz | mysql -u root -p baize_db
# 核对条数(必做)
mysql -u root -p -e "SELECT COUNT(*) FROM baize_db.posts;"数据量大或者要求不停机的话,用主从复制:新机作为从库追上主库,切换时提升为主库。个人站点一般用不上。
六、【关键】用 hosts 预验证
切换 DNS 之前,先让你自己的电脑「以为」域名已经指向新机,完整跑一遍。
# 本地修改 hosts(macOS / Linux)
sudo vim /etc/hosts
# 加一行:新IP 域名
NEW_IP www.bzii.cn
NEW_IP www.bzii.cn
# 清 DNS 缓存
sudo dscacheutil -flushcache && sudo killall -HUP mDNSResponder # macOS
sudo resolvectl flush-caches # Linux
ipconfig /flushdns # Windows然后像真实用户一样完整访问一遍:
- 首页能打开,样式正常(不是 404 / 默认页)
- HTTPS 证书有效(这是最容易出问题的地方)
- 各页面链接可达,文章能打开
- 数据库读写正常(能登录、能提交)
- 上传/写入目录权限正确
- 定时任务在新机已配好
# 验证证书(hosts 生效后)
curl -sI https://www.bzii.cn | head -1
echo | openssl s_client -connect www.bzii.cn:443 -servername www.bzii.cn 2>/dev/null \
| openssl x509 -noout -dates -subject这一步能挡掉 90% 的迁移事故。不要跳过。
验证完记得把 hosts 改回来。
七、切换 DNS
确认无误后,把 A 记录改成新 IP。
# 切换后持续观察,看全球生效情况
watch -n 10 "dig +short A www.bzii.cn"
# 或用 DNS Checker 看全球因为有 TTL=300,5 分钟内大部分用户会到新机。接下来 24 小时内:
# 看新机访问日志有没有流量进来
sudo tail -f /var/log/nginx/access.log
# 看错误日志
sudo tail -f /var/log/nginx/error.log八、回滚方案
旧机在确认期内绝对不要关。 一旦新机出问题:
- 把 DNS A 记录改回旧机 IP;
- 因为 TTL 是 300,5 分钟内用户回流;
- 慢慢排查新机问题。
这就是为什么「提前降 TTL」这么重要——它同时决定了切换速度和回滚速度。
九、收尾
确认 48 小时无异常后:
- 旧机打一份最终快照,再保留 7 天;
- 把 TTL 改回正常值(1800 或 3600);
- 更新备份脚本里的目标地址;
- 更新监控/告警里的机器信息;
- 更新
~/.ssh/config里的 IP; - 最后再退订旧机(别急着退,快照留着)。
十、checklist 汇总
准备阶段
- [ ] 记录旧机软件版本
- [ ] 新机基础加固
- [ ] 装依赖并核对版本
- [ ] TTL 降到 300(提前 24h)
- [ ] 迁移配置文件
- [ ] 同步文件与数据库
- [ ] 核对数据条数
验证阶段
- [ ] 改 hosts 指向新机
- [ ] 完整走查所有功能
- [ ] 证书有效
- [ ] 定时任务已迁移
- [ ] 恢复 hosts
切换阶段
- [ ] 改 A 记录
- [ ] 观察访问/错误日志
- [ ] 旧机保持在线待命
- [ ] 48h 后打快照、改回 TTL、下线旧机迁移本身不难,难的是每一步都可回滚。按这个顺序走,换机房就是改一行 DNS 的事。
