上一篇 下一篇 分享链接 返回 返回顶部

香港服务器 NVMe 做系统盘还是数据盘?分区、对齐与掉电保护要不要上

发布人:Minchunlin 发布时间:2025-09-29 10:02 阅读量:166


凌晨 3:07,香港机房的短信把我叫醒:“订单写入延迟飙升,3 分钟内失败率 2.1%”。我翻出值班本,定位到昨晚新上架的一台独立服务器:业务跑在 Docker 上,数据库是 PostgreSQL,数据盘被我临时放在一块“来不及换”的消费级 NVMe 上(无掉电保护),系统盘是SATA SSD。为了交付进度,我当时心想“先跑一天,明天换盘”。结果,峰值时段 fsync 压力一上来,这块无 PLP 的 NVMe 直接露了怯。
那一刻我决定做一轮系统化评测:NVMe 到底该做系统盘还是数据盘?分区/对齐到底多大影响?掉电保护要不要上?

环境与硬件清单(香港荔枝角机房)

型号/版本 备注
机型 Supermicro 1U / 单路 AMD EPYC 7302P(16C/32T) 固件已更新到厂商推荐版本
内存 128 GB DDR4 ECC  
系统 CentOS 7.9(3.10 内核) tuned-profile: throughput-performance
NVMe(企业级) Samsung PM9A3 1.92TB U.2(PCIe 4.0 x4) 带 PLP(掉电保护)
NVMe(消费级) WD Black SN770 1TB(PCIe 4.0 x4) 无 PLP
SATA SSD Intel S4510 960GB 带 PLP
双上联 10G 光口,BGP 多线 与内地业务有跨境流量
工具 fionvme-clilsblkpartedpgbench(PostgreSQL 13)、iostat  

说明:多数香港机房供电稳定,但我仍建议**UPS + 企业级 NVMe(带PLP)**作为数据库/日志盘的标配;跨境业务高峰时段写路径一旦被 fsync 压住,延迟直接影响成交。

评测设计:四种布局 + 三类工作负载

磁盘布局方案

A:NVMe 做系统盘,数据在 SATA SSD
适合预算有限或数据写入压力小的场景。

B:SATA SSD 做系统盘,NVMe(企业级,带PLP)做数据盘 ✅
常见且推荐的生产方案。

C:一块 NVMe 分区——前 100 GiB 做系统盘,剩余空间做数据盘
适合只有一块 NVMe 的机器,权衡成本/上架速度。

D:SATA SSD 做系统盘,NVMe(消费级,无PLP)做数据盘(临时) ⚠️
仅作对照,模拟“赶工交付/等盘到位”的风险场景。

负载模型

fio 随机读写

  • 4k 随机读(QD=32,4 job)
  • 4k 随机写(QD=32,4 job,不强制 fsync),看设备原生写入能力
  • 4k 写 fsync=1(QD=1,单 job),模拟数据库 WAL/订单落盘

128k 顺序吞吐(读取/写入,QD=32,4 job)

  • 模拟日志归档、对象文件顺序IO

pgbench(PostgreSQL 13)

  • synchronous_commit=on,full_page_writes=on
  • -c 32 -j 16 -T 300,scale=100
  • 只更换$PGDATA与pg_wal所在盘,其他保持一致

分区与对齐:我在现场的标准化做法

目标:1 MiB 对齐、GPT、系统与数据分卷独立挂载,操作简洁可回滚。

1)识别盘与基础信息

nvme list
nvme id-ctrl /dev/nvme0n1 | egrep -i 'oncs|vwc|frmw|fna'
lsblk -d -o NAME,ROTA,RO,TYPE,SIZE,MODEL

ROTA=0 表示非旋转介质(SSD/NVMe)。

vwc 只表示存在易失写缓存,不等于有 PLP;PLP 需查数据手册或选用企业型。

2)创建 GPT + 1 MiB 对齐分区(parted)

# 以企业级 NVMe /dev/nvme0n1 为例
parted -s /dev/nvme0n1 mklabel gpt
# 方案 C:前 100GiB 为系统盘,之后为数据盘
parted -s /dev/nvme0n1 unit MiB mkpart ESP fat32 1 513
parted -s /dev/nvme0n1 set 1 esp on
parted -s /dev/nvme0n1 unit MiB mkpart BOOT xfs 513 1025
parted -s /dev/nvme0n1 unit MiB mkpart ROOT xfs 1025 102400
parted -s /dev/nvme0n1 unit MiB mkpart DATA xfs 102400 100%

从 1 MiB 开始,天然对齐到 4k/8k 物理扇区。

print -l 可验证起始扇区是 2048 的倍数(512B 扇区时)。

3)文件系统与挂载

我习惯系统盘用 ext4(稳妥),数据盘用 XFS(大文件/并发更友好):

mkfs.vfat -F32 /dev/nvme0n1p1
mkfs.xfs  -f /dev/nvme0n1p2   # /boot
mkfs.ext4 -F -E lazy_itable_init=0,lazy_journal_init=0 /dev/nvme0n1p3  # /
mkfs.xfs  -f -m crc=1,finobt=1 -i size=512 -n size=4096 /dev/nvme0n1p4 # /data

挂载建议(/etc/fstab):

/dev/nvme0n1p3 /     ext4 defaults,noatime,nodiratime 0 1
/dev/nvme0n1p2 /boot xfs  defaults                      0 2
/dev/nvme0n1p4 /data xfs  defaults,noatime,inode64      0 2

不建议 discard 挂载选项,改为启用周期性 TRIM:

systemctl enable fstrim.timer
systemctl start fstrim.timer

4)I/O 调度器与读写前置

# NVMe 走多队列,推荐 'none'(旧内核可能显示 'noop')
cat /sys/block/nvme0n1/queue/scheduler
echo none > /sys/block/nvme0n1/queue/scheduler

# 合理的 readahead(示例 256 KiB)
blockdev --setra 512 /dev/nvme0n1

fio/pgbench 实测结果

注:每组测试跑 3 次,取中位数;温度稳定在 40–45℃;CPU 占用不成瓶颈。以下 IOPS/吞吐与延迟均为我机房现场数据,单位见表头。

1)随机 4k 读(QD32,4 job,IOPS)

布局 IOPS(万) P99 延迟(µs)
A:NVMe 系统 / SATA 数据 8.5 1450
B:SATA 系统 / NVMe(PLP) 数据 64.0 480
C:NVMe 分区(前100G系统/其余数据) 63.2 495
D:SATA 系统 / NVMe(无PLP) 数据 61.5 560

结论:随机读主要看介质;NVMe 放数据盘优势巨大。是否与系统共盘几乎不影响读性能(C≈B)。

2)随机 4k 写(QD32,4 job,IOPS;不强制fsync)

布局 IOPS(万) P99 延迟(µs)
A:NVMe 系统 / SATA 数据 4.1 6800
B:SATA 系统 / NVMe(PLP) 数据 14.0 2700
C:NVMe 分区(系统+数据) 13.7 2800
D:SATA 系统 / NVMe(无PLP) 数据 12.1 3300

结论:写入吞吐 NVMe 仍碾压 SATA;PLP 对非 fsync写入影响不大,但 NVMe 的稳定性更好。

3)4k 写 fsync=1(QD=1,单 job,ops/s)

布局 ops/s(千次) P99 延迟(ms)
A:NVMe 系统 / SATA 数据 2.3 13.0
B:SATA 系统 / NVMe(PLP) 数据 18.0 1.7
C:NVMe 分区(系统+数据) 17.6 1.8
D:SATA 系统 / NVMe(无PLP) 数据 5.8 5.6

结论(关键):带 PLP 的 NVMe 在 fsync 场景下领先 3~8 倍。无 PLP 的 NVMe 在强一致写入时性能显著掉队,且遇掉电风险时数据更不安全。

4)128k 顺序吞吐(GB/s)

布局 读(GB/s) 写(GB/s)
A:NVMe 系统 / SATA 数据 0.54 0.50
B:SATA 系统 / NVMe(PLP) 数据 3.50 2.80
C:NVMe 分区(系统+数据) 3.47 2.75
D:SATA 系统 / NVMe(无PLP) 数据 3.45 2.60

结论:顺序吞吐 NVMe 明显占优;是否与系统共盘影响极小。

5)pgbench(TPS,-c 32 -j 16 -T 300)

布局 TPS P99 提交延迟(ms)
A:NVMe 系统 / SATA 数据 3,300 28.4
B:SATA 系统 / NVMe(PLP) 数据 14,200 6.8
C:NVMe 分区(系统+数据) 13,900 7.1
D:SATA 系统 / NVMe(无PLP) 数据 5,100 17.9

结论:只要把 数据与 WAL 放到带 PLP 的 NVMe 上,TPS 立刻提升 3–4 倍;无 PLP 的 NVMe 在强一致事务下也拉胯。

为什么 PLP 如此关键?

数据库/支付/订单类场景会频繁调用 fsync() 确保写入落盘。

带 PLP 的企业级 NVMe(电容阵列 + 固件保证)能在断电时把易失缓存中的数据安全转存到 NAND;在有序写回与 cache flush 上更激进且仍然安全,因此 fsync 延迟更低、抖动更小。

无 PLP 的 NVMe 为确保崩溃一致性,往往需要更保守的 flush 策略,性能显著下降;极端掉电还可能导致元数据损坏(哪怕你使用了 barrier/journal 机制,也只是把风险降低,而不是消灭)。

实操建议(可直接套用)

优先顺序

  • 数据库/消息队列/高价值日志 → NVMe(企业级,带 PLP)
  • 系统盘 → SATA SSD 或 NVMe 切 100 GiB 分区(方案 B 或 C)
  • 预算有限只有 1 块 NVMe?方案 C:前 100 GiB 给系统,其余给数据,依然有 98% 的 NVMe 数据盘性能。

分区/对齐

  • 使用 GPT,从 1 MiB 起创建分区;避开旧 MBR/CHS 的齐次误差。
  • 验证起始扇区是否为 2048 的倍数。

文件系统

  • 系统盘 ext4(稳妥),数据盘 xfs(并发友好);noatime + fstrim.timer。
  • XFS 建议 -i size=512 -n size=4096,大目录与小文件场景兼顾。

调度器与内核

  • NVMe 调度器 none,合理调大 readahead(例如 256 KiB)。
  • tuned-adm profile throughput-performance,对批量 IO 友好。

电力与保护

  • PLP 优先级=高;同时配套 UPS 与定期备份(快照 + 远端对象存储)。
  • 生产库开启 synchronous_commit=on、full_page_writes=on;不要为 TPS 牺牲一致性。

监控与告警

  • nvme smart-log 温度、介质错误、可用备用块;
  • iostat -x 1 盯 util、await;
  • 业务侧暴露 P95/P99 fsync 延迟与失败率。

复现实验:可复制粘贴的命令

fio(示例)
# 随机读
fio --name=randread --filename=/data/fio.test --size=100G \
    --bs=4k --ioengine=libaio --iodepth=32 --rw=randread \
    --direct=1 --numjobs=4 --time_based --runtime=60 --group_reporting

# 随机写(非 fsync)
fio --name=randwrite --filename=/data/fio.test --size=100G \
    --bs=4k --ioengine=libaio --iodepth=32 --rw=randwrite \
    --direct=1 --numjobs=4 --time_based --runtime=60 --group_reporting

# 4k 写 + fsync=1(数据库最敏感)
fio --name=fsyncwrite --filename=/data/fio.fsync --size=10G \
    --bs=4k --ioengine=libaio --iodepth=1 --rw=write \
    --fsync=1 --direct=1 --numjobs=1 --time_based --runtime=60 --group_reporting

# 128k 顺序
fio --name=seqread --filename=/data/fio.seq --size=100G \
    --bs=128k --ioengine=libaio --iodepth=32 --rw=read \
    --direct=1 --numjobs=4 --time_based --runtime=60 --group_reporting

PostgreSQL(pgbench)快速跑法

# 假设 /data 为目标盘(切换不同布局时仅变更此挂载点)
initdb -D /data/pgdata
echo "synchronous_commit=on" >> /data/pgdata/postgresql.conf
echo "full_page_writes=on"   >> /data/pgdata/postgresql.conf
pg_ctl -D /data/pgdata -l /data/pgdata/logfile start

createdb bench
pgbench -i -s 100 bench
pgbench -c 32 -j 16 -T 300 bench

现场坑位与应急记要

坑1:无 PLP NVMe 在高峰 fsync 抖动严重
现象:P99 延迟从 2ms 飙到 20ms+;
处理:凌晨切业务只读,热迁移 WAL 到企业级 NVMe,TPS 与延迟恢复。

坑2:克隆系统后 XFS UUID 冲突
现象:/data 无法挂载;
处理:xfs_admin -U generate /dev/nvme0n1p4 重新生成 UUID,更新 /etc/fstab。

坑3:CentOS 7 旧内核某些机型上 NVMe 调度器显示异常
处理:确认 blk-mq 生效;不行就升级内核到 ELRepo kernel-lt(保守)后再测。

坑4:UEFI 启动项丢失(切分 NVMe 做系统盘时遇到)
处理:用 efibootmgr 重建启动项;必要时 chroot + grub2-install。

坑5:错误使用 discard 导致业务延迟抖动
处理:移除挂载 discard,改用 fstrim.timer 周期执行。

我给到的最终选择题答案

如果你跑的是数据库/支付/订单/队列这类强一致写入场景:

  • 选 B 或 C:让 NVMe(带 PLP)做数据盘,SATA 做系统或 NVMe 切 100 GiB 给系统。
  • 你的收益是:pgbench TPS 3–4 倍提升,P99 延迟大幅下降,故障边界也更可控。

如果你的业务主要是读多写少、无强一致:

  • 也建议NVMe 放数据盘。系统盘放 NVMe 的意义很小(除非你密集做容器镜像构建/IO 很重的系统任务)。

只有一块 NVMe 的情况:

  • 方案 C(前 100 GiB 系统,其余数据)几乎与纯数据 NVMe(方案 B)等效(本次测试差 <2%)。

NVMe 的价值 95% 在“数据盘”,而不是“系统盘”;PLP 是数据库/日志类场景的“硬性选项”。

我在香港机房把 WAL 切回企业级 NVMe,pgbench TPS 从 5k 爬回 14k,P99 落到 7ms。业务同事在群里丢了个“稳了”的表情包,我把凌晨的咖啡倒掉,关了告警声音。
NVMe 做系统盘还是数据盘? 这次不用再争了。把它用在最需要它的地方——数据与 WAL 上;对齐、文件系统、调度器一步不落;PLP 该上就上。下一次凌晨的短信,大概率会少很多

目录结构
全文