精读笔记(RHCA 英文教材)· RH442 Chapter 9 Tuning Storage Device I/O
精读笔记(RHCA 英文教材)· RH442 Chapter 9 Tuning Storage Device I/O
教材原文:RHCA 官方英文教材(PDF 第 346~373 页)(OCR 整书版已从本站移除,本页为章节精读) 关联中文笔记:
02-09-性能调优RH442(RHCA).md(磁盘:I/O 调度器 deadline/noop/mq-deadline、iostat -x、RAID 策略);本章=存储 I/O 三大块:I/O 模式与调度算法 → RAID 基础与对齐 → I/O 分析工具选型。 结构:3 个 Section(9.1 评估 I/O 模式与调度算法+GE storage-patterns;9.2 复习 RAID 基础+GE storage-raid;9.3 选择 I/O 分析工具+GE storage-analysis)+ Lab(lab: storage-review)。
Chapter Goal / Objectives(原文+译)
- GOAL: Manage settings for efficient disk utilization in various use cases.(管理多种场景下磁盘高效利用的设置。)
- OBJECTIVES: ① 描述事务型/顺序型 I/O 模式与磁盘调度算法;② 理解基本 RAID 架构,掌握应用写入与 RAID 条带对齐的关系;③ 掌握多种分析磁盘 I/O 行为的工具。
9.1 Evaluating I/O Patterns and Scheduling Algorithms(I/O 模式与调度算法)
- SSD 取代机械盘:SSD 无磁头寻道/旋转延迟/机械故障,访问时间全盘均匀,无需碎片整理与磁道优化。局限:写入次数有限(靠 wear leveling 均衡磨损延长寿命)、成本更高。
- 旧调优经验大多不适用于 SSD:不需 read ahead / write behind 缓存,缓存应配成 write-through。教材提示:SSD 上不必要的双重写入(含日志型写放大)增加磨损并拖慢速度,Red Hat 不建议在 SSD 上使用 journaling(❕按教材原文记录,生产环境请结合具体文件系统特性判断)。
- blk-mq 多队列机制:RHEL8 用 Multi-Queue Block I/O Queuing Mechanism 取代单队列调度器——I/O 映射到多条软件/硬件请求队列与执行线程,不同核并行处理,降低单设备并发 I/O 的锁竞争。NVMe 原生支持多条硬件提交/完成队列与低延迟,正好利用该特性。
- RHEL8 四个多队列调度器(
/sys/block/<dev>/queue/scheduler,[]括起的是当前激活项):- mq-deadline(默认):旧 deadline 的多队列版。两条按到期时间排序的队列(写/读各一)防 I/O 饿死;无临近到期请求时从第三条按扇区排序的队列派发。提供其他调度器还没有的写请求排序保证。
- kyber:面向高速设备,读(同步)与写(异步)两队列,靠严格限制在途请求数控制每请求延迟,高优先级请求完成快。吞吐敏感的服务端负载(尤其 SSD)首选——更简单、请求处理更快。
- bfq:CFQ 的改进版,公平共享按请求扇区数与启发式而非时间片;交互响应稳定,适合慢速机械盘。每操作开销较高,I/O 便宜且追求吞吐(如 CPU 慢的机器)时不合适。替代旧单队列 cfq。
- none:不重排 I/O 请求,适合 NVMe 这类快速随机设备;替代旧 noop。⚠️ NVMe 默认用 none 且无法更改。
- 查看可调参数:激活调度器参数在
/sys/block/<dev>/queue/iosched/,mq-deadline 有fifo_batch(每批操作数:小=低延迟,大=高吞吐)、front_merges、read_expire、write_expire、writes_starved。 - 启用旧单队列调度器:引导参数
scsi_mod.use_blk_mq=0可让 deadline/cfq/noop 在启动时可用(⚠️ 注意参数是给 scsi_mod 的,其它驱动不一定支持)。 - 用 tuned 调存储:预置档 latency-performance / throughput-performance。插件:disk 插件用
elevator=指定调度器;sysfs 插件用 key=value 写 iosched 参数(如[sysfs] /sys/block/vda/queue/iosched/fifo_batch=1)。 - fio 模拟工作负载:多线程/多进程模拟顺序/随机读写与混合 I/O,可多个 job 打同一文件。关键参数:
--filename:目标文件/块设备(⚠️ 指块设备会整盘覆写);--name+--size:无现成文件时按名建 size 大小文件。--rw=:read/write/randread/randwrite/readwrite/randrw;混合可设读写百分比。--bs/--bsrange:固定块大小或范围。--direct=1:Direct I/O 绕过 page cache 直写磁盘;=0 时走页缓存,测到的是内存速度而非磁盘。--ioengine=libaio --iodepth=N:N 个异步在途请求;异步必须配 direct=1(页缓存不可异步寻址)。ioengine 还支持同步/内存映射/rdma/网络等形态。--numjobs=N --group_reporting:N 个线程跑相同负载,合并统计输出。- 参考:
/usr/share/doc/fio/HowTo;KB:what tuning parameters are available for the mq-deadline I/O scheduler(access.redhat.com/solutions/3790801)。
9.1 GE(lab: storage-patterns)
servera:确认 vda 激活 mq-deadline、ls /sys/block/vda/queue/iosched 看参数(fifo_batch 默认 16)→ fio 随机写 512MiB×2 jobs 测基线(clat avg≈262585 usec)→ 自订档 /etc/tuned/reduce-latency/tuned.conf:[main] include=latency-performance + [sysfs] /sys/block/vda/queue/iosched/fifo_batch=1 → tuned-adm profile reduce-latency 并 cat 校验 → 重测 clat avg 降到≈215404 usec(fifo_batch 16→1 减批次大小降延迟)→ lab storage-patterns finish(恢复 virtual-guest 档)。
9.2 Reviewing RAID Fundamentals(RAID 基础复习)
- RAID 概念:多盘组合为单一逻辑存储单元,提升性能/冗余/容错,支持单盘故障不中断不丢数;用若干廉价盘替代单块又大又贵的盘。RHEL8 默认 chunk=512 KiB,数据拆成小块分布到各盘。
- 三大数据策略:
- 条带化 striping:数据分条分布多盘,多盘并行取数提升吞吐,无冗余。
- 镜像 mirroring:条带至少写两份,单盘故障可从另一份继续服务;RAID1 读吞吐比最快单盘还慢些,写吞吐必然更慢(每盘都写、由最慢盘决定)。
- 奇偶校验 parity:给条带附加校验位,可用工作数据+校验重建同一数据卷丢失的条带。
- 常用级别:RAID0=条带化无冗余、吞吐提升;RAID1=镜像、冗余但双写降速;RAID4=块级条带+专用校验盘;RAID5=块级条带+分布式校验、冗余但重建时间长;RAID6=双重分布式校验、缓解 RAID5 单盘重建窗口风险;RAID10=镜像条带集合、可承受多盘丢失、性能充足。
- SSD 组 RAID 的调优:硬件 RAID 用最新固件(新版对 SSD 支持更好);硬件阵列的 write cache/read ahead 缓存对 SSD 无益,一般应关闭 write behind 与 read ahead;SSD 预留 spare area(出厂坏块替换区)越大随机写越强——可用部分容量组 RAID 来扩大预留比例;让厂商提供合适的 SMART 属性便于健康监控;定期做一致性检查。
- mdadm 软件 RAID(Multiple Disk and Device Administration):
- 建:
mdadm -C /dev/md0 -l raid0 -n 2 /dev/vd[b-c]1(RAID 就绪后各盘不可再直接访问)。 - 拆:先
mdadm --stop /dev/md0停阵列 →mdadm --remove /dev/md0移除 → 逐盘mdadm --zero-superblock /dev/vdb(superblock 是 mdadm 标记 RAID 成员盘的头部,不清掉盘仍被识别为阵列盘)。 - RHEL8 也可用 Web Console 管理软件 RAID。
- 建:
- 条带单元与宽度对齐(重点):条带阵列上文件系统元数据若不对齐,一次写请求可能让每盘写两次,或全部元数据落到一盘成热点。建文件系统时就按阵列布局对齐:
- XFS:需知 chunk 大小、总盘数、校验盘数 → 数据盘数=总盘数−校验盘数;
mkfs -t xfs -d su=<chunk>,sw=<数据盘数>(su=stripe unit、sw=stripe width 数据盘数)。示例(6 盘 RAID6,chunk 64k):mkfs -t xfs -d su=64k,sw=4 /dev/san/lun1。 - ext4:需文件系统块大小+chunk+总盘数+校验盘数 → 算 stride(一个 chunk 容纳的 fs 块数:4KiB 块+64KiB chunk → 64/4=16)与 stripe-width(一条 stripe 的数据块数:6 盘 RAID6 减 2 校验盘=4 数据盘 → 4×16=64);
mkfs -t ext4 -E stride=16,stripe-width=64 /dev/san/lun1。
- XFS:需知 chunk 大小、总盘数、校验盘数 → 数据盘数=总盘数−校验盘数;
- LVM 上的 RAID:LVM LV 可用 PV 作 RAID 盘,支持 RAID0/1/4/5/6/10。建 N 条带的 RAID LV 时,LVM 建 N 个数据子卷(subvolume),带奇偶的类型再加校验子卷,且每个数据/校验子卷各配一个元数据子卷。示例(3 PV 的 raidvg 建 3 条带 RAID0 3GiB LV):
lvcreate --type raid0 -L 3G -n raidlv raidvg。lvconvert可把非 RAID LV 转成 RAID LV。
9.2 GE(lab: storage-raid)
servera:先在 vda 上 fio 写测基线(WRITE bw≈20.1 MiB/s,io=1024MiB、run≈51s)→ 用 parted /dev/vdb mklabel gpt+parted -a optimal /dev/vdb mkpart primary 0% 100%(vdc 同样)+partx -uv 刷新分区表 → mdadm -C /dev/md0 -l raid0 -n 2 /dev/vd[b-c]1 → mdadm --detail /dev/md0 确认 Chunk Size=512K → mkfs -t xfs -d su=512k,sw=2 /dev/md0 → mkdir /raid+mount /dev/md0 /raid → 重测写入(同样 fio,文件放 /raid/testfile)WRITE bw≈23.1 MiB/s、run 降到≈44.4s(“Note the increase in the data writing rate”,环境不同数值会变)→ lab storage-raid finish(清除 vdb/vdc 上的 RAID0)。
9.3 Selecting I/O Analysis Tools(I/O 分析工具选型)
- 故障定位思路:存储问题常表现为 load average 高(Linux 负载含磁盘等待)而 CPU us 低、wa 高达 90%+;应用可能用的是 SAN/NAS,响应看起来正常。先在存储服务端做通用测试确认正常,再回到客户端用 per 设备工具定位:受影响的是哪块盘、是哪个进程(如疯狂写日志)。
- iostat(sysstat 套件):
iostat -x扩展报表(每设备 r/s、w/s、await、aqu-sz、%util 等);-d限制只看指定设备(如iostat -xd vda)。输出首行=开机以来均值,之后各行按命令给定间隔的每秒统计。%util 超过 100% 说明该盘可能有问题/是 I/O 瓶颈。 - iotop:把 I/O 统计与正在做 I/O 的进程/线程关联(TID/PRIO/磁盘读写/SWAPIN/IO>)。
-o(--only)只看当前有 I/O 的、-P(--processes)显示进程级、-a(--accumulated)累计自启动以来的总量。区分瓶颈是磁盘慢还是应用写入方式不可持续(如日志越写越大)。 - blktrace 工具族:观测块 I/O 请求内部事件。
blktrace以二进制记录每笔 I/O 事件(-d指定设备)→blkparse解析二进制 →btt生成聚合统计,核心是 Q2c(queue-to-completion:含等待的 I/O 总时间)与 D2c(device-to-completion:设备服务时间);blkiomon从 blktrace 输出生成每设备请求大小与延迟。 - PCP 存储工具(比同名 sysstat 工具更强):
pcp-atop(atop 的 PCP 移植版):列出做 I/O 的进程与所用带宽,区分 total(块设备驱动读写总量)与 actual(真实硬件 I/O)——差值即文件系统缓存造成的,-d只看磁盘相关;长于总结每间隔系统变化。pmiostat:实时本地盘 I/O 统计,-h远程主机、-a回放 PCP 归档、-R <正则>过滤匹配的设备;默认只报 SCSI 设备,-x dm看 device-mapper 逻辑设备、-x noidle去掉空闲设备。参考:KB“Side-by-side comparison of PCP tools with legacy tools”、RH 文章“Introduction to storage performance analysis with PCP”。
9.3 GE(lab: storage-analysis)
servera:装 iotop、sysstat(提供 iostat)、pcp-system-tools → iotop 看进程级 I/O → iostat 找有负载的盘(vda)→ iostat -xd vda 看扩展统计(r/s、w/s、await、%util 等)→ 启 pmcd(systemctl enable --now pmcd)→ pmiostat -R vda 实时抓 vda → pcp-atop -d 看每进程磁盘 I/O 与系统摘要 → lab storage-analysis finish(清工具)。
Lab 概要(lab: storage-review)
serverb:① ssh+sudo -i;② fio 随机写测 vda 延迟基线(clat avg≈262585 usec);③ 建 reduce-latency 自订档(继承 latency-performance、sysfs 设 fifo_batch=1);④ 启用并 cat 校验;⑤ 重测确认延迟下降(≈215404 usec);⑥ 用 vdb/vdc 建 RAID0(GPT 分区+mdadm);⑦ 在 /dev/md0 上建 XFS(su=512k,sw=2)挂 /raid;⑧ fio 写 /raid/testfile 看 WRITE bw 提升 → lab storage-review grade 评分、lab storage-review finish 收尾。
命令速查表
| 用途 | 命令 |
|---|---|
| 查看/切换调度器 | cat /sys/block/vda/queue/scheduler([mq-deadline] kyber bfq none);echo none > /sys/block/<dev>/queue/scheduler(NVMe 不可改) |
| 调度器参数 | ls /sys/block/vda/queue/iosched(mq-deadline:fifo_batch/front_merges/read_expire/write_expire/writes_starved) |
| 旧调度器 | 引导参数 scsi_mod.use_blk_mq=0(启用 deadline/cfq/noop) |
| tuned 存储档 | [main] include=latency-performance;[sysfs] /sys/block/vda/queue/iosched/fifo_batch=1;tuned-adm profile reduce-latency |
| fio 基准 | fio --name=randwrite --ioengine=libaio --iodepth=1 --rw=randwrite --bs=4k --direct=1 --size=512M --numjobs=2 --group_reporting --filename=/tmp/testfile |
| RAID 建/查 | mdadm -C /dev/md0 -l raid0 -n 2 /dev/vd[b-c]1;mdadm --detail /dev/md0(看 Chunk Size) |
| RAID 拆 | mdadm --stop /dev/md0;mdadm --remove /dev/md0;mdadm --zero-superblock /dev/vdb |
| 分区对齐 | parted /dev/vdb mklabel gpt;parted -a optimal /dev/vdb mkpart primary 0% 100%;partx -uv /dev/vdb |
| XFS 条带对齐 | mkfs -t xfs -d su=512k,sw=2 /dev/md0(su=chunk,sw=数据盘数) |
| ext4 条带对齐 | mkfs -t ext4 -E stride=16,stripe-width=64 /dev/san/lun1 |
| LVM RAID | lvcreate --type raid0 -L 3G -n raidlv raidvg;lvconvert 转换非 RAID LV |
| 分析工具 | iostat -xd vda;iotop -o -P -a;pcp-atop -d;pmiostat -R vda(-h 远程/-a 归档/-x dm,noidle);blktrace -d /dev/vda→blkparse→btt(Q2c/D2c)、blkiomon |
| 实验/评分 | lab storage-patterns|storage-raid|storage-analysis|storage-review start;lab storage-review grade |
词汇表
| 英文 | 中文 | 速记 |
|---|---|---|
| SSD / HDD | 固态盘/机械盘 | 无寻道无旋转延迟;写寿命有限 |
| blk-mq | 多队列块 I/O 机制 | 多队列多核并行,减锁竞争 |
| mq-deadline / kyber / bfq / none | 四个多队列调度器 | 默认 mq-deadline;NVMe=none 不可改 |
| elevator | 调度器设置项 | tuned disk 插件参数 |
| fifo_batch | 每批操作数 | 小=低延迟,大=高吞吐 |
| direct I/O / page cache | 直接 I/O/页缓存 | direct=1 绕过缓存测真实磁盘 |
| fio / clat | I/O 基准工具/完成延迟 | 关注 clat 的 avg、bw |
| chunk / stripe | 块组/条带 | RHEL8 md 默认 512K |
| su / sw(XFS) | 条带单元/条带宽度 | su=chunk,sw=数据盘数 |
| stride / stripe-width(ext4) | 步距/条带宽度 | 块数口径的条带对齐 |
| mdadm | 软件 RAID 工具 | -C 建/-stop/-remove/-zero-superblock |
| superblock | 超级块 | mdadm 用它识别成员盘 |
| RAID LV subvolume | LVM RAID 子卷 | 数据/校验子卷各带元数据子卷 |
| %util(iostat) | 设备利用率 | >100% 提示问题 |
| iotop | 进程级 I/O 监控 | -o/-P/-a |
| blktrace / blkparse / btt / blkiomon | 块追踪工具族 | Q2c=含等待总时间,D2c=设备服务时间 |
| pcp-atop / pmiostat | PCP 存储工具 | total vs actual 区分缓存;-R 正则过滤 |
自测 10 题
- RHEL8 默认 I/O 调度器?四个多队列调度器各适合什么?(mq-deadline 默认;kyber 吞吐敏感/SSD;bfq 交互/慢盘;none 快速随机设备/NVMe)
- NVMe 的调度器能改吗?(默认 none,不能改)
- mq-deadline 如何防饿死?(读/写双到期队列+按扇区第三队列)
- fio 测磁盘真实性能为什么必须 --direct=1?(否则走 page cache 测到内存速度)
- --ioengine=libaio --iodepth=N 与 direct 的关系?(异步必须 direct=1)
- 六盘 RAID6、chunk 64KiB、4KiB 块的 ext4,stride 与 stripe-width?(stride=16;stripe-width=4×16=64)
- XFS 的 su/sw 含义?(su=阵列 chunk;sw=数据盘数=总盘数−校验盘数)
- mdadm 拆除阵列的正确顺序?(stop→remove→逐盘 zero-superblock)
- 判断存储瓶颈的典型 top 信号?(load 高但 us 低、wa 高)
- btt 的 Q2c 与 D2c 分别统计什么?(Q2c=入队到完成=等待+服务;D2c=到设备到完成=服务时间)
