Linux性能优化之磁盘优化

Posted Go_小易

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Linux性能优化之磁盘优化相关的知识,希望对你有一定的参考价值。

前言

关于本章内容,设计的东西比较多。这里会有关于文件系统、磁盘、CPU等方面的知识,以及涉及到关于这方面的性能排查等。

术语

文件系统通过缓存和缓冲以及异步I/O等手段来缓和磁盘的延时对应用程序的影响。为了更详细的了解文件系统,以下就简单介绍一些相关术语:

  • 文件系统:一种把数据组织成文件和目录的存储方式,提供了基于文件的存取接口,并通过文件权限控制访问。另外,一些表示设备、套接字和管道的特殊文件类型,以及包含文件访问时间戳的元数据。
  • 文件系统缓存:主存(通常是DRAM) 的一块区域,用来缓存文件系统的内容,可能包含各种数据和元数据。
  • 操作:文件系统的操作是对文件系统的请求,包括读、写、打开、关闭、创建以及其他操作。
  • I/O:输入/输出。文件系统I/O有多种定义,这里仅指直接读写(执行I/O)的操作,包括读、写、状态统计、创建。I/O不包括打开文件和关闭文件。
  • 逻辑I/O:由应用程序发给文件系统的I/O。
  • 物理I/O:由文件系统直接发给磁盘的I/O。
  • 吞吐量:当前应用程序和文件系统之间的数据传输率,单位是B/S。
  • inode:一个索引节点时一种含有文件系统对象元数据的数据结构,其中有访问权限、时间戳以及数据指针。
  • VFS:虚拟文件系统,一个为了抽象与支持不同文件系统类型的内核接口。

磁盘相关术语:

  • 存储设备的模拟。在系统看来,这是一块物理磁盘,但是,它可能由多块磁盘组成。
  • 传输总线:用来通信的物理总线,包括数据传输以及其他磁盘命令。
  • 扇区:磁盘上的一个存储块,通常是512B的大小。
  • I/O:对于磁盘,严格地说仅仅指读、写,而不包括其他磁盘命令。I/O至少由方向(读或写)、磁盘地址(位置)和大小(字节数)组成。
  • 磁盘命令:除了读写之外,磁盘还会被指派执行其他非数据传输的命令(例如缓存写回)。
  • 带宽:存储传输或者控制器能够达到的最大数据传输速率。
  • I/O延时:一个I/O操作的执行时间,这个词在操作系统领域广泛使用,早已超出了设备层。

相关概念

  文件系统延时
       文件系统延时是文件系统性能一项主要的指标,指的是一个文件系统逻辑请求从开始到结束的时间。它包括消耗在文件系统、内核磁盘I/O子系统以及等待磁盘设备——物理I/O的时间。应用程序的线程通常在请求时阻塞,等地文件系统请求的结束。这种情况下,文件系统的延时与应用程序的性能直接和成正比关系。在某些情况下,应用程序并不受文件系统的直接影响,例如非阻塞I/O或者I/O由一个异步线程发起。

  缓存

       文件系统启动之后会使用主存(RAM)当缓存以提供性能。缓存大小随时间增长而操作系统的空余内存不断减小,当应用程序需要更多内存时,内核应该迅速从文件系统缓存中释放一些内存空间。文件系统用缓存(caching)提高读性能,而用缓冲(buffering)提高写性能。文件系统和块设备子系统一般使用多种类型的缓存。

  随机I/O与顺序I/O
        一连串的文件系统逻辑I/O,按照每个I/O的文件偏移量,可以分为随机I/O与顺序I/O。顺序I/O里每个I/O都开始于上一个I/O结束的地址。随机I/O则找不出I/O之间的关系,偏移量随机变化。随机的文件系统负载也包括存取随机的文件。由于存储设备的某些性能特征的缘故,文件系统一直以来在磁盘上顺序和连续的存放文件数据,以努力减小随机I/O的数目。当文件系统未能达到这个目标时,文件的摆放变得杂乱无章,顺序的逻辑I/O被分解成随机的物理I/O,这种情况被称为碎片化。

提示:关于文件系统更多内容,还请自行查阅相关理论。比如你还需要了解文件系统的预读、预取、写回缓存、同步写、裸I/O、直接I/O、内存映射文件、元数据等相关知识。

性能分析

具备背景知识是分析性能问题时需要了解的。比如硬件 cache;再比如操作系统内核。应用程序的行为细节往往是和这些东西互相牵扯的,这些底层的东西会以意想不到的方式影响应用程序的性能,比如某些程序无法充分利用 cache,从而导致性能下降。比如不必要地调用过多的系统调用,造成频繁的内核 / 用户切换等。如果想深入了解Linux系统,建议购买相关书籍进行系统的学习。下面我们介绍如何分析磁盘性能工具(其实准确来说,不只是磁盘):

iostat

汇总了单个磁盘的统计信息,为磁盘负载、使用率和饱和度提供了指标。默认显示一行系统总结信息,包括内核版本、主机名、日志、架构和CPU数量等,每个磁盘设备都占一行。

[[email protected] ~]# iostat 
Linux 3.10.0-514.el7.x86_64 (localhost.localdomain) 	2017年09月18日 	_x86_64_	(1 CPU)

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           0.74    0.00    1.24    1.35    0.00   96.67

Device:            tps    kB_read/s    kB_wrtn/s    kB_read    kB_wrtn
sda              14.43       456.85        60.82     218580      29098
scd0              0.02         0.09         0.00         44          0
dm-0             13.65       404.58        56.50     193571      27030
dm-1              0.27         2.23         0.00       1068          0

参数说明

  • tps: 每秒事物数(IOPS)。
  • kB_read/s、kB_wrtn/s: 每秒读取KB数和每秒写入KB数。
  • kB_read、kB_wrtn: 总共读取和写入的KB数。

如下想输出更详细的内容,可以试试下面这个命令组合:

[[email protected] ~]# iostat -xkdz 1
Linux 3.10.0-514.el7.x86_64 (localhost.localdomain) 	2017年09月18日 	_x86_64_	(1 CPU)

Device:         rrqm/s   wrqm/s     r/s     w/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
sda               0.01     2.43   13.81    2.32   510.51    67.96    71.74     0.22   13.94    8.72   44.95   2.37   3.82
scd0              0.00     0.00    0.03    0.00     0.10     0.00     8.00     0.00    0.27    0.27    0.00   0.27   0.00
dm-0              0.00     0.00   10.52    4.73   452.10    63.13    67.56     0.44   28.56   10.41   68.93   2.47   3.76
dm-1              0.00     0.00    0.30    0.00     2.49     0.00    16.69     0.00    1.50    1.50    0.00   1.38   0.04

参数说明

  • rrqm/s:每秒合并放入驱动请求队列的读请求数(当系统调用需要读取数据的时候,VFS将请求发到各个FS,如果FS发现不同的读取请求读取的是相同Block的数据,FS会将这个请求合并Merge)。
  • wrqm/s:每秒合并放入驱动请求队列的写请求数。
  • rsec/s:每秒发给磁盘设备的读请求数。
  • wsec/:每秒发给磁盘设备的写请求数。
  • rKB/s:每秒从磁盘设备读取的KB数。
  • wKB/s:每秒向磁盘设备写入的KB数。
  • avgrq-sz 平均每次请求大小,单位为扇区(512B)。
  • avgqu-sz 在驱动请求队列和在设备中活跃的平均请求数。
  • await: 平均I/O响应时间,包括在驱动请求队列里等待和设备的I/O响应时间(ms)。一般地系统I/O响应时间应该低于5ms,如果大于10ms就比较大了。这个时间包括了队列时间和服务时间,也就是说,一般情况下,await大于svctm,它们的差值越小,则说明队列时间越短,反之差值越大,队列时间越长,说明系统出了问题。
  • svctm:磁盘设备的I/O平均响应时间(ms)。如果svctm的值与await很接近,表示几乎没有I/O等待,磁盘性能很好,如果await的值远高于svctm的值,则表示I/O队列等待太长系统上运行的应用程序将变慢。
  • %util: 设备忙处理I/O请求的百分比(使用率)。在统计时间内所有处理IO时间,除以总共统计时间。例如,如果统计间隔1秒,该设备有0.8秒在处理IO,而0.2秒闲置,那么该设备的%util = 0.8/1 = 80%,所以该参数暗示了设备的繁忙程度。一般地,如果该参数是100%表示设备已经接近满负荷运行了(当然如果是多磁盘,即使%util是100%,因为磁盘的并发能力,所以磁盘使用未必就到了瓶颈)。

      既然avgrq-sz是合并之后的数字,小尺寸(16个扇区或者更小)可以视为无法合并的实际I/O负载的迹象。大尺寸有可能是大I/O,或者是合并的连续负载。输出性能里最重要的指标是await。如果应用程序和文件系统使用了降低写延时的方法,w_await可能不那么重要,而更应该关注r_await。
      对于资源使用和容量规划,%util仍然很重要,不过记住这只是繁忙度的一个度量(非空闲时间),对于后面有多块磁盘支持的虚拟设备意义不大。可以通过施加负载更好地了解这些设备:IOPS(r/s + w/s)以及吞吐量(rkB/s + wkB/s)。

iotop

包含磁盘I/O的top工具。

批量模式(-b)可以提供滚动输出。下面的演示仅仅显示I/O进程(-o),每5秒输出一次(-d5):

[[email protected] ~]# iotop -bod5
Total DISK READ :       0.00 B/s | Total DISK WRITE :       8.76 K/s
Actual DISK READ:       0.00 B/s | Actual DISK WRITE:      24.49 K/s
  TID  PRIO  USER     DISK READ  DISK WRITE  SWAPIN      IO    COMMAND
21203 be/3 root        0.00 B/s  815.58 B/s  0.00 %  0.01 % [jbd2/dm-2-8]
22069 be/3 root        0.00 B/s    0.00 B/s  0.00 %  0.01 % [jbd2/dm-1-8]
 1531 be/0 root        0.00 B/s    6.37 K/s  0.00 %  0.01 % [loop0]
 3142 be/4 root        0.00 B/s    0.00 B/s  0.00 %  0.01 % [kworker/7:0]
21246 be/4 root        0.00 B/s 1631.15 B/s  0.00 %  0.00 % java -Djava.util.logging.config.file=/usr/local/tomcat/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -Djava.endorsed.dirs=/usr/local/tomcat/endorsed -classpath /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar -Dcatalina.base=/usr/local/tomcat -Dcatalina.home=/usr/local/tomcat -Djava.io.tmpdir=/usr/local/tomcat/temp org.apache.catalina.startup.Bootstrap start

提示:

        输出显示java进程正在以大约1631.15 B/s的速率施加磁盘写负载。其他有用的选项有-a,可以输出累计I/O而不是一段时间内的平均值,选项-o,只打印那些正在执行的磁盘I/O的进程。

  当然显示磁盘的命令还有例如sar、iosnoop、perf、blktrace等命令,这里只列举常用命令即可。

性能调优

文件系统优化

关于文件系统优化,并没有太多的内容需要说明。就目前的情况,Redhat Enterprise 7系列默认更换为性能更好的XFS,这也是由于XFS在性能表现确实很好的原因。在我们使用的过程中,建议对XFS做一些简单的优化即可,比如执行格式化时指定额外的一些参数,挂载该分区时指定一些额外的挂载参数,这些都能够提高文件系统的相关性能。

格式化时的参数:

mkfs.xfs -d agcount=256 -l size=128m,lazy-count=1,version=2 /dev/diska1

mount时的参数:

defaults,noatime,nodiratime,nobarrier,discard,allocsize=256m,logbufs=8,attr2,logbsize=256k

磁盘相关优化

  • 操作系统可调参数

  包括ionice、资源控制和内核可调参数。

  ionice

  Linux中的ionice命令可以设置一个进程I/O调度级别和优先级。调度级别为整数,0表示无,不指定级别,内核会挑选一个默认值,优先级根据进程nice值选定;1表示实时,对磁盘的最高级别访问,如果误用会导致其他进程饿死;2表示尽力,默认调度级别,包括优先级 0~7,0为最高级;3表示空闲,在一段磁盘空闲的期限过后才允许进行I/O。如下:

ionice -c 3 -p 65552

    cgroup

  通过cgroup为进程或进程组提供存储设备资源控制机制。一般很少用到,不用考虑。

    可调参数

  /sys/block/sda/queue/scheduler:选择I/O调度器策略,是空操作、最后期限、an还是cfq;

  • 磁盘设备可调参数

  Linux上的hdparm(磁盘测试工具)工具可以设置多种磁盘设备的可调参数。

  • 磁盘控制器可调参数

  

 




以上是关于Linux性能优化之磁盘优化的主要内容,如果未能解决你的问题,请参考以下文章

linux性能优化实战-磁盘子系统优化

Elasticsearch性能调优之磁盘读写性能优化

linux性能优化cpu 磁盘IO MEM

linux性能优化思路工具案例

性能优化之基础资源cpu&内存(JVM)

Linux性能优化实战:Linux 磁盘I/O是怎么工作的(上)(24)