关于Linux性能调优中IO调优的一些笔记

2023-01-30 15:38:09 浏览数 (1)

写在前面

  • 和小伙伴分享一些Linux IO优化的笔记,内容很浅,可以用作入门
  • 博文内容结合《Linux性能优化》读书笔记整理
  • 涉及内容包括
    • 使用vmstat 统计系统内磁盘分区I/O的性能
    • 使用iostat 分析磁盘分区的饱和度,利用率,读写速率。
    • 使用lsof 确定哪些进程正在使用一组给定的文件,从而确认进行磁盘IO的进程
  • 食用方式:
    • 需要了解Linux基础,存储相关知识
  • 理解不足小伙伴帮忙指正

「 总感觉当下的生活不是想要的,总感觉一路走下去会是一个讨厌的未来,每天睁眼的一瞬间就是懊悔,昨天又浪费掉了...人生没有意义,但是要努力寻找活着的意义--------山河已无恙」


性能工具:磁盘I/O

在Linux中,我们可以通过一些性能工具评估磁盘I/O子系统的使用情况。展示那些磁盘或分区已被使用,每个磁盘处理了多少I/O,发给这些磁盘的I/O请求要等多久才被处理。

磁盘I/O介绍

在学习性能工具之前,我们来了解Linux磁盘I/O系统是怎样构成的。

大多数现代Linux系统都有一个或多个磁盘驱动。SCSI驱动则常常被命名为sda、sdb、sdc等。

代码语言:javascript复制
┌──[root@vms81.liruilongs.github.io]-[/]
└─$lsblk
NAME   MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sda      8:0    0  200G  0 disk
|-sda1   8:1    0  150G  0 part /
`-sda2   8:2    0   10G  0 part

磁盘通常要分为多个分区,分区设备名称的创建方法是在基础驱动名称的后面直接添加分区编号。

一般每个独立分区要么包含一个文件系统,要么包含一个交换分区。当然也可以是一个VDO卷,分区被挂载到Linux文件系统,由/etc/fstab指定。

在Linux 中,我们可以直接对磁盘进行分区,使用文件系统格式化,也使用LVM的方式来使用管理磁盘,大多数情况下,是通过LVM来管理Linux存储。利用LVM,化零为整,可以对数据卷进行统一分配,动态扩容。关于LVM(PV,VG,LV),感兴趣小伙伴可以看看我之前的博文。

分区或者逻辑卷被指定文件系统格式化后,挂载目录。即可存放应用程序要读写的文件。

当一个应用程序进行读写时,Linux内核可以在其高速缓存或缓冲区中保存文件的副本,并且可以在不访问磁盘的情况下返回被请求的信息。但是,如果Linux内核没有在内存中保存数据副本,那它就向磁盘 I/O 队列添加一个请求。

若Linux内核注意到多个请求都指向磁盘内相邻的区域,它会把它们合并为一个大的请求。这种合并能消除第二次请求的寻道时间, 以此来提高磁盘整体性能。

当请求被放入磁盘队列,而磁盘当前不忙时,它就开始为IO请求服务。如果磁盘正忙,则请求就在队列中等待,直到该设备可用,请求将被服务。这里的等待,即我们在编程中讲的IO阻塞,尤其在涉及的并发的问题中,我们常常要考虑线程I/O阻塞情况来调整线程优先级,Java在JDK1.4 的版本中,提供NIO(采用内存映射文件的方式处理,将文件或文件的一段区域映射到内存中)来提高访问效率。

磁盘I/O性能工具

vmstat

vmstat是一个强大的工具,它能给出系统在性能方面的总览图。除了CPU和内存统计信息之外,vmstat还可以提供系统整体上的I/O性能情况。

我们用的版本

代码语言:javascript复制
┌──[root@vms81.liruilongs.github.io]-[/]
└─$vmstat  -V
vmstat from procps-ng 3.3.10
┌──[root@vms81.liruilongs.github.io]-[/]
└─$which vmstat
/usr/bin/vmstat

vmstat超过其他I/O工具的主要优势是:几乎所有的Linux发行版本都包含该工具。同时 vmstat提供的扩展磁盘统计信息只用于内核版本高于2.5.70的Linux系统

磁盘I/O性能相关的选项和输出

在使用vmstat从系统获取磁盘1/0统计信息时,要按照如下方式进行调用:

vmstat [-D] [-d] [-p partition] [interval [count]]

命令行选项

选项

描述

-D

显示Linux I/O子系统总的统计数据。它可以让你很好地了解你的IO子系统是如何被使用的,但它不会给出单个磁盘的统计数据。显示的统计数据是从系统启动.开始的总信息,而不是两次采样之间的发生量

-d

按每interval一个样本的速率显示单个磁盘的统计数据。这些统计信息是从系统启动开始的总信息,而不是两次采样之间的发生量

-p partition

按照每interval一个采样的速率显示给定分区的性能统计数据。这些统计信息是从系统启动开始的总信息,而不是两次采样之间的发生量

interval

采样之间的时间间隔

count

所取的样本总数

整个系统的IO统计数据

在用-D模式运行时, vmstat提供的是系统内磁盘10系统的总体统计数据。

代码语言:javascript复制
┌──[root@vms81.liruilongs.github.io]-[/]
└─$vmstat -D
            1 disks
            2 partitions
        14661 total reads
           33 merged reads
      3369384 read sectors
        16091 milli reading
       521150 writes
         5093 merged writes
      5189564 written sectors
       110797 milli writing
            0 inprogress IO
           86 milli spent IO

参数

说明

disks

系统中的磁盘总数

partitions

系统中的分区总数

total reads

读请求总数

merged reads

为了提升性能而被合并的不同读请求数量,这些读请求访问的是磁盘上的相邻位置

read sectors

从磁盘读取的扇区总数(一个扇区通常为512字节)

milli reading

磁盘读所花费的时间(以毫秒为单位)

writes

写请求的总数

merged writes

为了提升性能而被合并的不同写请求数量,这些写请求访问的是磁盘上的相邻位置

written sectors

向磁盘写入的扇区总数(一个扇区通常为512字节)

milli writing

磁盘写所花费的时间(以毫秒为单位)

inprogress IO

当前正在处理的10总数。请注意,最近版本(v3.2)的vmstat在这里有个漏洞,除以1000时其结果是错误的,几乎总是得到。

milli spent IO

等待1/0完成所花费的毫秒数。请注意,最近版本(v3.2)的vmstat在这里有个漏洞,其数值为1/0花费的秒数,而非毫秒数

整个系统的IO性能情况

如果你在运行vmstat时只使用了[interval]和[count]参数,其他参数没有使用,那么显示的就是默认输出。该输出中包含了三列与磁盘1/0性能相关的内容: bo, bi和wa。

代码语言:javascript复制
┌──[root@vms81.liruilongs.github.io]-[/]
└─$vmstat  1 2
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 1  0      0 243708   2072 1748600    0    0    13    21   55  107  2  3 95  0  0
 0  0      0 242768   2072 1748604    0    0     0    32 3352 5026  4  3 93  0  0
┌──[root@vms81.liruilongs.github.io]-[/]
└─$

列名

说明

bo

表示前次间隔中被写入磁盘的总块数(vmstat内磁盘的典型块大小为1024字节)

bi

表示前次间隔中从磁盘读出的块数(vmstat内磁盘的典型块大小为1024字节)

wa

表示等待1/0完成所消耗的CPU时间。每秒写磁盘块的速率

使用vmstat取样3个样本,时间间隔为1秒

代码语言:javascript复制
┌──[root@vms81.liruilongs.github.io]-[/]
└─$vmstat 1 3
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 1  0      0 209244   2072 1751828    0    0    13    20   88  160  2  3 95  0  0
 0  0      0 209040   2072 1751828    0    0     0    12 3182 4760  2  3 95  0  0
 0  0      0 209028   2072 1751828    0    0     0    58 3053 4668  2  3 96  0  0
┌──[root@vms81.liruilongs.github.io]-[/]
└─$

我们可以看到,在第一秒的时候,io读取13块,写入了20块,第二读取0,写入12块,磁盘块的大小为1024字节,即系统读取速率为13/1024,等待IO的时间为O,说明当前系统IO读写空闲

每个磁盘的统计信息

vmstat的-d选项显示的是每一个磁盘的I/O统计信息。这些统计数据与-D选项的数据类似

代码语言:javascript复制
┌──[root@vms81.liruilongs.github.io]-[/]
└─$vmstat  -d
disk- ------------reads------------ ------------writes----------- -----IO------
       total merged sectors      ms  total merged sectors      ms    cur    sec
sda    14661     33 3369384   16091 523799   5120 5213233  111242      0     86

统计数据

说明

reads:total

读请求的总数

reads:merged

为了提升性能而被合并的不同读请求数量,这些读请求访问的是磁盘上的相邻位置

reads:sectors

从磁盘读取的扇区总数

reads:ms

磁盘读所花费的时间(以毫秒为单位)

writes:total

写请求的总数

writes:merged

为了提升性能而被合并的不同写请求数量,这些写请求访问的是磁盘上的相邻位置

writes:sectors

向磁盘写人的扇区总数(一个扇区通常为512字节)

writes:ms

磁盘写所花费的时间(以毫秒为单位)当前正在处理的I/O总数

IO:cur

当前正在处理的I/O总数。

10:sec

等待1/0完成所花费的秒数

代码语言:javascript复制
[root@foundation0 ~]# vmstat -d 1 2
disk- ------------reads------------ ------------writes----------- -----IO------
       total merged sectors      ms  total merged sectors      ms    cur    sec
nvme0n1  72865      5 6560405   54580 138514   1015 6715558   94026      0    149
sr0        0      0       0       0      0      0       0       0      0      0
loop0     49      0    2308      10      0      0       0       0      0      0
loop1     93      0   19822     146      0      0       0       0      0      0
loop2     77      0    3764      20      0      0       0       0      0      0
loop3     88      0   20882      73      0      0       0       0      0      0
loop4    463      0   64058    1904      0      0       0       0      0      0
nvme0n1  72865      5 6560405   54580 138514   1015 6715558   94026      0    149
sr0        0      0       0       0      0      0       0       0      0      0
loop0     49      0    2308      10      0      0       0       0      0      0
loop1     93      0   19822     146      0      0       0       0      0      0
loop2     77      0    3764      20      0      0       0       0      0      0
loop3     88      0   20882      73      0      0       0       0      0      0
loop4    463      0   64058    1904      0      0       0       0      0      0
[root@foundation0 ~]#
统计磁盘分区的读写情况
代码语言:javascript复制
┌──[root@vms81.liruilongs.github.io]-[/]
└─$vmstat -p sda1 1 3
sda1          reads   read sectors  writes    requested writes
               15036    3381024     545880    5414724
               15036    3381024     545894    5414837
               15036    3381024     545895    5414846

上面我们可以看到,对于sda1物理分区来讲,有14(545880-545894)个写提交了

虽然vmstat提供了单个磁盘/分区的统计信息,但是它只给出其总量,却不给出在采样过程中的变化率。因此,要分辨哪个设备的统计数据在采样期间发生了明显的变化就显得很困难。

iostat

iostat与vmstat相似,但它是一个专门用于显示磁盘1/0子系统统计信息的工具。

iostat提供的信息细化到每个设备和每个分区从特定磁盘读写了多少个块。(iostat中块大小一般为512字节。)

此外,iostat还可以提供大量的信息来显示磁盘是如何被利用的,以及Linux花费了多长时间来等待将请求提交到磁盘。

磁盘I/O性能相关的选项和输出

iostat用如下命令行调用:

iostat [-d] [-k] [-x] [devicel] [interval[count]]

与vmstat很相似,iostat可以定期显示性能统计信息。

选项

说明

-d

只显示磁盘I/O的统计信息,而不是默认信息。默认信息中还包括了CPU使用情况

-k

按KB显示统计数据,而不是按块显示

-x

显示扩展性能I/O统计信息

device

若指定设备,则iostat只显示该设备的信息

interval

采样间隔时间

count

获取的样本总数

iostat设备统计信息

代码语言:javascript复制
┌──[root@vms81.liruilongs.github.io]-[/]
└─$iostat
Linux 3.10.0-693.el7.x86_64 (vms81.liruilongs.github.io)        06/14/22        _x86_64_        (2 CPU)

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           2.42    0.00    2.94    0.01    0.00   94.63

Device:            tps    kB_read/s    kB_wrtn/s    kB_read    kB_wrtn
sda               8.18        24.59        39.45    1694748    2718599

统计数据

说明

tps

每秒传输次数。该项为每秒对设备/分区读写请求的次数

kB_read/s

每秒读取磁盘块的速率

kB_wrtn/s

每秒写入磁盘块的速率

kB_read

在时间间隔内读取块的总数量

kB_wrtn

在时间间隔内写入块的总数量

代码语言:javascript复制
┌──[root@vms81.liruilongs.github.io]-[/]
└─$iostat  -d 1 3
Linux 3.10.0-693.el7.x86_64 (vms81.liruilongs.github.io)        06/14/22        _x86_64_        (2 CPU)

Device:            tps    kB_read/s    kB_wrtn/s    kB_read    kB_wrtn
sda               8.17        24.33        39.40    1694756    2744300

Device:            tps    kB_read/s    kB_wrtn/s    kB_read    kB_wrtn
sda               9.00         0.00        37.00          0         37

Device:            tps    kB_read/s    kB_wrtn/s    kB_read    kB_wrtn
sda               0.00         0.00         0.00          0          0

┌──[root@vms81.liruilongs.github.io]-[/]
└─$

当你使用-x参数调用iostat时,它会显示更多关于磁盘I/O子系统的统计信息。

代码语言:javascript复制
┌──[root@vms81.liruilongs.github.io]-[/]
└─$iostat -x  -dk  1 3 /dev/sda1
Linux 3.10.0-693.el7.x86_64 (vms81.liruilongs.github.io)        06/14/22        _x86_64_        (2 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
sda1              0.00     0.08    0.22    7.96    24.21    39.39    15.57     0.00    0.23    1.10    0.21   0.16   0.13

Device:         rrqm/s   wrqm/s     r/s     w/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
sda1              0.00     0.00    0.00   15.00     0.00    60.00     8.00     0.00    0.27    0.00    0.27   0.27   0.40

Device:         rrqm/s   wrqm/s     r/s     w/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
sda1              0.00     0.00    0.00    8.00     0.00    32.00     8.00     0.00    0.25    0.00    0.25   0.25   0.20

┌──[root@vms81.liruilongs.github.io]-[/]
└─$

iostat的扩展磁盘统计信息

统计数据

说明

rrqm/s

在提交给磁盘前,被合并的读请求的数量

wrqm/s

在提交给磁盘前,被合并的写请求的数量

r/s

每秒提交给磁盘的读请求数量

w/s

每秒提交给磁盘的写请求数量

rsec/s

每秒读取的磁盘扇区数

wsec/s

每秒写入的磁盘扇区数

rkB/s

每秒从磁盘读取了多少KB的数据

wkB/s

每秒向磁盘写入了多少KB的数据

avgrq-sz

磁盘请求的平均大小(按扇区计)

avgqu-sz

磁盘请求队列的平均大小。

await

完成对一个请求的服务所需的平均时间(按毫秒计),该平均时间为请求在磁盘队列中等待的时间加上磁盘对其服务所需的时间

svctm

提交到磁盘的请求的平均服务时间(按毫秒计)。该项表明磁盘完成一个请求所花费的平均时间。与await不同,该项不包含在队列中等待的时间

%util

利用率

当avgqu-sz的值特别大的时候,且请求等待时间await远远高于请求服务svctm所花费时间,且利用率%util为100%的时候,表明该磁盘处于饱和状态。

sar

sar可以收集Linux系统多个不同方面的性能统计信息。除了CPU和内存之外,它还可以收集关于磁盘I/O子系统的信息。

磁盘I/O性能相关的选项和输出

当使用sar 来监视磁盘I/O统计数据时,你可以用如下命令行来调用它:

sar -d [interval [count] ]

通常,sar显示的是系统中CPU使用的相关信息。若要显示磁盘使用情况的统计信息,你必须使用-d选项。sar只能在高于2.5.70的内核版本中显示磁盘I/O统计数据。

显示信息进行了说明。

代码语言:javascript复制
┌──[root@vms81.liruilongs.github.io]-[/]
└─$sar -d 1 3
Linux 3.10.0-693.el7.x86_64 (vms81.liruilongs.github.io)        06/14/22        _x86_64_        (2 CPU)

23:31:21          DEV       tps  rd_sec/s  wr_sec/s  avgrq-sz  avgqu-sz     await     svctm     %util
23:31:22       dev8-0      7.00      0.00     56.00      8.00      0.00      0.29      0.29      0.20

23:31:22          DEV       tps  rd_sec/s  wr_sec/s  avgrq-sz  avgqu-sz     await     svctm     %util
23:31:23       dev8-0      1.00      0.00     10.00     10.00      0.00      0.00      0.00      0.00

23:31:23          DEV       tps  rd_sec/s  wr_sec/s  avgrq-sz  avgqu-sz     await     svctm     %util
23:31:24       dev8-0     12.00      0.00     96.00      8.00      0.00      0.33      0.25      0.30

Average:          DEV       tps  rd_sec/s  wr_sec/s  avgrq-sz  avgqu-sz     await     svctm     %util
Average:       dev8-0      6.67      0.00     54.00      8.10      0.00      0.30      0.25      0.17
┌──[root@vms81.liruilongs.github.io]-[/]
└─$

统计数据

说明

tps

每秒传输数。该项为每秒对设备/分区进行读写的次数

rd_sec/s

每秒读取的磁盘扇区数

wr_sec/s

每秒写入的磁盘扇区数

avgrq-sz

磁盘请求的平均大小(按扇区计)

avgqu-sz

磁盘请求队列的平均大小。

await

完成对一个请求的服务所需的平均时间(按毫秒计),该平均时间为请求在磁盘队列中等待的时间加上磁盘对其服务所需的时间

svctm

提交到磁盘的请求的平均服务时间(按毫秒计)。该项表明磁盘完成一个请求所花费的平均时间。与await不同,该项不包含在队列中等待的时间

%util

利用率

lsof(列出打开文件)

1sof提供了一种方法来确定哪些进程打开了一个特定的文件。除了跟踪单个文件的用户外,lsof还可以显示使用了特定目录下文件的进程。同时,它还可以递归搜索整个目录树,并列出使用了该目录树内文件的进程。在要筛选哪些应用程序产生了I/O时,lsof是很有用的。

磁盘I/O性能相关的选项和输出

你可以使用如下命令行调用lsof来找出进程打开了哪些文件:

1sof [-r delay] [ D directory] [ d directory] [file]

代码语言:javascript复制
┌──[root@vms81.liruilongs.github.io]-[/]
└─$yum -y install  lsof

通常,lsof显示的是使用给定文件的进程。但是,通过使用 d和 D选项,它可以显示多个文件的相关信息。表6-10解释了1sof的命令行选项,它们可用于追踪I/O性能问题。

sof 命令行选项

选项

说明

-r delay

使得1sof每间隔delay秒输出一次统计数据

D directory

使得1sof递归搜索给定目录下的所有文件,并报告哪些进程正在使用它们

d directory

使得1sof报告哪些进程正在使用给定目录下的文件

代码语言:javascript复制
┌──[root@vms81.liruilongs.github.io]-[/]
└─$lsof  -r 2  D /usr/bin/
COMMAND      PID USER  FD   TYPE DEVICE  SIZE/OFF      NODE NAME
dbus-daem    539 dbus txt    REG    8,1    442080 268592945 /usr/bin/dbus-daemon
VGAuthSer    544 root txt    REG    8,1    128488 268979997 /usr/bin/VGAuthService
vmtoolsd     545 root txt    REG    8,1     48976 268980000 /usr/bin/vmtoolsd
firewalld    636 root txt    REG    8,1      7136 268591652 /usr/bin/python2.7
tuned        951 root txt    REG    8,1      7136 268591652 /usr/bin/python2.7
kubelet      957 root txt    REG    8,1 153350040 270317939 /usr/bin/kubelet
container    961 root txt    REG    8,1  48766984 268964765 /usr/bin/containerd
dockerd     1073 root txt    REG    8,1  96765968 268963237 /usr/bin/dockerd
container   1735 root txt    REG    8,1   8617984 268592410 /usr/bin/containerd-shim-runc-v2
container   1782 root txt    REG    8,1   8617984 268592410 /usr/bin/containerd-shim-runc-v2
container   1853 root txt    REG    8,1   8617984 268592410 /usr/bin/containerd-shim-runc-v

统计数据

说明

COMMAND

打开该文件的命令的名称

PID

打开该文件的命令的PID

USER

打开文件的用户

FD

该文件的描述符。txt表示可执行文件,mem表示内存映射文件TYPE文件类型,REG表示常规文件

DEVICE

用主设备号和次设备号表示的设备编号

SIZE

文件的大小

NODE

文件的索引节点

可以通过DEVICE来查看对应的设备位置

代码语言:javascript复制
┌──[root@vms81.liruilongs.github.io]-[/]
└─$ls -la /dev/ | grep sd
brw-rw----   1 root disk      8,   0 Jun 12 14:58 sda
brw-rw----   1 root disk      8,   1 Jun 12 14:58 sda1
brw-rw----   1 root disk      8,   2 Jun 12 14:58 sda2
┌──[root@vms81.liruilongs.github.io]-[/]
└─$

当我们通过前面的命令确定了饱和的磁盘设备。那么我们可以通过lsof来根据磁盘找到对应的文件,从而确认对应的PID

0 人点赞