服务器磁盘减配实战:从200GB到50GB + 文件存储,零数据丢失迁移指南

  |   0 评论   |   0 浏览

一、背景与需求

最近遇到一个典型的服务器资源优化场景:一台应用服务器挂载了200GB的系统盘,其中附件数据占了大部分空间,而实际业务核心程序占用不足50GB。为了降本增效,需要:

  • 磁盘减配 :将200GB磁盘替换为50GB磁盘
  • 附件分离 :将附件数据迁移到外部文件存储(NAS/云文件存储)
  • 路径不变 :业务访问路径必须保持 /data 不变,应用零改造

本文记录了一次零数据丢失、可秒级回滚的完整迁移过程。

二、方案设计

2.1 架构对比

迁移前:

text

/data  →  200GB本地磁盘(程序 + 附件混在一起)

迁移后:

text

/data  →  50GB本地磁盘(仅程序、配置文件)
/data/attachments  →  文件存储(NAS/云存储,存放附件)

2.2 核心策略

采用 “先同步、后切换” 的策略,整个过程分为四个阶段:

  1. 数据同步 :在业务正常运行期间,将数据同步到目标存储
  2. 停机切换 :停止服务,完成最后一次增量同步,切换挂载点
  3. 验证持久化 :启动服务验证,配置开机自动挂载
  4. 观察回收 :稳定运行后回收旧磁盘

2.3 关键技术点

  • rsync:增量同步,支持断点续传,保留权限属性
  • mount --bind(备选):或直接切换挂载点
  • /etc/fstab:开机自动挂载配置
  • 紧急回滚预案:旧盘数据不动,可秒级恢复

三、环境准备

3.1 变量确认

开始前,请先确认以下信息:

项目示例值确认命令
旧磁盘设备/dev/vda1df -h /data
新磁盘设备/dev/vdb1lsblk
文件存储地址192.168.1.100:/nas_share根据实际填写
附件目录/data/attachmentsls -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 确认安全后回收旧盘

云环境:

  1. 登录云厂商控制台
  2. 找到该服务器关联的云盘
  3. 先点击 “卸载” (Detach)
  4. 再点击 “释放/删除” (Release)
  5. 确认停止计费

物理机:

  1. 通知运维人员
  2. 将硬盘从服务器槽位物理拔出

五、紧急回滚预案

如果迁移后发现问题,可在秒级内回滚到旧状态(旧盘数据完好无损):

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. 保留回滚 :旧盘数据不动,可随时回滚
  3. 权限一致 :迁移后检查文件权限和属主
  4. 稳妥验证 :观察1-2天后再回收旧资源

7.3 收益

  • ✅ 磁盘从200GB降为50GB,云资源成本降低约75%
  • ✅ 附件数据迁移到文件存储,便于统一管理和备份
  • ✅ 应用零改造,业务访问路径完全不变
  • ✅ 迁移过程零数据丢失,支持秒级回滚

标题:服务器磁盘减配实战:从200GB到50GB + 文件存储,零数据丢失迁移指南
作者:zytops
地址:https://www.zytops.com/articles/2026/07/22/1784685827128.html