linux性能评估-磁盘io概念理解篇

摘要:
索引节点,简称为inode,用来记录文件的元数据,比如inode编号、文件大小、访问权限、修改日期、数据的位置等。下面这张图是Linux文件系统的架构图,帮你更好地理解系统调用、VFS、缓存、文件系统以及块存储之间的关系。

1.Linux 文件系统的工作原理

1.索引节点和目录项

在 Linux 中一切皆文件。不仅普通的文件和目录,就连块设备、套接字、管道等,也都要通过统一的文件系统来管理。
为了方便管理,Linux 文件系统为每个文件都分配两个数据结构,索引节点(index node)和目录项(directory entry)。它们主要用来记录文件的元信息和目录结构。

  • 索引节点,简称为 inode,用来记录文件的元数据,比如 inode 编号、文件大小、访问权限、修改日期、数据的位置等。索引节点和文件一一对应,它跟文件内容一样,都会被持久化存储到磁盘中。所以记住,索引节点同样占用磁盘空间。
  • 目录项,简称为 dentry,用来记录文件的名字、索引节点指针以及与其他目录项的关联关系。多个关联的目录项,就构成了文件系统的目录结构。不过,不同于索引节点,目录项是由内核维护的一个内存数据结构,所以通常也被叫做目录项缓存。

2.虚拟文件系统

虚拟文件系统VFS 定义了一组所有文件系统都支持的数据结构和标准接口。这样,用户进程和内核中的其他子系统,只需要跟 VFS 提供的统一接口进行交互就可以了,而不需要再关心底层各种文件系统的实现细节。
下面这张图是Linux 文件系统的架构图,帮你更好地理解系统调用、VFS、缓存、文件系统以及块存储之间的关系。

linux性能评估-磁盘io概念理解篇第1张

通过这张图,你可以看到,在 VFS 的下方,Linux 支持各种各样的文件系统,如 Ext4、XFS、NFS 等等。按照存储位置的不同,这些文件系统可以分为三类。

  • 第一类是基于磁盘的文件系统,也就是把数据直接存储在计算机本地挂载的磁盘中。常见的 Ext4、XFS、OverlayFS 等,都是这类文件系统。
  • 第二类是基于内存的文件系统,也就是我们常说的虚拟文件系统。这类文件系统,不需要任何磁盘分配存储空间,但会占用内存。我们经常用到的 /proc 文件系统,其实就是一种最常见的虚拟文件系统。此外,/sys 文件系统也属于这一类,主要向用户空间导出层次化的内核对象。
  • 第三类是网络文件系统,也就是用来访问其他计算机数据的文件系统,比如 NFS、SMB、iSCSI 等。

3.文件系统 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 与非直接 I/O。

  • 直接 I/O,是指跳过操作系统的页缓存,直接跟文件系统交互来访问文件。
  • 非直接 I/O 正好相反,文件读写时,先要经过系统的页缓存,然后再由内核或额外的系统调用,真正写入磁盘。

想要实现直接 I/O,需要你在系统调用中,指定 O_DIRECT 标志。如果没有设置过,默认的是非直接 I/O。
不过要注意,直接 I/O、非直接 I/O,本质上还是和文件系统交互。如果是在数据库等场景中,你还会看到,跳过文件系统读写磁盘的情况,也就是我们通常所说的裸 I/O。
第三,根据应用程序是否阻塞自身运行,可以把文件 I/O 分为阻塞 I/O 和非阻塞 I/O:

  • 所谓阻塞 I/O,是指应用程序执行 I/O 操作后,如果没有获得响应,就会阻塞当前线程,自然就不能执行其他任务。
  • 所谓非阻塞 I/O,是指应用程序执行 I/O 操作后,不会阻塞当前的线程,可以继续执行其他的任务,随后再通过轮询或者事件通知的形式,获取调用的结果。

比方说,访问管道或者网络套接字时,设置 O_NONBLOCK 标志,就表示用非阻塞方式访问;而如果不做任何设置,默认的就是阻塞访问。
第四,根据是否等待响应结果,可以把文件 I/O 分为同步和异步 I/O:

  • 所谓同步 I/O,是指应用程序执行 I/O 操作后,要一直等到整个 I/O 完成后,才能获得 I/O 响应。
  • 所谓异步 I/O,是指应用程序执行 I/O 操作后,不用等待完成和完成后的响应,而是继续执行就可以。等到这次 I/O 完成后,响应会用事件通知的方式,告诉应用程序。

4.性能观测

容量
对文件系统来说,最常见的一个问题就是空间不足。当然,你可能本身就知道,用 df 命令,就能查看文件系统的磁盘空间使用情况。比如:

df -h /dev/sda1
Filesystem Size Used Avail Use% Mounted on
/dev/sda1 20G 6.4G 13G 35% /

不过有时候,明明你碰到了空间不足的问题,可是用 df 查看磁盘空间后,却发现剩余空间还有很多。这是怎么回事呢?

#给 df 命令加上 -i 参数,查看索引节点的使用情况
df -i /dev/sda1
Filesystem Inodes IUsed IFree IUse% Mounted on
/dev/sda1 1310720167343114337713% /

索引节点的容量,(也就是 Inode 个数)是在格式化磁盘时设定好的,一般由格式化工具自动生成。当你发现索引节点空间不足,但磁盘空间充足时,很可能就是过多小文件导致的。所以,一般来说,删除这些小文件,或者把它们移动到索引节点充足的其他磁盘中,就可以解决这个问题。
缓存
在前面 Cache 案例中,我已经介绍过,可以用 free 或 vmstat,来观察页缓存的大小。free 输出的 Cache,是页缓存和可回收 Slab 缓存的和,你可以从 /proc/meminfo ,直接得到它们的大小:

cat /proc/meminfo |grep -E "SReclaimable|Cached"
Cached: 431680kB
SwapCached: 27780kB
SReclaimable: 88540kB

文件系统中的目录项和索引节点缓存,又该如何观察呢?
比如,运行下面的命令,你就可以得到,所有目录项和各种文件系统索引节点的缓存情况:

cat /proc/slabinfo | grep -E '^#|dentry|inode'
# name : tunables : slabdata
ovl_inode 282282688478: tunables 000: slabdata 660
mqueue_inode_cache 6868960348: tunables 000: slabdata 220
fuse_inode 7878832398: tunables 000: slabdata 220
ecryptfs_inode_cache 001024328: tunables 000: slabdata 000
fat_inode_cache 00744448: tunables 000: slabdata 000
squashfs_inode_cache 1152311638704468: tunables 000: slabdata 2532530
ext4_inode_cache 23845276001088308: tunables 000: slabdata 9209200
hugetlbfs_inode_cache 102102632518: tunables 000: slabdata 220
sock_inode_cache 39904278704468: tunables 000: slabdata 93930
shmem_inode_cache 23072668712468: tunables 000: slabdata 58580
proc_inode_cache 48525232680488: tunables 000: slabdata 1091090
inode_cache 2206723956608538: tunables 000: slabdata 4524520
dentry 6891288074192422: tunables 000: slabdata 209720970

这个界面中,dentry 行表示目录项缓存,inode_cache 行,表示 VFS 索引节点缓存,其余的则是各种文件系统的索引节点缓存。
在实际性能分析中,我们更常使用 slabtop ,来找到占用内存最多的缓存类型。

slabtop

linux性能评估-磁盘io概念理解篇第2张

2.Linux 磁盘 IO 的工作原理

1.磁盘

磁盘是可以持久化存储的设备,根据存储介质的不同,常见磁盘可以分为两类:机械磁盘和固态磁盘。

  • 第一类,机械磁盘,也称为硬盘驱动器(Hard Disk Driver),通常缩写为 HDD。机械磁盘主要由盘片和读写磁头组成,数据就存储在盘片的环状磁道中。在读写数据前,需要移动读写磁头,定位到数据所在的磁道,然后才能访问数据。
  • 第二类,固态磁盘(Solid State Disk),通常缩写为 SSD,由固态电子元器件组成。固态磁盘不需要磁道寻址,所以,不管是连续 I/O,还是随机 I/O 的性能,都比机械磁盘要好得多。

其实,无论机械磁盘,还是固态磁盘,相同磁盘的随机 I/O 都要比连续 I/O 慢很多,原因也很明显。

  • 对机械磁盘来说,由于随机 I/O 需要更多的磁头寻道和盘片旋转,它的性能自然要比连续 I/O 慢。
  • 而对固态磁盘来说,虽然它的随机性能比机械硬盘好很多,但同样存在“先擦除再写入”的限制。随机读写会导致大量的垃圾回收,所以相对应的,随机 I/O 的性能比起连续 I/O 来,也还是差了很多。
  • 此外,连续 I/O 还可以通过预读的方式,来减少 I/O 请求的次数,这也是其性能优异的一个原因。很多性能优化的方案,也都会从这个角度出发,来优化 I/O 性能。


2.通用块层

通用块层,其实是处在文件系统和磁盘驱动中间的一个块设备抽象层。它主要有两个功能 。

  • 第一个功能跟虚拟文件系统的功能类似。向上,为文件系统和应用程序,提供访问块设备的标准接口;向下,把各种异构的磁盘设备抽象为统一的块设备,并提供统一框架来管理这些设备的驱动程序。
  • 第二个功能,通用块层还会给文件系统和应用程序发来的 I/O 请求排队,并通过重新排序、请求合并等方式,提高磁盘读写的效率。


3.I/O 栈

我们可以把 Linux 存储系统的 I/O 栈,由上到下分为三个层次,分别是文件系统层、通用块层和设备层。
存储系统 I/O 的工作原理:

  • 文件系统层,包括虚拟文件系统和其他各种文件系统的具体实现。它为上层的应用程序,提供标准的文件访问接口;对下会通过通用块层,来存储和管理磁盘数据。
  • 通用块层,包括块设备 I/O 队列和 I/O 调度器。它会对文件系统的 I/O 请求进行排队,再通过重新排序和请求合并,然后才要发送给下一级的设备层。
  • 设备层,包括存储设备和相应的驱动程序,负责最终物理设备的 I/O 操作。

4.磁盘性能指标

说到磁盘性能的衡量标准,必须要提到五个常见指标,也就是我们经常用到的,使用率、饱和度、IOPS、吞吐量以及响应时间等。这五个指标,是衡量磁盘性能的基本指标。

  • 使用率,是指磁盘处理 I/O 的时间百分比。过高的使用率(比如超过 80%),通常意味着磁盘 I/O 存在性能瓶颈。
  • 饱和度,是指磁盘处理 I/O 的繁忙程度。过高的饱和度,意味着磁盘存在严重的性能瓶颈。当饱和度为 100% 时,磁盘无法接受新的 I/O 请求。
  • IOPS(Input/Output Per Second),是指每秒的 I/O 请求数。
  • 吞吐量,是指每秒的 I/O 请求大小。
  • 响应时间,是指 I/O 请求从发出到收到响应的间隔时间。

这里要注意的是,使用率只考虑有没有 I/O,而不考虑 I/O 的大小。换句话说,当使用率是 100% 的时候,磁盘依然有可能接受新的 I/O 请求。
4.1磁盘 I/O 观测
第一个要观测的,是每块磁盘的使用情况。
iostat 的输出界面如下。

-d -x 表示显示所有磁盘 I/O 的指标
$ iostat -d -x 1
Linux 4.18.0-15-generic (ubuntu) 02/26/2019_x86_64_ (2CPU)
Device r/s w/s rkB/s wkB/s rrqm/s wrqm/s %rrqm %wrqm r_await w_await aqu-sz rareq-sz wareq-sz svctm %util
loop0 0.000.000.010.000.000.000.000.001.630.000.003.730.001.850.00
loop1 0.000.000.000.000.000.000.000.000.330.000.002.530.000.570.00
loop2 0.000.000.000.000.000.000.000.003.120.000.001.910.002.830.00
loop3 0.050.000.070.000.000.000.000.000.710.000.001.500.000.240.00
loop4 0.020.000.030.000.000.000.000.000.180.000.001.350.000.260.00
loop5 0.020.000.040.000.000.000.000.000.240.000.002.230.000.290.00
loop6 0.000.000.010.000.000.000.000.001.210.000.004.070.001.580.00
loop7 0.680.000.700.000.000.000.000.000.690.000.001.030.000.050.00
sda 74.812.3553938.75142.554.5910.915.7882.307.0134.690.69721.0360.770.262.04
loop8 0.010.000.030.000.000.000.000.000.200.000.003.060.000.210.00
loop9 0.010.000.020.000.000.000.000.000.090.000.001.690.000.130.00

iostat指标解读:

linux性能评估-磁盘io概念理解篇第3张

这些指标中,你要注意:

  • %util ,就是我们前面提到的磁盘 I/O 使用率;
  • r/s+ w/s ,就是 IOPS;
  • rkB/s+wkB/s ,就是吞吐量;
  • r_await+w_await ,就是响应时间。

在观测指标时,也别忘了结合请求的大小( rareq-sz 和 wareq-sz)一起分析。

4.2.进程 I/O 观测
上面提到的 iostat 只提供磁盘整体的 I/O 性能数据,缺点在于,并不能知道具体是哪些进程在进行磁盘读写。要观察进程的 I/O 情况,你还可以使用 pidstat 和 iotop 这两个工具。

$ pidstat -d 1
13:39:51UID PID kB_rd/s kB_wr/s kB_ccwr/s iodelay Command
13:39:521029160.004.000.000rsyslogd

从 pidstat 的输出你能看到,它可以实时查看每个进程的 I/O 情况,包括下面这些内容。

  • 用户 ID(UID)和进程 ID(PID) 。
  • 每秒读取的数据大小(kB_rd/s) ,单位是 KB。
  • 每秒发出的写请求数据大小(kB_wr/s) ,单位是 KB。
  • 每秒取消的写请求数据大小(kB_ccwr/s) ,单位是 KB。
  • 块 I/O 延迟(iodelay),包括等待同步块 I/O 和换入块 I/O 结束的时间,单位是时钟周期。

除了可以用 pidstat 实时查看,根据 I/O 大小对进程排序,也是性能分析中一个常用的方法。这一点,我推荐另一个工具, iotop。它是一个类似于 top 的工具,你可以按照 I/O 大小对进程排序,然后找到 I/O 较大的那些进程。

iotop 的输出如下所示:

linux性能评估-磁盘io概念理解篇第4张

从这个输出,你可以看到,前两行分别表示,进程的磁盘读写大小总数和磁盘真实的读写大小总数。因为缓存、缓冲区、I/O 合并等因素的影响,它们可能并不相等。

免责声明:文章转载自《linux性能评估-磁盘io概念理解篇》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇X窗口系统的协议和架构LVS配置下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

安卓手机清缓存方式

1,安卓手机清除缓存访问:debugx5.qq.com 2, 安卓手机清除缓存三步走:1、点击 debugtbs.qq.com 后退出;2、点击 debugmm.qq.com/?forcex5=true 后退出;3、访问 debugx5.qq.com,在这个页面清除缓存;...

网络基础 -(4)Linux下的网络分析

目录 netstat 命令 参数 命令的格式和详细参数 常用参数 常用命令示例 列出所有端口 列出所有处于监听状态的sockets 显示协议的统计信息 显示 PID 和进程名称 显示关于以太网的统计数据 输出信息 man netstat 基本信息 常见使用场景 统计端口、状态 服务器存在大量TIME_WAIT 服务器端大量E...

一种memory问题导致的kernel panic的处理方法

下面是一个在kernel panic或者oops之后,能够打印更多内存信息的patch,主要用到前面介绍的die notify功能注册oops/painc回调函数。 #include <linux/mm.h> #include <linux/spinlock.h> #include <linux/slab.h> #inc...

linux路由表配置

一、原理说明 1、路由表(table)从0到255进行编号,每个编号可以对应一个别名,编号和别名的对应关系在linux下放在/etc/iproute2/rt_tables这个文件里,一般0编号的table对应的别名为upspec,255编号对应的别名为local,254和253对应的别名分别为main和default,我们通常用route命令配置和查看的...

zookeeper(二):linux centos下安装zookeeper(单机和集群)

下载 http://zookeeper.apache.org/releases.html 解压 tar –zxvf zookeeper-3.4.6.tar.gz 解压文件到"/usr/local/zookeeper-3.4.6". 复制conf目录下的zoo_sample.cfg,并命名为zoo.cfg 修改zoo.cfg配置文件 # The number...

Linux 之不同运维人员共用root 账户权限审计

一、为什么?   在中小型企业,公司不同运维人员基本都是以root 账户进行服务器的登陆管理,缺少了账户权限审计制度。不出问题还好,出了问题,就很难找出源头。   这里介绍下,如何利用编译bash 使不同的客户端在使用root 登陆服务器使,记录各自的操作,并且可以在结合ELK 日志分析系统,来收集登陆操作日志 二、环境   服务器:centos 6.5...