从普通云硬盘迁移到香港云服务器NVMe盘,如何评估I/O收益、停机窗口与回退条件?

先判断:NVMe 的收益是否能解决当前瓶颈
香港云服务器 NVMe 硬盘优势是什么?通常体现在更适合高并发随机读写、较低存储访问延迟,以及更好的并行 I/O 能力。但“使用 NVMe 接口”不等于业务一定会变快,最终效果还取决于云平台的存储后端、磁盘 IOPS 和吞吐上限、文件系统、队列深度,以及应用是否真的受存储限制。
因此,从普通云硬盘迁移前,建议先满足三个条件:
- 已经确认当前业务瓶颈与磁盘读写有关,而不是 CPU、内存、数据库锁、网络或应用代码。
- 新盘可以在当前香港云服务器上正常挂载,并确认其数据持久性、快照和备份能力符合业务要求。
- 已准备可恢复的旧盘、备份或快照,并且迁移后保留一段不变更的回退路径。
如果当前磁盘的 await、应用写入延迟或数据库提交等待明显偏高,同时新 NVMe 盘在相同测试条件下表现更好,迁移通常有评估价值。若业务只是顺序读取、网络响应慢,或者磁盘利用率长期很低,单纯更换 NVMe 盘可能不会带来明显收益。
迁移前先确认哪些条件
确认新盘的实际属性
在云平台控制台和系统内分别确认以下内容:
- 新盘是否支持挂载到当前服务器,还是必须创建新的服务器。
- 新盘是持久化云盘、临时本地盘,还是具有重建后数据可能丢失的限制。
- 云平台是否对 IOPS、吞吐量、突发性能或容量设置上限。
- 是否支持快照、备份、扩容和故障恢复。
- 操作系统内核是否识别 NVMe 设备。
- 新盘支持的文件系统,以及现有应用需要的挂载参数。
- 云平台是否要求使用特定的设备标识或控制台操作完成挂载。
NVMe 设备在 Linux 中常见的名称类似 /dev/nvme1n1,但不能仅凭设备名称判断哪块盘是新盘。先执行以下检查:
cat /etc/os-release
uname -r
lsblk -o NAME,MODEL,SERIAL,SIZE,TYPE,FSTYPE,MOUNTPOINTS,UUID
findmnt -R
对照云平台显示的容量、序列号或设备标识确认目标盘。确认前不要执行格式化操作。
如果新盘是空盘,可以查看其是否已经存在文件系统:
sudo blkid /dev/disk/by-id/REPLACE_WITH_NEW_DEVICE
sudo file -s /dev/disk/by-id/REPLACE_WITH_NEW_DEVICE
只有在确认设备为空、没有需要保留的数据,并且已经完成备份或确认不需要回退该盘时,才可以格式化。例如使用 ext4:
sudo mkfs.ext4 -L appdata-nvme /dev/disk/by-id/REPLACE_WITH_NEW_DEVICE
mkfs 会覆盖目标设备上的原有文件系统,设备路径、文件系统类型和业务数据必须再次核对。若业务要求 XFS 或其他文件系统,应按操作系统和应用兼容性选择,不能直接套用上述示例。
记录现有数据和写入规模
停机窗口不能只按照磁盘容量估算。需要同时了解已用空间、文件数量、持续写入量和需要同步的日志目录。
OLD_MOUNT="/srv/app-data"
df -hT "$OLD_MOUNT"
df -ih "$OLD_MOUNT"
sudo du -shx "$OLD_MOUNT"
findmnt -T "$OLD_MOUNT"
findmnt -R "$OLD_MOUNT"
如果文件数量很多,可以在业务低峰期统计:
sudo find "$OLD_MOUNT" -xdev -type f | wc -l
还要确认以下内容是否位于迁移目录中:
- 数据库主数据目录;
- 事务日志、归档日志或消息队列数据;
- 应用上传文件;
- 定时任务产生的临时文件;
- 备份程序使用的目录;
- 通过挂载点嵌套在目录下的其他文件系统。
如果目录下存在嵌套挂载,不能把整个目录简单地当成一个普通目录复制。应分别核对每个挂载点,否则迁移后可能出现目录存在但实际数据未迁移的情况。
用同口径测试判断 I/O 收益
先看业务是否真的受磁盘限制
在当前业务运行期间观察磁盘和应用指标。Linux 上可以使用 iostat:
iostat -xz 1
重点记录业务高峰期间的以下指标:
r/s、w/s:每秒读写次数;rkB/s、wkB/s:读写吞吐;await:I/O 平均等待时间;aqu-sz:设备队列长度;%util:设备繁忙程度。
同时记录应用请求延迟、错误率、数据库提交等待、任务处理时间等业务指标。单看 %util 不能证明一定需要迁移,因为应用可能受 CPU、锁或线程数限制;单看 IOPS 也不能证明业务一定受益,必须和实际请求延迟对应起来。
如果当前磁盘已经出现持续排队、等待时间升高,且应用延迟和磁盘高峰同步变化,存储更换的收益更值得验证。若磁盘很空闲,但应用延迟仍然很高,应先排查应用和数据库,不要直接采购更高规格磁盘。
在新盘上进行非生产压测
新盘挂载到临时目录后,可以在新盘上建立独立测试文件。不要直接对生产数据目录执行随机写压测,也不要在没有备份的情况下覆盖现有数据。
先确认 fio 是否可用:
fio --version
fio --enghelp
下面是一个示例测试,测试文件位于新盘,不会直接覆盖业务数据:
STAGE_MOUNT="/mnt/nvme"
sudo fio \
--name=nvme-randrw \
--filename="$STAGE_MOUNT/.fio-test" \
--size=1G \
--rw=randrw \
--rwmixread=70 \
--bs=4k \
--ioengine=libaio \
--iodepth=32 \
--numjobs=1 \
--direct=1 \
--runtime=60 \
--time_based \
--group_reporting
测试参数需要和业务特征保持一致:
- 小文件、数据库索引较多时,重点关注小块随机读写和延迟;
- 日志或备份以连续写入为主时,重点关注顺序吞吐;
- 并发应用较多时,测试多个队列深度或任务数;
- 业务依赖持久化提交时,需要关注
fsync或同步写入延迟; - 测试文件应足够覆盖实际工作集,但不能占满新盘。
libaio、io_uring 等 I/O 引擎是否可用取决于系统和 fio 编译方式。如果测试报错,应根据 fio --enghelp 选择当前系统支持的引擎,并保证新旧测试使用相同参数。压测输出中的 IOPS、带宽和平均或百分位延迟只能用于同口径比较,不能直接当作业务承载量承诺。
如果要对普通云硬盘做对照测试,应使用独立测试文件、快照副本或业务允许的低风险窗口。生产盘不建议执行随机写测试。更可靠的方式是记录现有业务高峰指标,再将新盘测试结果与同一业务回放或迁移后的实际指标比较。
判断是否值得迁移
可以按以下条件做判断:
| 观察结果 | 迁移判断 |
|---|---|
| 现有盘等待时间高,应用延迟与磁盘排队同步升高;新盘同口径延迟更低 | 值得进入迁移准备 |
| 现有盘吞吐接近上限,新盘吞吐上限和测试结果都更高 | 可评估迁移,但要确认应用能产生足够并发 |
| 磁盘利用率低,瓶颈位于 CPU、内存、锁或网络 | 暂不迁移,先处理实际瓶颈 |
| 新盘压测好看,但应用请求延迟没有改善 | 不应仅凭压测结果迁移 |
| 新盘是临时盘,重建或特定运维操作可能丢失数据 | 不能把它作为唯一持久化副本 |
| 需要保留 ACL、扩展属性、稀疏文件或特殊挂载参数,但新文件系统不支持 | 先解决兼容性,再安排迁移 |
成本判断也不能只看磁盘单价,还要核对容量、性能上限、快照和备份费用、扩容方式,以及迁移期间的人工和停机成本。当前没有这些实际报价时,不应预设具体节省金额。
设计可控的迁移窗口
先完成一次在线初始复制
以下示例假设新盘挂载到 /mnt/nvme,旧数据目录是 /srv/app-data。目标目录必须确认为空或仅包含本次复制的数据。
OLD_MOUNT="/srv/app-data"
STAGE_MOUNT="/mnt/nvme"
sudo mkdir -p "$STAGE_MOUNT"
sudo mount /dev/disk/by-uuid/REPLACE_WITH_NEW_UUID "$STAGE_MOUNT"
df -hT "$OLD_MOUNT" "$STAGE_MOUNT"
findmnt -T "$STAGE_MOUNT"
对于普通文件目录,可以先进行初始复制:
time sudo rsync -aHAXS \
--numeric-ids \
--info=progress2 \
"$OLD_MOUNT"/ "$STAGE_MOUNT"/
这些参数用于尽量保留硬链接、ACL、扩展属性、稀疏文件和数字 UID/GID。使用前确认目标文件系统支持这些属性;如果 rsync 报告 ACL 或扩展属性不支持,不要直接忽略错误,应先核对应用是否依赖这些属性。
在线初始复制只适合能够接受文件短暂不一致、并且可以在最终阶段停止写入的普通文件业务。不要把正在运行的数据库主数据目录当成普通文件目录持续复制。数据库应使用自身的备份、物理复制、快照或干净停库方案,以保证事务一致性。
初始复制结束后,再进行一次演练式检查,估计最终同步需要处理多少变更:
sudo rsync -aHAXS \
--numeric-ids \
--dry-run \
--stats \
"$OLD_MOUNT"/ "$STAGE_MOUNT"/
通过初始复制耗时、第二次同步的变更量,以及业务实际写入速度,可以估算最终停机阶段的同步时间。停机窗口可按以下方式拆分:
停机窗口 =
停止写入与服务耗时
+ 最终同步耗时
+ 卸载旧盘与挂载新盘耗时
+ 服务启动耗时
+ 数据与业务验证耗时
最终同步的关键不是总数据量,而是停机时仍然变化的数据量。如果业务持续写入的速度高于同步速度,最终同步可能无法收敛,此时应先启用维护模式、暂停任务生产、停止写入进程,或改用数据库复制方案。
进入最终同步前停止所有写入者
不要只停止主应用,还要核对后台任务、队列消费者、定时任务和备份程序是否仍会写入目录。以 systemd 服务为例:
APP_SERVICE="your-app.service"
sudo systemctl stop "$APP_SERVICE"
sudo systemctl is-active "$APP_SERVICE" || true
systemctl stop 会中断指定服务,执行前应确认已经有可用备份,并记录服务当前状态。若停止失败,不要立即强制终止进程,先查看服务日志和进程状态。
确认服务和写入任务都停止后,再执行最终同步。只有当新目录是旧目录的准确镜像,并且已经确认目标盘内容可以被覆盖或删除时,才使用 --delete:
sudo rsync -aHAXS \
--numeric-ids \
--delete \
--info=progress2 \
"$OLD_MOUNT"/ "$STAGE_MOUNT"/
--delete 会删除目标目录中源目录不存在的文件,影响范围仅限于目标路径,但误选路径会造成数据丢失。执行前必须核对源、目标、备份和目录末尾的 /。如果不需要同步源端删除记录,可以去掉 --delete,但目标盘可能保留源端已经删除的旧文件。
最终同步完成后,可以做内容和元数据核对:
sudo rsync -aHAXS \
--numeric-ids \
--checksum \
--dry-run \
--itemize-changes \
"$OLD_MOUNT"/ "$STAGE_MOUNT"/
--checksum 会读取文件内容进行比较,数据量较大时可能增加 I/O 和校验时间。重要数据还应使用应用自身的校验、数据库一致性检查或备份恢复验证,不要只依赖目录大小相同。
切换挂载点并保持旧盘可回退
先保存挂载配置
在改动 /etc/fstab 前,先保存副本,并记录旧盘 UUID:
sudo cp -a /etc/fstab /etc/fstab.before-nvme-migration
lsblk -f
findmnt -no SOURCE,FSTYPE,OPTIONS /srv/app-data
然后使用 sudoedit 修改挂载配置,将业务挂载点指向新盘 UUID。示例仅表示格式,文件系统类型和挂载选项必须替换为实际值:
UUID=REPLACE_WITH_NEW_UUID /srv/app-data ext4 defaults 0 2
不要直接套用旧盘的设备名,因为设备名可能在重启或重新挂载后发生变化。也不要在不了解含义的情况下复制旧盘的全部挂载选项。修改后先检查配置:
sudo findmnt --verify --verbose
执行切换
确认服务已停止、最终同步完成,并且新旧盘的 UUID 都已记录。先卸载临时挂载,再卸载旧盘:
sudo umount /mnt/nvme
sudo umount /srv/app-data
如果卸载提示目录繁忙,先查找占用进程:
sudo fuser -vm /srv/app-data
不要在没有确认进程和数据状态的情况下使用强制卸载。处理完占用后重新卸载。强制卸载可能让应用看到不完整的数据状态,也会增加回退难度。
挂载新盘:
sudo mount /srv/app-data
findmnt -T /srv/app-data
df -hT /srv/app-data
如果挂载失败,不要格式化新盘,也不要删除旧盘。先检查 UUID、文件系统类型、挂载参数和内核日志:
lsblk -f
sudo journalctl -k -b --no-pager -n 100
只有确认挂载点显示的是新盘,并且文件系统容量、可用空间和挂载参数正确后,才进入服务启动阶段。
切换后的成功验证
验证顺序建议从存储层、权限层、应用层到性能层逐步进行。
存储和权限验证
findmnt -T /srv/app-data
lsblk -o NAME,SIZE,FSTYPE,MOUNTPOINTS,UUID
df -hT /srv/app-data
df -ih /srv/app-data
检查关键目录的属主、权限、ACL 和扩展属性:
sudo stat /srv/app-data
sudo namei -l /srv/app-data
应用使用的账号必须能够按原有方式读取和写入。可以使用业务账号创建临时文件进行验证,但路径和文件名必须是明确的测试对象:
APP_USER="app"
TEST_FILE="/srv/app-data/.migration-write-test"
sudo -u "$APP_USER" sh -c "printf '%s\n' migration-test > '$TEST_FILE'"
sudo -u "$APP_USER" cat "$TEST_FILE"
sudo rm -f -- "$TEST_FILE"
上述删除命令只应在确认变量指向本次创建的测试文件后执行。如果应用账号、目录或权限模型不同,应使用实际业务账号和测试路径,不要用 root 写入来代替应用权限验证。
应用和数据验证
启动服务前,先确认配置中的数据路径没有变化,或者新挂载点已经保持原路径:
sudo systemctl start "$APP_SERVICE"
sudo systemctl is-active "$APP_SERVICE"
sudo journalctl -u "$APP_SERVICE" -n 100 --no-pager
随后验证:
- 应用能否正常启动;
- 既有文件是否可读取;
- 新文件是否能写入;
- 数据库或应用自身的一致性检查是否通过;
- 后台任务是否能正常执行;
- 备份程序是否仍能找到目录;
- 监控是否识别新设备和新挂载点。
如果应用有内部健康检查,应使用实际的本地检查地址,例如:
curl -fsS http://127.0.0.1:REPLACE_WITH_PORT/health
端口和路径必须替换为业务真实配置,不能把示例地址当成通用接口。
重新记录性能
服务恢复后,在与迁移前相近的业务负载下重新观察:
iostat -xz 1
对比迁移前后的应用延迟、错误率、数据库提交等待、I/O 等待和任务完成时间。只有在真实业务指标改善,或者已明确解决原有存储瓶颈时,才能认为迁移收益成立。新盘的 fio 结果高于旧盘,并不代表所有业务都会按相同比例提升。
失败时如何回退
适合立即回退的情况
出现以下情况时,应优先停止写入并考虑回退:
- 新盘无法稳定挂载或出现 I/O 错误;
- 文件数量、关键文件校验或数据库一致性检查不通过;
- 应用启动失败,且原因明确与路径、权限或文件系统有关;
- 迁移后延迟和错误率明显恶化;
- 新盘的持久化、快照或备份能力不满足业务要求;
- 业务观察期内出现持续的读写异常。
回退前先停止应用和所有写入任务:
sudo systemctl stop "$APP_SERVICE"
sudo fuser -vm /srv/app-data
确认没有写入进程后,卸载当前挂载的新盘:
sudo umount /srv/app-data
然后将 /etc/fstab 中的挂载项恢复为旧盘 UUID,再挂载旧盘:
sudoedit /etc/fstab
sudo findmnt --verify --verbose
sudo mount /srv/app-data
findmnt -T /srv/app-data
df -hT /srv/app-data
最后进行关键文件、权限和应用检查,确认旧盘可用后再启动服务。旧盘在确认迁移成功前不要格式化、删除或交还平台。
明确回退截止点
回退并不是任意时刻都能无损完成。新盘切换后,如果应用已经在新盘产生了新订单、新文件、日志或数据库事务,旧盘就会落后于新盘。此时直接挂回旧盘会丢失切换后的新增数据。
因此,迁移前应预先确定回退截止点:
- 在服务启动前发现挂载或校验问题,通常可以直接回退;
- 服务启动但尚未接受业务写入时,仍可快速回退;
- 服务已经产生新写入后,必须先保留新盘,结合数据库备份、业务导出或一致性复制方案处理数据差异;
- 不要同时让新旧两块盘以可写方式承载同一份业务数据,避免形成无法判断的双向差异。
如果回退过程中发现目录繁忙、数据校验失败或设备异常,不要反复强制卸载和覆盖写入。先保留现场,记录内核日志、应用日志、挂载状态和新旧盘 UUID,再决定是恢复旧盘、从备份恢复,还是重新执行一次受控迁移。
什么时候应继续升级,而不是停在 NVMe 迁移
迁移完成后,如果磁盘等待时间下降但业务延迟没有改善,说明瓶颈可能已经转移到 CPU、内存、数据库锁、连接池、应用线程或网络,此时继续提高磁盘规格未必有效。
如果新盘仍然出现队列堆积,应进一步核对云平台公布的 IOPS、吞吐和并发限制,以及应用实际的并发度和 I/O 模式。若业务数据持续增长、日志和临时文件挤占空间,升级容量或重新规划目录也应与性能升级分开评估。
只有在以下条件同时成立时,才适合扩大迁移范围或继续提升配置:
- 新 NVMe 盘在实际业务中稳定改善了关键延迟指标;
- 备份、快照和恢复流程已经验证;
- 应用、数据库和文件系统兼容性没有异常;
- 停机窗口能够覆盖最终同步和验证;
- 旧盘或可恢复备份仍然保留;
- 新增的性能和容量确实对应业务增长,而不是只根据接口名称或压测峰值采购。