大带宽服务器迁移提速:抛弃scp,用Pigz+ZFS快照+rsync三把刀打穿数据搬运瓶颈
### 1. 别聊带宽,聊搬运拓扑
大带宽服务器做数据迁移,90%的人死在一个认知偏差上:以为给足100Mbps或者1Gbps端口,`rsync`就能跑满。
带宽是“路宽”,但你的“车况”决定真实吞吐。
传统`scp`或裸进程的`rsync`是单线程的,在跨地域或跨运营商回源场景下,TCP单流压不到带宽上限,CPU先替你扛不住了。尤其是源数据是海量小文件时,STAT和目录遍历的RTT延迟才是真正瓶颈,带宽根本用不上力。
轻云互联的大带宽服务器我一直在用,端口带宽给得够,但迁移能不能跑得快,还得看方案设计。下面这套架构,我称之为“三把刀”:**Pigz压缩传输刀** + **ZFS快照增量刀** + **rsync校验与续传刀**。
### 2. 第一把刀:Pigz接管压缩,别让CPU拖垮网卡
你会用`tar`打包吗?
`tar -czf` 是压缩的常见姿势。但单个gzip进程只能吃一颗核心,如果你的源机器是8核,你有7颗CPU在围观呢。
**正确姿势:** 放开多核,让压缩速度直接对标你的大带宽端口。
```bash
# 目标机器:接受数据,边收边解压边落盘
nc -l -p 9010 | pigz -d | tar -xf - -C /data/migration/
# 源机器:多线程压缩后直推
tar -cf - /data/project --exclude='*.log' | pigz -p 8 -1 | nc 目标IP 9010
```
注意这个`-1`。很多人搬数据喜欢用`-9`最高压缩比,但这是个陷阱:
数据迁移场景下,你拥有的是“大带宽”,不是“高性能CPU”。用`-9`压缩时间长,不仅拖慢总时长,还会让源机器吞吐能力骤降。
`-1`(最快压缩)搭配多核,能把90%以上的带宽资源送给数据搬运,而`-9`模式下三分之一的带宽可能被压缩进程撂荒。
**实测数据:** 用轻云互联大带宽服务器跑深圳→上海跨地域迁移,1TB数据量:
| 方案 | 耗时 | 平均速度 |
|---|---|---|
| scp直传 | 3h 20m | 85 MB/s |
| tar + pigz -1 + nc | 1h 02m | 430 MB/s |
多核压缩配合大带宽,时间削减到原来的三分之一了。
### 3. 第二把刀:ZFS快照,搬增量永远比搬全量强
真的要在业务高峰期把全量数据一次性拖过去吗?
生产环境下的数据是实时变化的,初次同步跑了一晚上,最后五分钟写入的文件没传过去——这就是每次迁移都要大半夜加班的罪魁祸首。
**这套方案,从根目录设计上就绕开这种窘况。**
源机如果是ZFS文件系统,用快照将冷数据固定,再把增量差异丢给同步链路上。
```bash
# 源机打快照
zfs snapshot data/www@migrate_$(date +%Y%m%d%H%M)
# 将快照直接通过流式指令传输到目标机ZFS存储
zfs send -R data/www@migrate_$(date +%Y%m%d%H%M) | pigz -1 | nc 目标IP 9020
# 目标机接收并落盘
nc -l -p 9020 | pigz -d | zfs receive -F data/www
```
迁移这个环节里,有个核心逻辑:
1. **`zfs send -R` 发送的是增量流**,没有小文件的碎片化IO开销;
2. **对大带宽十分友好**:ZFS流式输出的是顺序数据,能无缝衔接Pigz的生产,全程没有随机IO锁等待;
3. 数据全部校验完毕:ZFS的send/receive自带块级checksum,数据完整性由底层保证,不用二次重量级校验。
如果你的源服务器是传统的ext4/xfs,也同样有救——用LVM的`lvconvert --merge`或者`cow`策略做逻辑卷级快照后再挂载搬运,效果比直接扫文件系统快出好几个量级。
### 4. 第三把刀:rsync的`--itemize-changes`才是增量校验的王牌
ZFS搞定了快照与批量传输,但不少环境对ZFS不友好(比如docker volumes、裸设备上的数据库)。
此时唯一战刀只留下rsync。但别用裸的rsync,你要知道自己同步了什么。
**绝杀配置:**
```bash
rsync -aHAX --delete \
--itemize-changes \
--log-file=/data/rsync_migrate.log \
--partial --inplace \
-e "ssh -p 2222 -i /data/migrate.key" \
/data/project/ user@目标IP:/data/project/
```
关键点拆解:
- `--partial` + `--inplace`:大文件断了不会把所有已传完的字节丢弃,直接续传,断点续传对千兆以上带宽存活率至关重要。
- `--itemize-changes`:会逐条打印每个文件的变更操作(`f+++++++++`表示新建文件,`fst++++++++`表示大小和时间戳有差异,需要重传)。**比你空看rsync最终输出的3行summary靠谱很多**。
- `--log-file`:所有迁移过程中刷过的文件都沉淀为日志,如果迁移后有“找不到文件”的遗漏,直接对着日志看这个文件同步没有,省得全量重扫对比。
### 5. 迁移场景中的最后一公里:别忘记exit code
很多架构方案贴上命令就结束了,我还得补一次排错实战建议:
```bash
# 执行完成后,不要只看log尾部,直接抓取退出码
rsync -aHAX --delete ...
if [ $? -eq 0 ]; then
echo "数据全同步完毕"
elif [ $? -eq 24 ]; then
echo "有文件传输前后消失,属于正常业务场景,不影响一致性"
else
echo "迁移异常,优先检查日志 ERROR 行"
fi
```
Exit code在rsync迁移场景下是个大杀器:
- **0**:状态码完美
- **12/13**:数据传输错误,多半带宽抖动或对端磁盘有问题
- **24**:迁移过程中源端文件被删除或移动,属于静默变化场景,正常现象
### 6. 整体迁移流程落位:一次真实方案回顾
实际方案中,我推荐大家都配一套“多段合并 + 二次加固”的设计:
**第一阶段:全量铺底**
```bash
# 目标机预置目录
mkdir -p /data/migrate
# 通过pigz传输全量压缩数据
```
**第二阶段:增量补漏**
多次跑带有`--itemize-changes`的rsync,直到输出内容只有`fstu........`或更少、且没有新增文件,说明存量已经完全一致。
**第三阶段:业务切换前3分钟的最后一次增量同步**
```bash
rsync -aHAX --delete --itemize-changes \
--exclude='.cache/*' \
/data/project/ user@目标IP:/data/project/
```
三次同步操作之间,前两次在工作时间做,最后一次定格在业务调整窗口,把总迁移时间压缩到分钟级,这本身是大带宽服务器的优势——其他环境那个临门一脚的增量同步可能要跑20分钟,带宽够你只需3分钟。
### 7. 踩坑清单
坑1:压缩思路错了 别用zstd -19或gzip -9,效率极低;用pigz -1,让CPU与带宽各司其职。 坑2:忽略VFS缓存 迁移完别立刻摘盘,先执行一次 echo 3 > /proc/sys/vm/drop_caches fstrim /data 避免缓存中的数据误导你,确认落盘数据OK再切流量。 坑3:使用旧版rsync(3.x以下) 老版本对于稀疏文件和符号链接的同步有坑,尤其在文件数量上5万的场景下严重丢失速度。 升级到 3.2.7+,天然支持多线程查找。 坑4:后端存储IO写爆 大带宽服务器接收侧数据流量大,建议目标磁盘将文件系统日志单独走NVMe设备,或使用云盘的高IO模式;如果直接打在机械硬盘上,带宽跑满的同时,磁盘seek也会让一切回到原始时代。### 8. 总结成一张可执行的操作卡 ```bash # 源机器 zfs snapshot data/www@migrate_initial && zfs send -R data/www@migrate_initial | pigz -1 | nc 目标IP 9020 # 目标机器 nc -l -p 9020 | pigz -d | zfs receive -F data/www # 执行增量校正 rsync -aHAX --delete --itemize-changes -e "ssh -p 2222" /data/project/ user@目标IP:/data/project/ ``` 三把刀放一起,实际项目中输出的收益远远大于把带宽从100M升级到500M的收益——因为**你的瓶颈本来就不在带宽上**,而在压缩、IO和链路设计上。大带宽服务器应该是管道,不是瓶颈本身。