记一次服务器迁移

多算胜,少算不胜,而况于无算乎!—— 《孙子兵法》

下午 5 点接客户紧急通知其服务器所在机房将被查封,断电断网,需紧急配合客户进行数据迁移。

挑战

  • 需要迁移全部数据,总计约 60GB
  • 时间紧迫,只有 4 个小时(事后发现服务器并未真正断电断网)
  • 技术储备薄弱,缺少相应的预案
  • 客户服务器不是用的公有云方案,用的自建机房
  • 主机存储介质为机械硬盘,读写文件速度捉急
  • 客户主机出站带宽仅 100Mbps,且网络不稳定

迁移这个事情本身难度并不大,说穿了就是把数据备份出来,重新安装程序加载运行即可。但是加上了时间限定,就不那么好玩了。重压之下做决策和做动作都会变形。

迁移过程中踩的坑

  1. scp 传输大文件数据断流
  2. dns 改 IP 指向后缓存时间不定,原服务器需停机强制客户端刷新缓存,连接新服务器
  3. 客户数据盘挂在在 /home 下,/root 目录空间较小,备份过程中慌乱选错了目录,导致重新来过
  4. 发现时间不够时心态有段时间要崩,产生了慌乱感,几次操作出错

事后诸葛亮式的理论方案

  1. 服务器停机
  2. 将数据进行打包并切割成小块
  3. 分别将小块进行压缩
  4. 利用 scp 并行对每一个小块进行拷贝
  5. 合并、还原,同时恢复数据

小知识

nginx 不重启加载配置

nginx -t
nginx -s reload

文件切割

# 打包,切割分卷(不压缩)
tar cf - $filename | split -d -b 100m - logs.tar.gz.
# - 为管道连接符

# 解压,打包分卷
cat logs.tar.gz* | tar xf

ssh 保活

编辑 vi /root/.ssh/config 增加一句 ServerAliveInterval 10。(示例为每 10 秒保活一次,按需更改)

zstd

zstd 不单一追求一项技术指标的文件压缩设计理念,使得其及其适合应对这种需要多快好省的情况。虽然所有点都达到最优是不可能的,但在压缩比率选取合理的情况下可以达到网络传输与压缩时间平衡点。

// 压缩
zstd -12 $filename

// 解压
zstd -d filename

tsunami-udp

过程中咨询了一个朋友关于网络不稳定状态下的高效数据传输方案,他推荐了 tsunami-udp。使用下来,带宽利用率提升非常明显,实测 scp 和 tsunami-udp 同时打开,带宽基本都被 tsunami-udp 吃掉了,scp 完败。
但是。。。
客户网络防火墙没能搞定,最后也没用成这个方案。很可惜。

使用默认端口通信

tsunami-udp 默认端口是 46224

服务端:

tsunamid *

客户端:

tsunami

客户端单条指令下载文件

tsunami connect demo.tsunami-udp.cmcm set udpport 51031 get mnt/d2/file4download quit

理解:

  1. tsunami
  2. connect demo.tsunami-udp.cmcm
  3. set udpport 51031
  4. get mnt/d2/file4download
    其他指令:
  5. set rate 100M (设置速率)

tsunami-udp 的技术实现

tsunami-udp 使用TCP进行传输控制、UDP进行数据传输。 服务端和客户端需要同时开启防火墙的 TCP/UDP 支持,默认端口 46224。

rsync 备份

rsync -P --rsh=ssh home.tar 192.168.205.34:/home/home.tar

总结

对于大文件打包进行文件传输的场景,传统的 打包 -> 压缩 -> 切割 的方法不适用,因为打包和压缩的时间耗时很长。理想的流程应该是 打包 -> 切割 -> 压缩 这样的工作流。这样可以第一个压缩分卷可以很快出来。
也更进一步理解 sync 在设备热插拔场景下的特殊意义,Linux 系统缓存机制其实极大的提升了数据访问的效率,大多数场景下其实用户不必关心数据到底有没有落盘,但是对于支持热插拔的设备来说,这种设计是灾难性的,用户的耐心在指令结束时可能已经耗得差不多了,这时热插拔必定导致悲剧,而系统的 eject 设计大多比较保守,在多数情况下都会提示设备占用,用户根本分不清楚哪些是真占用(危险)哪些是假占用(安全)。支持热插拔的设备,最理想的设计其实应该是特殊处理关闭缓存,让每一次操作都变成原子式的。