Skip to content

Linux I/O 性能详解 ​

I/O(Input/Output)性能问题通常表现为:应用响应变慢、请求延迟升高、CPU 使用率不高但 Load Average 很高、磁盘吞吐达到上限、系统频繁进入 I/O wait,或者数据库出现大量慢查询。

I/O 性能优化不能只看某一个指标。一个完整的分析过程应该回答以下问题:

  1. 当前是读 I/O、写 I/O,还是读写混合?
  2. 瓶颈位于应用、文件系统、块设备、存储介质,还是网络存储?
  3. 当前主要受吞吐量、IOPS、延迟、队列深度还是带宽限制?
  4. I/O 是顺序访问还是随机访问?请求大小是否合理?
  5. 是设备真的繁忙,还是应用在锁、内存回收、网络或 CPU 上等待?
  6. 修改参数后,性能是否改善,是否引入了数据安全风险?

本文以 Linux 服务器为背景,从 I/O 路径、性能指标、工具使用和实战排查几个方面进行说明。

一、Linux I/O 路径 ​

一次普通文件读取并不是应用直接从磁盘读取数据,而是经过多个层次:

text
应用程序
   │ read / pread / readv / mmap
   ▼
系统调用层
   │
   ▼
VFS(虚拟文件系统)
   │
   ├── Page Cache(页缓存)
   │       ├── 命中:直接返回内存中的数据
   │       └── 未命中:向文件系统发起读取
   │
   ▼
具体文件系统(ext4 / XFS / Btrfs ...)
   │
   ▼
块层(bio / request / I/O scheduler)
   │
   ▼
设备驱动
   │
   ▼
物理设备(HDD / SSD / NVMe / SAN / 网络盘)

写入路径还可能经过 Page Cache、文件系统日志、设备缓存和持久化介质,因此“系统调用返回”不一定等于“数据已经安全落盘”。

1. VFS ​

VFS 为不同文件系统提供统一的接口。应用调用 open()、read()、write()、fsync() 等系统调用时,首先进入 VFS,再由具体文件系统完成后续工作。

VFS 负责抽象出常见对象:

  • inode:文件元数据和数据块索引;
  • dentry:目录项与路径解析缓存;
  • file:进程打开文件后的内核对象;
  • superblock:文件系统整体信息。

2. Page Cache ​

Page Cache 是 Linux 用于缓存文件内容的内存区域。文件第一次读取时,数据通常从设备进入 Page Cache;后续访问如果命中缓存,就不需要再次访问磁盘。

text
第一次读取:磁盘 → Page Cache → 应用
再次读取:  Page Cache → 应用

因此,使用 free 观察到的缓存内存并不一定是“浪费的内存”。Linux 会在需要时回收大部分可回收缓存。

查看内存和缓存:

bash
free -h
cat /proc/meminfo | grep -E 'Cached|Buffers|Dirty|Writeback'

常见字段:

  • Cached:文件页缓存;
  • Buffers:块设备元数据等缓冲区;
  • Dirty:已修改但尚未写回设备的页;
  • Writeback:正在写回设备的页。

3. 块层 ​

当文件系统需要从块设备读取数据时,会把请求组织成 bio,再由块层合并、排序或调度,最终提交给设备驱动。

块层常见影响因素:

  • 请求大小;
  • 请求是否连续;
  • 队列深度;
  • I/O 调度器;
  • 多个进程之间的请求竞争;
  • 设备是否支持并发 I/O。

4. 设备层 ​

设备层是最终执行 I/O 的地方。不同介质的能力差异很大:

介质典型特点常见瓶颈
HDD顺序吞吐尚可,随机访问延迟高寻道、随机 IOPS
SATA SSD延迟低于 HDD,带宽受 SATA 限制SATA 带宽、写放大、垃圾回收
NVMe SSD高并发、低延迟、高 IOPSPCIe 带宽、队列、温度、介质写入寿命
SAN / NAS通过网络或存储网络访问网络延迟、共享存储竞争、服务端队列
云盘由云平台提供虚拟块设备IOPS/吞吐配额、突发额度、租户竞争

二、I/O 性能的核心指标 ​

1. 吞吐量 ​

吞吐量表示单位时间传输的数据量,通常以 MB/s 或 GB/s 表示。

text
吞吐量 = 单位时间完成的字节数

吞吐量适合衡量大文件顺序读写、日志批量写入、备份归档、数据导入导出以及视频或大对象传输。

吞吐量高不代表延迟低。一个设备可能在顺序读时达到很高吞吐量,但随机小块读的延迟仍然很高。

2. IOPS ​

IOPS(Input/Output Operations Per Second)表示每秒完成的 I/O 操作次数。

text
IOPS ≈ 吞吐量 / 单次 I/O 大小

例如,设备以 100 MB/s 处理 4 KB 请求时:

text
100 × 1024 KB / 4 KB ≈ 25,600 IOPS

IOPS 常用于数据库、键值存储和小文件服务等随机访问场景。

3. 延迟 ​

延迟是一次 I/O 从提交到完成所经历的时间,通常以微秒或毫秒表示。需要区分应用端延迟、系统调用延迟、块设备延迟和网络存储服务延迟。

平均延迟可能掩盖长尾问题。生产环境更应该关注 P95、P99 或 P99.9 延迟。

4. 队列深度 ​

队列深度表示同时等待处理的 I/O 请求数量。队列深度过低,设备并行能力没有被利用;队列深度过高,则可能导致延迟上升。

对于 NVMe 和云盘等高并发设备,适当的队列深度可以提高吞吐量;对于延迟敏感服务,盲目增加队列深度可能适得其反。

5. 利用率 ​

%util 表示设备在采样期间处于处理 I/O 状态的时间比例。它可以帮助判断设备是否繁忙,但不能简单地认为 %util=100% 就代表设备已经无法继续处理请求。

现代多队列设备可以在 %util 接近 100% 时仍有较好的吞吐能力,因此还应结合 await、aqu-sz、IOPS、吞吐量和应用延迟共同判断。

6. I/O wait ​

%iowait 表示 CPU 空闲期间,系统中存在未完成 I/O 的时间比例。它不是“CPU 正在等待磁盘”的精确计时器。

高 I/O wait 通常说明系统中存在 I/O 等待,但不一定能证明某个进程就是根因。需要配合进程级工具、设备级工具和系统调用跟踪进一步定位。

三、顺序 I/O 与随机 I/O ​

1. 顺序 I/O ​

顺序 I/O 的访问位置连续或接近连续,设备可以减少寻址和合并请求的开销,适合大文件读取、备份恢复、日志追加写入和批量导入导出。

顺序 I/O 更容易达到设备的最大吞吐量。

2. 随机 I/O ​

随机 I/O 的访问位置分散,设备需要处理更多寻址、队列和元数据操作,常见于数据库索引访问、键值存储、小文件读取和多进程并发访问。

随机 I/O 通常更受延迟和 IOPS 限制,而不是单纯受 MB/s 限制。

3. 请求大小的影响 ​

请求大小过小会增加系统调用、队列和元数据开销;请求大小过大则可能增加单次延迟、内存占用和无效数据读取。

请求大小应根据业务访问模式选择:

  • 小块随机读:关注延迟和 IOPS;
  • 大块顺序读:关注吞吐量;
  • 混合读写:关注尾延迟、队列和读写隔离;
  • 数据库场景:以数据库实际页面大小和工作负载为准。

四、使用工具定位 I/O 问题 ​

1. iostat:设备级总览 ​

iostat 来自 sysstat 软件包,适合查看设备吞吐、IOPS、利用率和平均等待时间。

bash
# Debian / Ubuntu
sudo apt-get install sysstat

# RHEL / CentOS / Rocky Linux
sudo dnf install sysstat

iostat -xz 1

常见字段:

字段含义
r/s每秒完成的读请求数
w/s每秒完成的写请求数
rkB/s每秒读取的 KB 数
wkB/s每秒写入的 KB 数
awaitI/O 请求平均等待时间,通常包含队列时间
aqu-sz平均队列长度
%util设备忙碌时间比例
r_await读请求平均等待时间
w_await写请求平均等待时间

一个简单判断思路:

  • %util 高、await 高:设备或设备队列可能成为瓶颈;
  • %util 高、await 低:设备可能高效运行,不能仅凭 %util 判定异常;
  • %util 不高、await 高:可能存在设备抖动、网络存储延迟或请求阻塞;
  • 吞吐量低、IOPS 高:可能是大量小块 I/O;
  • 吞吐量高、IOPS 低:通常是大块顺序 I/O。

2. pidstat:进程级 I/O ​

使用 pidstat 可以定位哪些进程正在产生读写:

bash
pidstat -d 1

常见字段:

  • kB_rd/s:每秒从存储设备读取的 KB;
  • kB_wr/s:每秒写入的 KB;
  • kB_ccwr/s:由于写时复制而导致的写入量;
  • iodelay:I/O 延迟相关统计。

如果 iodelay 很高,说明进程的执行时间中有较多时间受到 I/O 延迟影响,但仍需结合系统调用和设备信息确认。

3. iotop:实时观察 I/O 活跃进程 ​

bash
sudo iotop -oPa

参数含义:

  • -o:只显示正在进行 I/O 的进程;
  • -P:按进程显示,而不是按线程显示;
  • -a:显示累计 I/O。

4. vmstat:观察系统整体状态 ​

bash
vmstat 1

重点关注:

  • r:可运行队列;
  • b:不可中断睡眠进程数,常见于等待 I/O;
  • si / so:swap 换入换出;
  • bi / bo:块设备读入和写出;
  • wa:I/O wait;
  • cs:上下文切换。

如果 si/so 持续较高,问题可能不仅是磁盘吞吐不足,也可能是内存压力导致的 swap I/O。

5. sar:查看历史趋势 ​

bash
sar -d 1 10
sar -b 1 10

前提是系统已启用 sysstat 数据采集。历史数据可用于判断 I/O 峰值是否与业务发布时间吻合、是否每天固定时间发生备份竞争,以及设备延迟是否逐步恶化。

6. df 与 df -i:检查空间和 inode ​

bash
df -h
df -i

需要分别检查块空间、inode、单个目录下的小文件数量,以及删除文件后空间是否仍未释放。

删除文件后空间没有立即恢复,常见原因是文件仍被进程打开:

bash
sudo lsof +L1

7. lsof:定位打开文件 ​

bash
sudo lsof /var/log/app.log
sudo lsof +D /var/lib/app 2>/dev/null

lsof 可以帮助确认哪个进程打开了文件、文件是否已删除但仍被进程持有,以及某个挂载点是否仍在使用。

8. strace:定位系统调用级延迟 ​

针对单个进程,可以使用:

bash
sudo strace -f -ttT -p <PID> -e trace=%file,read,write,fsync,fdatasync

参数含义:

  • -f:跟踪子进程和线程;
  • -tt:打印更精确的时间戳;
  • -T:显示每个系统调用耗时;
  • -p:附加到指定进程;
  • -e trace=...:只关注文件和 I/O 相关调用。

重点观察 read()、pread64()、write()、fsync()、fdatasync() 是否耗时较高,以及是否频繁调用 openat()、stat()、fstat()。

生产环境中使用 strace 需要评估性能影响,建议短时间、低采样范围使用。

9. blktrace:块层请求分析 ​

bash
sudo blktrace -d /dev/nvme0n1 -o - | blkparse -i -

blktrace 可以帮助分析请求来源、读写类型、请求大小、连续性、队列等待时间和从提交到完成经过的阶段。它通常用于 iostat、pidstat 和 strace 无法解释问题时。

10. bpftrace / eBPF:动态观测 ​

现代 Linux 可以使用 eBPF 追踪 I/O 延迟和系统调用行为。生产环境建议优先使用经过验证的工具,例如 biolatency、biosnoop、fileslower、filetop,避免自行编写脚本时错误关联设备、请求或并发事件。

五、读 I/O 与写 I/O 的排查思路 ​

1. 读 I/O 问题 ​

读延迟升高时,可以依次检查:

text
应用是否发起了大量读请求
    ↓
Page Cache 命中率是否下降
    ↓
读请求是否过于随机或过小
    ↓
设备读队列是否堆积
    ↓
文件系统和设备延迟是否升高
    ↓
是否存在内存回收或 swap 读写

常见原因包括工作集超过内存、数据库索引不合理、小文件过多、多服务竞争同一设备、网络存储抖动,以及预读参数与访问模式不匹配。

2. 写 I/O 问题 ​

写入延迟升高时,需要重点观察脏页和回写:

bash
cat /proc/meminfo | grep -E 'Dirty|Writeback'
cat /proc/sys/vm/dirty_ratio
cat /proc/sys/vm/dirty_background_ratio

常见原因包括脏页集中回写、fsync() 或 fdatasync() 频繁调用、文件系统日志压力、数据库 checkpoint/WAL 集中写入,以及 SSD 垃圾回收或磨损均衡导致的延迟抖动。

降低写入延迟不能以牺牲数据一致性为代价。数据库、日志和交易系统不能为了“看起来更快”而随意关闭同步写入。

六、文件系统层面的性能因素 ​

1. 挂载参数 ​

查看当前挂载参数:

bash
findmnt -o TARGET,SOURCE,FSTYPE,OPTIONS
mount | column -t

常见参数包括 noatime、relatime、nodiratime、discard、ext4 的 data= 和写屏障相关参数。修改前应确认文件系统类型、内核版本、设备特性和数据安全要求。

2. 文件碎片 ​

机械硬盘和部分文件系统在长期使用后可能出现碎片,影响顺序读写;SSD 的随机访问成本较低,但碎片仍可能增加元数据和请求数量。

bash
sudo filefrag -v large-file

不要在没有评估的情况下直接执行在线碎片整理。生产环境应安排维护窗口,并提前确认备份与回滚方案。

3. inode 与目录结构 ​

大量小文件会带来 inode 消耗、dentry/inode 缓存压力、目录遍历变慢、stat() 操作增加,以及备份和扫描任务变慢。

常见改进方式是使用目录分片、按时间或哈希拆分目录、合并小对象、选择合适的对象存储或键值存储,并定期清理过期文件。

七、I/O 调度器 ​

查看设备当前调度器:

bash
cat /sys/block/sda/queue/scheduler
cat /sys/block/nvme0n1/queue/scheduler

常见调度器包括:

  • none:尽量减少软件层调度,常见于高性能 NVMe;
  • mq-deadline:尝试控制请求延迟,适合部分通用场景;
  • bfq:更强调公平性和交互体验;
  • kyber:通过控制队列实现延迟目标。

临时修改示例:

bash
sudo sh -c 'echo mq-deadline > /sys/block/sda/queue/scheduler'

调度器没有万能最优解。选择前应使用与生产相似的负载进行基准测试,并同时观察吞吐量、尾延迟和其他服务的影响。

八、常用内核参数 ​

1. 脏页回写参数 ​

bash
sysctl vm.dirty_background_ratio
sysctl vm.dirty_ratio
sysctl vm.dirty_background_bytes
sysctl vm.dirty_bytes
sysctl vm.dirty_expire_centisecs
sysctl vm.dirty_writeback_centisecs

这些参数影响脏页何时开始后台回写,以及进程在写入时何时被迫参与回写。阈值过高可能形成突发写入和长尾延迟,阈值过低则可能增加持续回写频率。

2. 预读参数 ​

bash
blockdev --getra /dev/sda
cat /sys/block/sda/queue/read_ahead_kb
sudo blockdev --setra 4096 /dev/sda

顺序读取可以适当增加预读,但随机读取场景下过大的预读会读取大量无用数据,浪费带宽和缓存。

3. 队列参数 ​

bash
cat /sys/block/sda/queue/nr_requests
cat /sys/block/sda/queue/max_sectors_kb
cat /sys/block/sda/queue/nomerges

队列越大不一定越快。过大的队列可能增加等待时间,尤其是在延迟敏感业务中。

九、应用层优化 ​

1. 减少无效 I/O ​

最有效的优化通常不是换更快的磁盘,而是减少根本不需要的 I/O:

  • 避免重复读取相同数据;
  • 使用缓存降低后端读取量;
  • 只读取需要的字段和范围;
  • 避免无条件扫描完整文件;
  • 清理无效日志和重复落盘;
  • 合并小块写入。

2. 缓冲与批量写入 ​

频繁执行小块 write() 会产生较多系统调用和块层请求。可以通过用户态缓冲、批量提交或异步写入合并请求。

但批量写入会增加数据暂存时间和单次失败损失,需要在吞吐量、延迟和可靠性之间平衡。

3. 同步写入 ​

以下操作通常会要求数据或元数据持久化:

  • fsync();
  • fdatasync();
  • O_SYNC;
  • O_DSYNC;
  • 数据库 WAL 或日志提交。

同步写入可能显著提高延迟,但它们往往是数据一致性的组成部分,不能简单删除。

4. mmap 的适用边界 ​

mmap() 可以把文件映射到进程地址空间,适合随机访问和减少显式 read 系统调用的场景,但它并不意味着没有 I/O。缺页时仍然可能触发磁盘读取。

使用 mmap 需要关注工作集大小、缺页长尾、文件增长和截断、多进程共享修改,以及映射区域带来的内存回收压力。

5. 异步 I/O 与 io_uring ​

异步 I/O 可以让应用在提交请求后继续执行,减少同步等待。io_uring 支持提交队列和完成队列,可以减少系统调用次数,但收益取决于应用是否能有效并发提交请求、文件系统和设备是否支持目标操作,以及队列深度是否合理。

十、数据库场景 ​

数据库是典型的 I/O 敏感系统,排查时不能只在操作系统层面看磁盘利用率。

1. 数据文件、日志和临时文件分离 ​

如果条件允许,可以将数据文件、WAL/redo log、临时表空间、备份文件和归档日志放到不同设备或存储池,减少不同 I/O 模式之间的相互干扰。

2. 检查数据库自身指标 ​

应同时观察:

  • buffer pool / shared buffers 命中率;
  • checkpoint 频率和耗时;
  • WAL / redo 写入延迟;
  • 临时文件产生量;
  • 全表扫描数量;
  • 数据库连接和并发请求;
  • 慢查询与执行计划。

如果数据库在没有明显设备瓶颈时仍然延迟升高,根因可能是锁等待、CPU、内存、网络或执行计划,而不是 I/O。

3. 避免用缓存命中率单独下结论 ​

缓存命中率很高并不一定表示系统没有 I/O 问题。少量关键请求可能遇到长尾,写回和 checkpoint 仍可能阻塞,临时文件、日志和元数据 I/O 也可能被忽略。

十一、典型问题分析 ​

场景一:CPU 使用率低,但 Load Average 很高 ​

bash
uptime
vmstat 1
iostat -xz 1
pidstat -d 1

如果 vmstat 中 b 持续较高,同时 iostat 的设备 await 或队列长度明显上升,通常说明大量任务在等待 I/O。若设备指标正常,则继续检查 NFS、D 状态进程、锁竞争、内存回收和驱动错误。

场景二:磁盘 %util 接近 100%,但吞吐不高 ​

可能是大量小块随机 I/O。若 IOPS 高、吞吐量低、请求大小小,优化方向通常是减少随机访问、合并小请求、优化数据库索引、增加缓存或评估更高 IOPS 的设备。

场景三:写入突然导致服务卡顿 ​

可能是脏页达到阈值,进程被迫同步参与回写。建议观察 Dirty、Writeback、设备延迟和写入来源,再评估回写参数,不要直接关闭同步机制。

场景四:删除日志后磁盘空间没有释放 ​

bash
lsof +L1

如果某进程仍打开已删除文件,需要让应用正确关闭并重新打开日志文件,或使用应用支持的日志轮转方式。

场景五:系统出现大量 swap I/O ​

bash
free -h
vmstat 1
iostat -xz 1
sar -W 1 10

重点确认是否内存不足、存在内存泄漏、进程工作集突然增长,以及 swap 是否位于慢设备。单独调低 vm.swappiness 不能替代内存容量和内存泄漏治理。

十二、基准测试方法 ​

任何 I/O 优化都应先建立基线,再进行对照测试。

1. fio 基本示例 ​

顺序读取:

bash
fio --name=seq-read \
  --filename=/data/testfile \
  --size=4G \
  --bs=1M \
  --rw=read \
  --iodepth=16 \
  --direct=1 \
  --runtime=60 \
  --time_based \
  --group_reporting

随机读写:

bash
fio --name=rand-rw \
  --filename=/data/testfile \
  --size=4G \
  --bs=4k \
  --rw=randrw \
  --rwmixread=70 \
  --iodepth=32 \
  --numjobs=4 \
  --direct=1 \
  --runtime=60 \
  --time_based \
  --group_reporting

测试参数含义:

  • --bs:请求块大小;
  • --rw:读写模式;
  • --iodepth:单个作业的队列深度;
  • --numjobs:并发作业数;
  • --direct=1:绕过 Page Cache,测试设备路径;
  • --runtime:运行时间;
  • --group_reporting:合并输出结果。

2. 基准测试注意事项 ​

不要直接在生产数据盘上运行破坏性测试。需要注意:

  • fio 的写测试可能覆盖已有数据;
  • 测试文件可能触发 SSD 垃圾回收和缓存效应;
  • Page Cache 测试与 direct I/O 测试代表不同路径;
  • 测试盘的容量、温度和突发缓存会影响结果;
  • 云盘可能有突发 IOPS 或吞吐额度;
  • 测试期间应同步采集 iostat、应用延迟和设备错误。

十三、I/O 性能优化方法论 ​

第一步:确认现象 ​

先记录故障时间窗口和影响范围:

  • 哪些服务受影响;
  • 读、写还是混合 I/O;
  • 平均延迟和 P99 延迟;
  • 设备吞吐、IOPS、队列和 await;
  • CPU、内存、swap、网络是否异常。

第二步:定位责任主体 ​

使用 pidstat、iotop、lsof 和应用指标确认 I/O 来源。不要仅凭设备满载就认定某个应用有问题。

第三步:判断访问模式 ​

确认读写比例、请求大小、顺序/随机比例、并发度,以及是否存在周期性批任务。

第四步:分层验证 ​

text
应用指标
  → 系统调用
  → 文件系统
  → 块层
  → 设备
  → 存储服务端

每一层都应回答“请求在哪里耗时”,而不是只收集更多指标。

第五步:选择优化手段 ​

优先级通常是:

  1. 删除无效 I/O;
  2. 优化访问模式和数据结构;
  3. 使用缓存和批量处理;
  4. 分离不同业务的 I/O;
  5. 调整文件系统、队列和回写参数;
  6. 升级设备或增加 IOPS/吞吐配额;
  7. 通过横向扩展分散负载。

第六步:验证副作用 ​

优化后必须确认数据一致性、数据丢失窗口、其他服务影响、长尾延迟、峰值稳定性,以及参数重启后是否仍然生效。

十四、常见误区 ​

误区一:%iowait 高就一定是磁盘坏了 ​

I/O wait 只能说明系统存在 I/O 等待,可能来自本地磁盘、网络文件系统、swap、虚拟化存储或驱动层。必须结合设备和进程数据判断。

误区二:%util=100% 就一定要换磁盘 ​

对于现代多队列设备,%util 的解释不能脱离 await、IOPS、吞吐和应用延迟。设备可能处于高效饱和,也可能正在处理大量小请求。

误区三:清 Page Cache 可以解决性能问题 ​

以下命令会丢弃缓存:

bash
sync
echo 3 | sudo tee /proc/sys/vm/drop_caches

这通常只适合测试环境或特定诊断场景,不是生产优化手段。清缓存会导致后续请求重新从设备读取,可能引发更严重的延迟抖动。

误区四:把 noatime 当成万能优化 ​

noatime 可能减少访问时间更新,但收益取决于业务访问模式和文件系统配置。修改挂载参数前还要考虑应用是否依赖访问时间。

误区五:关闭 fsync 就能解决写延迟 ​

关闭同步写入可能降低表面延迟,却会增加断电、崩溃或存储故障时的数据丢失和损坏风险。数据库和关键日志系统不应为了基准成绩随意关闭可靠性机制。

误区六:只跑一次 fio 就代表生产性能 ​

一次基准测试不能代表真实工作负载。生产性能还受到缓存、温度、并发、后台回收、混合读写、云盘额度和文件系统状态影响。

十五、实用排查清单 ​

bash
# 1. 系统总体状态
uptime
vmstat 1
free -h

# 2. 设备级 I/O
iostat -xz 1

# 3. 进程级 I/O
pidstat -d 1
sudo iotop -oPa

# 4. 文件系统容量与 inode
df -h
df -i

# 5. 删除但仍被打开的文件
sudo lsof +L1

# 6. 挂载点和文件系统类型
findmnt -o TARGET,SOURCE,FSTYPE,OPTIONS

# 7. 内核和设备错误
dmesg -T | grep -iE 'error|fail|reset|timeout|I/O'

# 8. 块设备信息
lsblk -o NAME,TYPE,FSTYPE,SIZE,ROTA,SCHED,MOUNTPOINT

十六、总结 ​

Linux I/O 性能问题的本质,是应用产生的访问模式与文件系统、块层、设备和存储服务能力之间出现了不匹配。

排查时建议遵循以下原则:

  1. 先区分读写,再区分顺序和随机;
  2. 同时观察吞吐量、IOPS、延迟和队列,而不是只看一个指标;
  3. 从进程、系统调用、文件系统、块层到设备逐层定位;
  4. 关注 P99 等长尾指标,不要只看平均值;
  5. 优先减少无效 I/O,再考虑调参和升级硬件;
  6. 任何降低同步和持久化保证的优化,都必须明确评估数据风险;
  7. 使用与生产相似的负载进行基准测试,并在修改后验证副作用。

一个稳定的 I/O 优化闭环应该是:

text
发现异常
  → 建立基线
  → 定位 I/O 来源
  → 判断访问模式
  → 分层分析延迟
  → 实施最小改动
  → 对照验证
  → 观察长期趋势

只有当性能指标、应用行为和业务结果同时改善时,才可以认为 I/O 优化真正完成。

最近更新