服务器磁盘减配实战:从200GB到50GB + 文件存储,零数据丢失迁移指南
一、背景与需求
最近遇到一个典型的服务器资源优化场景:一台应用服务器挂载了200GB的系统盘,其中附件数据占了大部分空间,而实际业务核心程序占用不足50GB。为了降本增效,需要:
- 磁盘减配 :将200GB磁盘替换为50GB磁盘
- 附件分离 :将附件数据迁移到外部文件存储(NAS/云文件存储)
- 路径不变 :业务访问路径必须保持
/data不变,应用零改造
本文记录了一次零数据丢失、可秒级回滚的完整迁移过程。
二、方案设计
2.1 架构对比
迁移前:
text
/data → 200GB本地磁盘(程序 + 附件混在一起)
迁移后:
text
/data → 50GB本地磁盘(仅程序、配置文件)
/data/attachments → 文件存储(NAS/云存储,存放附件)
2.2 核心策略
采用 “先同步、后切换” 的策略,整个过程分为四个阶段:
- 数据同步 :在业务正常运行期间,将数据同步到目标存储
- 停机切换 :停止服务,完成最后一次增量同步,切换挂载点
- 验证持久化 :启动服务验证,配置开机自动挂载
- 观察回收 :稳定运行后回收旧磁盘
2.3 关键技术点
rsync:增量同步,支持断点续传,保留权限属性mount --bind(备选):或直接切换挂载点/etc/fstab:开机自动挂载配置- 紧急回滚预案:旧盘数据不动,可秒级恢复
三、环境准备
3.1 变量确认
开始前,请先确认以下信息:
| 项目 | 示例值 | 确认命令 |
|---|---|---|
| 旧磁盘设备 | /dev/vda1 | df -h /data |
| 新磁盘设备 | /dev/vdb1 | lsblk |
| 文件存储地址 | 192.168.1.100:/nas_share | 根据实际填写 |
| 附件目录 | /data/attachments | ls -la /data |
3.2 前置检查
bash
# 1. 确认当前磁盘使用情况
df -h /data
# 2. 确认新增磁盘已识别
lsblk
# 3. 确认文件存储网络可达
ping 192.168.1.100
四、详细操作步骤
第一阶段:创建临时挂载点并挂载
bash
# 1. 创建临时挂载点
sudo mkdir -p /mnt/new_disk
sudo mkdir -p /mnt/nas
# 2. 挂载新磁盘(50GB)
sudo mount /dev/vdb1 /mnt/new_disk
# 3. 挂载文件存储(NAS/云存储)
sudo mount -t nfs 192.168.1.100:/nas_share /mnt/nas
# 4. 验证挂载结果
df -h | grep -E "/mnt/new_disk|/mnt/nas"
注意 :此阶段对线上业务 零影响 ,可在业务高峰期外执行。
第二阶段:数据同步(业务正常运行)
2.1 同步非附件数据到新盘
bash
sudo rsync -av --numeric-ids --progress --exclude='/attachments' /data/ /mnt/new_disk/
参数说明:
-a:归档模式,保留权限、时间戳等所有属性-v:显示详细过程--numeric-ids:保留UID/GID数字值(跨设备迁移必备)--progress:显示传输进度--exclude='/attachments':排除顶层附件目录
2.2 同步附件数据到文件存储
bash
sudo rsync -av --numeric-ids --progress /data/attachments/ /mnt/nas/
提示 :如果数据量很大,以上两条命令可以 多次执行 ,
rsync会自动增量同步,只传输变更的文件,大幅缩短最终停机时间。
第三阶段:停机切换(核心操作)
3.1 停止业务服务
bash
# 示例:停止 Nginx 和 PHP-FPM(请替换为你的实际服务名)
sudo systemctl stop nginx php-fpm
# 或使用更激进的方式(确保没有进程写入)
sudo systemctl stop $(systemctl list-units --type=service --state=running | grep -E "nginx|php|tomcat" | awk '{print $1}')
3.2 最后一次增量同步
bash
sudo rsync -av --numeric-ids --progress --exclude='/attachments' /data/ /mnt/new_disk/
sudo rsync -av --numeric-ids --progress /data/attachments/ /mnt/nas/
3.3 释放临时挂载点
bash
cd / # 务必退出 /data 目录,否则无法卸载
sudo umount /mnt/nas
sudo umount /mnt/new_disk
3.4 切换正式挂载点
bash
# 1. 卸载旧200GB磁盘(切断旧关联)
sudo umount /data
# 2. 将新50GB磁盘挂载到 /data
sudo mount /dev/vdb1 /data
# 3. 创建附件目录(新盘可能没有)
sudo mkdir -p /data/attachments
# 4. 将文件存储挂载到 /data/attachments
sudo mount -t nfs 192.168.1.100:/nas_share /data/attachments
核心原理 :
umount /data只是切断目录与旧盘的关联, 旧盘数据完好无损 。/data变成一个普通空目录后,新盘直接挂载上来,实现无缝切换。
第四阶段:验证挂载结果
bash
# 1. 检查挂载点(应看到两条 /data 记录)
df -h | grep /data
# 预期输出示例:
# /dev/vdb1 50G 2.3G 47G 5% /data
# 192.168.1.100:/nas_share 1.0T 200G 800G 20% /data/attachments
# 2. 检查目录结构
ls -la /data
ls -la /data/attachments
# 3. 检查文件权限
ls -n /data | head -5
ls -n /data/attachments | head -5
第五阶段:启动服务并配置开机自动挂载
bash
# 1. 启动业务服务
sudo systemctl start nginx php-fpm
# 2. 测试业务功能(上传、下载附件)
# 建议用实际业务场景验证,如:
# - 登录业务后台
# - 上传一个新附件
# - 下载一个旧附件
# - 查看附件列表
# 3. 备份 /etc/fstab
sudo cp /etc/fstab /etc/fstab.bak
# 4. 编辑 /etc/fstab
sudo vi /etc/fstab
修改 /etc/fstab 内容:
text
# 旧200G磁盘行必须注释掉(行首加 #)
# /dev/vda1 /data ext4 defaults 0 0
# 新50G磁盘(父目录先挂载)
/dev/vdb1 /data ext4 defaults 0 0
# 文件存储(子目录后挂载)
192.168.1.100:/nas_share /data/attachments nfs defaults,_netdev,nofail,soft,timeo=100,retrans=2 0 0
关键参数说明:
| 参数 | 作用 |
|---|---|
_netdev | 网络设备,网络就绪后才挂载,避免开机卡住 |
nofail | 挂载失败不影响系统启动(云环境必备) |
soft | 超时后返回错误,不无限重试 |
timeo=100 | 超时时间10秒(单位0.1秒) |
retrans=2 | 重试2次后报错 |
特别注意 :
/etc/fstab中 父目录挂载行必须出现在子目录之前 (先/data,后/data/attachments),否则重启会报错。
bash
# 5. 验证 fstab 语法
sudo mount -a
如果没有任何错误输出,说明配置正确。
第六阶段:观察与回收旧盘
6.1 持续观察(建议1-2天)
bash
# 1. 检查业务日志,确认无报错
tail -f /var/log/nginx/access.log
tail -f /var/log/php-fpm/error.log
# 2. 检查磁盘使用情况
df -h /data
df -h /data/attachments
# 3. 检查是否有进程还在使用旧盘(应无输出)
sudo lsof | grep /dev/vda1
6.2 确认安全后回收旧盘
云环境:
- 登录云厂商控制台
- 找到该服务器关联的云盘
- 先点击 “卸载” (Detach)
- 再点击 “释放/删除” (Release)
- 确认停止计费
物理机:
- 通知运维人员
- 将硬盘从服务器槽位物理拔出
五、紧急回滚预案
如果迁移后发现问题,可在秒级内回滚到旧状态(旧盘数据完好无损):
bash
# 1. 停止服务
sudo systemctl stop nginx php-fpm
# 2. 卸载新挂载(注意顺序:先子目录,再父目录)
sudo umount /data/attachments
sudo umount /data
# 3. 重新挂载旧盘到 /data
sudo mount /dev/vda1 /data
# 4. 启动服务
sudo systemctl start nginx php-fpm
# 回滚完成,业务恢复正常
六、踩坑经验与避坑指南
6.1 挂载顺序陷阱
错误操作:
bash
sudo mount -t nfs 192.168.1.100:/nas_share /data/attachments
sudo mount /dev/vdb1 /data # 覆盖了NAS挂载!
正确操作: 必须先挂父目录,再挂子目录。
6.2 umount 时提示 target is busy
bash
# 解决方案
sudo fuser -km /data # 强制踢掉所有占用进程
sudo umount /data # 现在可以卸载了
6.3 rsync 源路径末尾的斜杠
/data/attachments/(带斜杠):复制目录内容到目标/data/attachments(不带斜杠):复制目录本身到目标
建议使用带斜杠的写法,避免多一层目录嵌套。
6.4 权限问题
跨设备迁移时,UID/GID可能不一致。使用 --numeric-ids 参数可保留数字ID,配合 --numeric-ids 能完美解决。
bash
# 检查权限是否一致
sudo ls -n /data/attachments | head -5
sudo ls -n /mnt/nas | head -5
七、总结
7.1 操作流程速览
| 阶段 | 操作 | 业务影响 |
|---|---|---|
| 第一阶段 | 挂载临时目录 | ✅ 无影响 |
| 第二阶段 | rsync 数据同步 | ✅ 无影响 |
| 第三阶段 | 停机切换挂载点 | ❌ 需停服 |
| 第四阶段 | 验证挂载结果 | ⚠️ 验证中 |
| 第五阶段 | 配置 fstab,启动服务 | ✅ 恢复正常 |
| 第六阶段 | 观察后回收旧盘 | ✅ 无影响 |
7.2 核心原则
- 数据先行 :所有变更操作前,先完成数据同步
- 保留回滚 :旧盘数据不动,可随时回滚
- 权限一致 :迁移后检查文件权限和属主
- 稳妥验证 :观察1-2天后再回收旧资源
7.3 收益
- ✅ 磁盘从200GB降为50GB,云资源成本降低约75%
- ✅ 附件数据迁移到文件存储,便于统一管理和备份
- ✅ 应用零改造,业务访问路径完全不变
- ✅ 迁移过程零数据丢失,支持秒级回滚
标题:服务器磁盘减配实战:从200GB到50GB + 文件存储,零数据丢失迁移指南
作者:zytops
地址:https://zytops.com/articles/2026/07/22/1784685827128.html