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:虚拟文件系统,一个为了抽象与支持不同文件系统类型的内核接口。

【文章福利】小编推荐自己的Linux内核技术交流群: 【977878001】整理一些个人觉得比较好得学习书籍、视频资料共享在群文件里面,有需要的可以自行添加哦!!!前100进群领取,额外赠送一份 价值699的内核资料包(含视频教程、电子书、实战项目及代码)

Linux性能优化之磁盘优化_第1张图片

内核资料直通车:Linux内核源码技术学习路线+视频教程代码资料

学习直通车:Linux内核源码/内存调优/文件系统/进程管理/设备驱动/网络协议栈

磁盘相关术语:

存储设备的模拟。在系统看来,这是一块物理磁盘,但是,它可能由多块磁盘组成。

传输总线:用来通信的物理总线,包括数据传输以及其他磁盘命令。

扇区:磁盘上的一个存储块,通常是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数量等,每个磁盘设备都占一行。

[root@localhost ~]# 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数。

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

[root@localhost ~]# 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):

[root@localhost ~]# 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(磁盘测试工具)工具可以设置多种磁盘设备的可调参数。

磁盘控制器可调参数

由于各种的I/O负载情形各异,Linux系统中文件系统的缺省配置一般来说都比较中庸,强调普遍适用性。然而在特定应用下,这种配置往往在I/O性能方面不能达到最优。因此,如果应用对I/O性能要求较高,除了采用性能更高的硬件(如磁盘、HBA卡、CPU、MEM等)外,我们还可以通过对文件系统进行性能调优,来获得更高的I/O性能提升。总的来说,主要可以从三个方面来做工作:

1、Disk相关参数调优

2、文件系统本身参数调优

3、文件系统挂载(mount)参数调优

当然,负载情况不同,需要结合理论分析与充分的测试和实验来得到合理的参数。下面以SAS(Serial attached SCSI)磁盘上的EXT3文件系统为例,给出Linux文件系统性能优化的一般方法。请根据自身情况作适合调整,不要生搬硬套。

1、Disk相关参数

1.1 Cache mode:启用WCE=1(Write Cache Enable), RCD=0(Read Cache Disable)模式

sdparm -s WCE=1, RCD=0 -S /dev/sdb

1.2 Linux I/O scheduler算法

经过实验,在重负载情形下,deadline调度方式对squidI/O负载具有更好的性能表现。其他三种为noop(fifo), as, cfq,noop多用于SAN/RAID存储系统,as多用于大文件顺序读写,

cfq适于桌面应用。

echo deadline > /sys/block/sdb/queue/scheduler

1.3 deadline调度参数

对于redhat linux建议 read_expire = 1/2 write_expire,对于大量频繁的小文件I/O负载,应当这两者取较小值。更合适的值,需要通过实验测试得到。

echo 500 > /sys/block/sdb/queue/iosched/read_expire

echo 1000 > /sys/block/sdb/queue/iosched/write_expire

1.4 readahead 预读扇区数

预读是提高磁盘性能的有效手段,目前对顺序读比较有效,主要利用数据的局部性特点。比如在我的系统上,通过实验设置通读256块扇区性能较优。

blockdev --setra 256 /dev/sdb

2、EXT3文件系统参数

2.1 block size = 4096 (4KB)

mkfs.ext3 -b指定,大的数据块会浪费一定空间,但会提升I/O性能。EXT3文件系统块大小可以为1KB、2KB、4KB。

2.2 inode size

这是一个逻辑概念,即一个inode所对应的文件相应占用多大物理空间。mkfs.ext3 -i指定,可用文件系统文件大小平均值来设定,可减少磁盘寻址和元数据操作时间。

2.3 reserved block

mkfs.ext3 -m指定,缺省为5%,可调小该值以增大部分可用存储空间。

2.4 disable journal

对数据安全要求不高的应用(如web cache),可以关闭日志功能,以提高I/O性能。

tune2fs -O^has_journal /dev/sdb

3、mount参数

3.1 noatime, nodirtime

访问文件目录,不修改访问文件元信息,对于频繁的小文件负载,可以有效提高性能。

3.2 async

异步I/O方式,提高写性能。

3.3 data=writeback (if journal)

日志模式下,启用写回机制,可提高写性能。数据写入顺序不再保护,可能会造成文件系统数据不一致性,重要数据应用慎用。

3.4 barrier=0 (if journal)

barrier=1,可以保证文件系统在日志数据写入磁盘之后才写commit记录,但影响性能。重要数据应用慎用,有可能造成数据损坏。

小结

以/dev/sdb为例,优化操作方法如下,参数请自行调整。

sdparm -s WCE=1, RCD=0 -S /dev/sdb

echo deadline > /sys/block/sdb/queue/scheduler

echo 500 > /sys/block/sdb/queue/iosched/read_expire

echo 1000 > /sys/block/sdb/queue/iosched/write_expire

blockdev --setra 256 /dev/sdb

mkfs.ext3 -b 4096 -i 16384 -m 2 /dev/sdb1

tune2fs -O^has_journal /dev/sdb1

mount /dev/sdb1 /cache1 -o defaults,noatime,nodirtime,async,data=writeback,barrier=0 (if with journal)

mount /dev/sdb1 /cache1 -o defaults,noatime,nodirtime,async (if without journal)


Linux性能优化之磁盘优化_第2张图片

你可能感兴趣的:(linux,性能优化,运维)