这篇文章上次修改于 765 天前,可能其部分内容已经发生变化,如有疑问可询问作者。

1 I/O 基准测试

为了更客观合理地评估优化效果,我们首先应该对磁盘和文件系统进行基准测试,得到文件系统或者磁盘 I/O 的极限性能。可通过 blktrace+fio 的组合使用来测试。

2 I/O 性能优化

2.1 应用程序优化

  • 用追加写代替随机写。
  • 可以借助缓存 I/O ,充分利用系统缓存。C 标准库提供的 fopen、fread 等库函数,都会利用标准库的缓存,减少磁盘的操作。而直接使用 open、read 等系统调用时,就只能利用操作系统提供的页缓存和缓冲区等,而没有库函数的缓存可用。
  • 可以在应用程序内部构建自己的缓存,或者用 Redis 这类外部缓存系统。
  • 在需要频繁读写同一块磁盘空间时,可以用 mmap 代替 read/write,减少内存的拷贝次数。
  • 在需要同步写的场景中,尽量将写请求合并,而不是让每个请求都同步写入磁盘,即可以用 fsync() 取代 O_SYNC。
  • 在多个应用程序共享相同磁盘时,为了保证 I/O 不被某个应用完全占用,推荐使用 cgroups 的 I/O 子系统,来限制进程 / 进程组的 IOPS 以及吞吐量。
  • 在使用 CFQ 调度器时,可以用 ionice 来调整进程的 I/O 调度优先级,特别是提高核心应用的 I/O 优先级。

2.2 文件系统优化

  • 根据实际创建选择合适的文件系统。例如相对于 ext4,xfs 支持更大的磁盘分区和更大的文件数量,但无法收缩。
  • 优化文件系统配置项。如文件系统的特性、日志模式、挂载项等。
  • 优化文件系统的缓存。如 pdflush 脏页刷新频率和脏页限额;内核回收目录项缓存和索引节点缓存的倾向;在不需要持久化时,采用内存文件系统 tmpfs 以获得更好的 I/O 性能。

2.3 磁盘优化

  • 换用更好性能的磁盘,如用 SSD 代替 HDD。
  • 使用 RAID,将多个磁盘组合成一个冗余磁盘阵列,提供数据可靠性和访问性能。
  • 针对磁盘和应用程序 I/O 模式特征,选择更合适的 I/O 调度算法。比如,SSD 和虚拟机中的磁盘通过采用 noop 算法,数据库应用通常采用 deadline 算法。
  • 对应用程序的数据,采用磁盘级别的隔离。比如,日志、数据库等 I/O 压力比较重的应用,应单独配置磁盘。
  • 在顺序读比较多的场景中,增大磁盘预读取数据。
  • 优化内核设备 I/O 选项。比如,增大磁盘队列长度,提高吞吐量。
  • 磁盘本出现硬件错误时,及时查看。如查看 dmesg 中是否有 I/O 硬件故障的日志。

参考

倪朋飞. Linux 性能优化实战.