关于操作系统:聊聊磁盘-IO

34次阅读

共计 9771 个字符,预计需要花费 25 分钟才能阅读完成。

常见的磁盘类型

按存储原理的不同,能够把磁盘分为这么几种

  1. HDD 盘:没啥说的,就是平时最常见的机械盘。
  2. SSD 盘:用电信号来记录存储数据,而不是磁片。显然进行 I/O 时,这要比机械盘的物理寻址形式快的多。
  3. HHD 盘:HDD + SSD 的组合模式。
掂量磁盘性能的指标有哪些?

有时咱们发现运行在 Linux 服务器上的某个利用响应很慢,你也不晓得是什么起因,然而就是想看看磁盘 I/O 是不是有问题。除了 I/O 还有没有其余的指标参考呢?答案是 有!

  1. 吞吐量:指的是磁盘每秒解决 I/O 申请总的数据大小。用 TPS 示意,例如 32M/s。
  2. IOPS:每秒解决 I/O 申请的次数。个别咱们在说 IOPS 的时候说的就是磁盘的随机读写性能,这个指标在购买云服务器的时候,厂商会明确的通知你该数据,用来辨别不同云存属性的性能。
  3. 使用率:磁盘解决 I/O 的工夫百分比。过高的使用率 (80%+) 意味着磁盘的 I/O 存在性能瓶颈。
  4. 响应工夫:通过零碎调用内核收回 I/O 申请,到内核收到 I/O 响应破费的工夫,包含 I/O 申请处于 I/O 队列中期待的工夫。

在查找磁盘瓶颈时,这些指标是咱们须要特地关注的。那么,这些指标怎么看?上面我用一个案例说下。

环境筹备
4G , 4c 虚拟机两台,装置了 docker 环境。
S: 10.10.3.56
C: 10.10.3.55

S:# 下载 redis 官网镜像
[root@a ~]# docker pull redis

# 这里我本地 /data 目录下有一个自定义的 redis.conf 配置文件,启动时 mount 到了容器的 /data 目录
[root@a ~]# docker run -itd --name redis -p 6379:6379 -v /data:/data docker.io/redis redis-server /data/redis.conf

在另一台虚拟机写脚本程序向 redis 插入数据。

C:
[root@huiyoujia ~]# ls  # txt 是我结构的 redis 数据文件,sh 脚本读取并插入到对端 Redis 实例
redis_data.txt  request.sh
[root@huiyoujia ~]# sh redis_data.txt >>/dev/null
启动脚本模仿应用程序 I/O 申请

排查问题的时候,咱们把模仿环境的信息忘掉。所有都是未知的,而后一步步进行排查。

一. 从利用的角度解决磁盘 I/O 瓶颈

1. 先 top 一下看看过程信息
[root@a ~]# top
top - 17:55:01 up 36 days,  6:34,  1 user,  load average: 2.55, 0.13, 0.05
Tasks: 104 total,   1 running,  53 sleeping,   0 stopped,   0 zombie
%Cpu0  :  0.0 us,  0.7 sy,  0.0 ni, 15.3 id, 83.7 wa,  0.0 hi,  0.3 si,  0.0 st
%Cpu1  :  0.0 us,  0.0 sy,  0.0 ni,100.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
%Cpu2  :  0.0 us,  0.3 sy,  0.0 ni, 99.7 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
%Cpu3  :  1.3 us,  2.3 sy,  0.0 ni, 91.7 id,  0.0 wa,  0.0 hi,  4.7 si,  0.0 st
KiB Mem :  4039612 total,  3391044 free,   307880 used,   340688 buff/cache
KiB Swap:  2097148 total,  2088688 free,     8460 used.  3422408 avail Mem

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND                                                                 
 5385 systemd+  20   0  207616  18496   3344 D  13.3  0.5   0:14.30 redis-server                                                                           
    1 root      20   0   46192   7184   4600 S   0.0  0.2   0:30.39 systemd                                                                                    
    2 root      20   0       0      0      0 S   0.0  0.0   0:00.44 kthreadd                                                                              
    3 root       0 -20       0      0      0 I   0.0  0.0   0:00.00 rcu_gp                                                                              
    4 root       0 -20       0      0      0 I   0.0  0.0   0:00.00 rcu_par_gp

# top 之后按快捷键 1 查看所有 cpu 的应用状况。top 输入的信息很多,排查 I/O 问题时这些须要重点关注:第一行的  load average  均匀负载  
第三行的  %Cpu(s)
  us 用户态:该值高的时候要排查用户态的过程;sy 内核态:该值高的时候,排查内核态的过程流动,cpu 上下文切换等的状况。id cpu 闲暇工夫百分比:该值很高,阐明你的 cpu 没有什么计算工作,没事干。wa cpu 等待时间百分比:该值很高,阐明 cpu 在期待过程准备就绪花了很多工夫,大量过程如果在期待 IO, 则该值会很高。第六行 
  S: 过程的状态,关注 r 状态的过程
  %CPU %MEM 等标签

查看 top 输入信息,看到 Cpu0 编号的 wa 值 比拟高,达到了 83.7%, 而其余 cpu 则失常,有点可疑。再接着看 过程的 cpu 工夫,发现 除了 pid 是 5385 的过程 cpu 工夫有点高之外,13.3 如同也不是很高,其余过程都很失常。这里先做个标记,pid 是 5385 的过程 应用的是 redis-server 命令,有可能是 redis-server 引起的 wa 值升高。

(记住咱们的初衷是:就是想看看磁盘 I/O 是不是有问题。)
当初既然狐疑是 redis-server 引起的问题,那么就看看零碎磁盘的性能状态。

2. iostat 查看磁盘的状态
[root@a ~]# iostat -d -x 1
Linux 4.18.4-1.el7.elrepo.x86_64 (a.huiyoujia.com)     08/15/2019     _x86_64_    (4 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
scd0              0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
sda               0.00    28.00    0.00   84.00     0.00   444.00    10.57     0.99   10.01    0.00   10.01  11.81  99.20


# -d 查看 磁盘信息;# -x 列出具体的输入信息;# 每隔 1s 刷新一次
iostat 工具除了能查看磁盘状态,还能查看 cpu 等的信息。man iostat 查看具体的应用办法。回忆一下后面提到的掂量磁盘性能的指标。输入信息中心咱们应该重点关注这些:1. rrqm/s:每秒合并读的申请数
2. wrqm/s:每秒合并写的申请数
3. r/s: 每秒读申请的次数
4. w/s: 每秒写申请的次数
5. rkB/s: 每秒读的数据大小
6. wkB/s: 每秒写的数据大小
7. r_await: 实现读申请期待的工夫
8. w_wait: 实现写申请等到的工夫
9. %util: 磁盘的使用率
10. avgqu-sz: 磁盘 i/o 队列的长度

# 1 & 2 在排查 mysql 数据库时能够参考,因为 mysql 合并读写的状况很常见。# 3 & 4 指的是以后磁盘的 IOPS。并不是 最大 iops。# 5 & 6 指的就是磁盘的吞吐量
# 7 & 8 指的是响应工夫
# 9 使用率

当初咱们曾经有了磁盘的性能指标的数据。
通过观察发现 sda 盘的磁盘使用率曾经达到了 99.2%,阐明 sda 盘的确有 I/O 瓶颈。看来咱们的磁盘确实有瓶颈。那么是什么起因或者是零碎执行的什么工作导致的 磁盘使用率升高呢?须要 进一步剖析零碎过程 应用 IO 的 状况。

3. pidstat 查看过程应用系统资源的详细信息
[root@a ~]# pidstat -d 2 5
Linux 4.18.4-1.el7.elrepo.x86_64 (a.huiyoujia.com)     08/15/2019     _x86_64_    (4 CPU)

06:59:11 PM   UID       PID   kB_rd/s   kB_wr/s kB_ccwr/s  Command
06:59:15 PM   UID       PID   kB_rd/s   kB_wr/s kB_ccwr/s  Command
06:59:17 PM   999      5385      0.00    118.00      0.00  redis-server
06:59:13 PM  1000     32038      0.00      1.99      0.00  mysqld
Average:        0       341      0.00      1.00      0.00  jbd2/sda2-8

06:59:17 PM   UID       PID   kB_rd/s   kB_wr/s kB_ccwr/s  Command
06:59:19 PM   999      5385      0.00    520.00      0.00  redis-server
06:59:13 PM  1000     32038      0.00      1.99      0.00  mysqld

Average:      UID       PID   kB_rd/s   kB_wr/s kB_ccwr/s  Command
Average:      999      5385      0.00    518.35      0.00  redis-server

# -d 查看过程的 I/O 状况
# 2 5 没两秒刷新一次,刷新五次退出

pidstat 不仅能看过程的 I/ O 状况, cpu,上下文切换,内存等的信息也能查看。

pidstat 输入的信息中看到,pid 5383 的过程,每秒写 500 KB 的数据,其余过程则没有什么 I/O 申请。pid 5383 的过程 Command 是 redis-server。这印证了咱们后面的猜想,阐明咱们的猜想是正确的。

好的,当初咱们曾经晓得了是 redis-server 导致的 磁盘 I/O 瓶颈。问题完结!

然而问题并没有解决,你的利用依然响应很慢。还要接着查,为什么 redis-server 会导致磁盘使用率升到呢?redis 在做什么?

pidstat 输入的信息中显示 redis-server 有大量的写磁盘操作,读却很少。那么,redis 利用 在写什么?

redis 运行在用户态,依据操作系统的原理咱们晓得用户态的过程发动 I/O 申请,须要通过零碎调用,由内核程序实现 I/O 调度操作,那么咱们就要查看 redis 利用的零碎调用状况。

4. strace 查看过程的零碎调用信息
[root@a ~]# strace -f -p 5385
[pid  5385] epoll_wait(5, [{EPOLLIN, {u32=7, u64=7}}], 10128, 42) = 1
[pid  5385] accept(7, {sa_family=AF_INET, sin_port=htons(50014), sin_addr=inet_addr("10.10.3.55")}, [16]) = 9
[pid  5385] fcntl(9, F_GETFL)           = 0x2 (flags O_RDWR)
[pid  5385] fcntl(9, F_SETFL, O_RDWR|O_NONBLOCK) = 0
[pid  5385] setsockopt(9, SOL_TCP, TCP_NODELAY, [1], 4) = 0
[pid  5385] epoll_ctl(5, EPOLL_CTL_ADD, 9, {EPOLLIN, {u32=9, u64=9}}) = 0
[pid  5385] accept(7, 0x7fff29fbec00, 0x7fff29fbebfc) = -1 EAGAIN (Resource temporarily unavailable)
[pid  5385] read(3, 0x7fff29fbecbf, 1)  = -1 EAGAIN (Resource temporarily unavailable)
[pid  5385] epoll_wait(5, [{EPOLLIN, {u32=9, u64=9}}], 10128, 40) = 1
[pid  5385] read(9, "*1\r\n$7\r\nCOMMAND\r\n", 16384) = 17
[pid  5385] read(3, 0x7fff29fbecbf, 1)  = -1 EAGAIN (Resource temporarily unavailable)
[pid  5385] write(8, "*200\r\n*6\r\n$9\r\npexpireat\r\n:3\r\n", 29) = 29
[pid  5385] write(8, "*2\r\n+write\r\n+fast\r\n:1\r\n:1\r\n:1\r\n*"..., 50) = 50
[pid  5385] write(8, "*3\r\n+write\r\n+denyoom\r\n+fast\r\n:1\r"..., 62) = 62
[pid  5385] write(8, "*2\r\n+admin\r\n+noscript\r\n:0\r\n:0\r\n:"..., 55) = 55



# -f 查看字过程 或者 子线程的信息
# -p 指定 pid。这里咱们曾经晓得是 5385 的过程了。察看一会他这个输入根本是循环的,这里截取其中一段。(案例中是循环输入,其余状况不肯定,须要多察看输入信息)epoll_wait, read, write, setsockopt 等这些都是零碎函数,5383 的 过程因为 始终在写货色,所以这里显示有很多 write() 函数调用的状况,括号里的第一个数字指的 FD, 就是文件描述符为 9,在前面那一串看起来是换行权限什么的,没什么用。只有找到文件描述符就能够了。

晓得了 redis-server 在写 FD 号是 8 的文件 咱们能干什么?能查到具体的文件。

对于文件描述符:
Linux 所有皆文件,内核利用文件描述符来拜访文件。关上现存文件或新建文件时,内核会返回一个文件描述符。读写文件也须要应用文件描述符来指定待读写的文件。每一个文件描述符会与一个关上文件绝对应,同时,不同的文件描述符也会指向同一个文件。雷同的文件能够被不同的过程关上也能够在同一个过程中被屡次关上。零碎为每一个过程保护了一个文件描述符表,该表的值都是从 0 开始的,所以在不同的过程中你会看到雷同的文件描述符,这种状况下雷同文件描述符有可能指向同一个文件,也有可能指向不同的文件。具体情况要具体分析,要了解具体其详情如何,须要查看由内核保护的 3 个数据结构。
1. 过程级的文件描述符表;
2. 零碎级的关上文件描述符表;
3. 文件系统的 i -node 表。

i-node 即 index-name ,inode 号是惟一的,切只能一个文件或者目录领有。操作系统并不分明文件名和目录名,而是操作 inode 号码,文件名和目录名只是敌对显示, 更改文件名对操作系统无感,因为更改文件名 inode 号也不会变。如果你晓得 inode 号,则能够用 inode 号治理这个文件。

5. lsof 查看过程关上的文件
[root@a ~]# lsof -p 5385
COMMAND    PID              USER   FD      TYPE DEVICE SIZE/OFF    NODE NAME
redis-ser 5385 systemd-bus-proxy  cwd       DIR    8,2     4096 5505025 /data
redis-ser 5385 systemd-bus-proxy  rtd       DIR   0,43     4096 5640717 /
redis-ser 5385 systemd-bus-proxy  txt       REG   0,43 10407928 5640636 /usr/local/bin/redis-server
redis-ser 5385 systemd-bus-proxy  mem       REG    8,2          5640636 /usr/local/bin/redis-server (stat: No such file or directory)
redis-ser 5385 systemd-bus-proxy  mem       REG    8,2          5636195 /lib/x86_64-linux-gnu/libc-2.28.so (stat: No such file or directory)
redis-ser 5385 systemd-bus-proxy  mem       REG    8,2          5636250 /lib/x86_64-linux-gnu/libpthread-2.28.so (stat: No such file or directory)
redis-ser 5385 systemd-bus-proxy  mem       REG    8,2          5636254 /lib/x86_64-linux-gnu/librt-2.28.so (stat: No such file or directory)
redis-ser 5385 systemd-bus-proxy  mem       REG    8,2          5636203 /lib/x86_64-linux-gnu/libdl-2.28.so (stat: No such file or directory)
redis-ser 5385 systemd-bus-proxy  mem       REG    8,2          5636218 /lib/x86_64-linux-gnu/libm-2.28.so (stat: No such file or directory)
redis-ser 5385 systemd-bus-proxy  mem       REG    8,2          5636181 /lib/x86_64-linux-gnu/ld-2.28.so (stat: No such file or directory)
redis-ser 5385 systemd-bus-proxy    0u      CHR  136,2      0t0       5 /2
redis-ser 5385 systemd-bus-proxy    1u      CHR  136,2      0t0       5 /2
redis-ser 5385 systemd-bus-proxy    2u      CHR  136,2      0t0       5 /2
redis-ser 5385 systemd-bus-proxy    3r     FIFO   0,12      0t0 4723129 pipe
redis-ser 5385 systemd-bus-proxy    4w     FIFO   0,12      0t0 4723129 pipe
redis-ser 5385 systemd-bus-proxy    5u  a_inode   0,13        0    9538 [eventpoll]
redis-ser 5385 systemd-bus-proxy    6u     sock    0,9      0t0 4723130 protocol: TCPv6
redis-ser 5385 systemd-bus-proxy    7u     sock    0,9      0t0 4723131 protocol: TCP
redis-ser 5385 systemd-bus-proxy    8w      REG    8,2  6551861 5505296 /data/appendonly.aof
redis-ser 5385 systemd-bus-proxy    9u     sock    0,9      0t0 4874906 protocol: TCP

第四列最初二行 8w 是 redis-server 过程操作的 FD,与之前 strace 追踪到的对应。8w,w 是写的意思,REG 惯例文件,正在写的文件是 /data/appendonly.aof。至此,咱们找到了 redis 在写文件 /data/appendonly.aof,导致了磁盘 I/O 瓶颈。## 以上输入的信息系统 man 手册都能看到解释,遗记了能够进行查看。罕用的相熟就能够。

appendonly.aof 是 redis 的快照数据,有可能是 redis 快照策略配置的不合理,这个时候就要查看 redis 的配置了。(案例中成心配置了不合理的快照策略)

排查零碎性能问题耗时费劲,案例只是提供了 排查 I/O 性能的一种思路。也有其余的办法其余工具,比方 sar 能够替换 iostat。(不过,这个形式差不多就能够搞定绝大部分 i/o 问题了)

工具链:top–>iostat–>pidstat–>strace–>lsof
这些工具应用非常灵活,参数十分多,没有必要都记住,遗记了能够查看 man 手册。

二. 从物理角度解决磁盘 I/O 瓶颈

如果不是应用程序的问题导致磁盘 I/O 瓶颈,的确是业务量的需要,那么须要物理上进步磁盘的 I/O 性能。

罕用的形式:

做 Raid 磁盘阵列,不同的 Raid 级别存储效率差别较大。常见的有这些:

  1. Raid 0:条带模式,是一种程度扩大形式,n 快盘连接起来,看起来像一块盘,容量是 n 快盘的总和。存储时把 数据打散,扩散的存到道不同的盘上,因为是 多快盘同时进行 I/O,所以 Raid 0 的 IOPS 是线性的进步。然而其中一块盘坏掉,数据就会失落,数据冗余较差。
  2. Raid 1:镜像模式,至多须要两块盘能力做 Raid 1。每次把写两份数据,一份存到镜像盘上。
    容量和 IOPS 是线性降落。然而数据安全性很高,主盘快掉,镜像盘能够进行替换。
  3. Raid 10: 是 Raid 1 和 Raid 0 的组合形式,至多须要 4 快磁盘,每两块先做出成 Raid 1,而后再把 Raid 1 做成 Raid 0。及解决了 Raid 0 数据不平安的问题,又解决了 Raid 1 IOPS 性能的问题。
  4. Raid 5:奇偶校验存储,至多须要三块磁盘。数据存储用奇偶校验的形式存到不同的盘上,当有磁盘损坏是,用奇偶存储推算出失落的数据进行复原。是 Raid 0 和 Raid 1 的这种计划,IOPS 介于两者之间。

不同级别能够任意组合,像 Raid10 + Raid10 再组合成 Raid 0

IOPS: Raid 0 > Raid 10 ≈ Raid 5 > 单块磁盘 > Raid 1

mysql 数据库服务器,通常会应用 Raid 10 形式。日志服务器 Raid 0。
磁盘阵列是由 Raid 控制卡(硬件)实现的,Raid 控制卡蕴含了一块 512M 的内存,有读写缓存的能力,然而写缓存默认是未开启的,开启后能无效的进步磁盘的 IOPS 性能。

应用 SSD 盘

IOPS 作为掂量磁盘 I/O 性能的重要指标,是咱们须要重点关注的。
说 ssd 盘速度快,个别指的是 IOPS 性能的晋升。

如何洽购硬盘?

1. 机械盘:

机械盘要关注磁盘转速参数,转速 10k, 示意 每分钟磁盘转 1w 圈。由机械盘的存储原理可知,转速越快意味着旋转提早越小,磁针能更快的达到指定扇区。
服务器磁盘转速 10k, 15k 的比拟常见。PC 机磁盘 5400, 7200。

用转速估算磁盘的 IOPS:
IOPS = 1s/(寻道工夫 + 旋转提早)ms

寻道工夫:磁盘上有不同半径的磁道,磁道上散布着各个扇区,扇区是磁盘读写数据的最小单元。读写磁盘上的数据,靠的是磁针在不同的磁道上来回挪动,磁道的半径不同,磁针挪动到不同磁道上的工夫也就不同。目前的机械盘,寻道工夫在 3-15ms(平均数)    

旋转提早:磁针达到指定半径的磁道之后,还不能立即读写扇区上的数据,因为同半径的磁道上有很多扇区,磁针要期待磁盘旋转达到指定的扇区才行。有可能磁针刚好停留的地位
就是须要的扇区,也有可能须要磁盘旋转一周。旋转延通常迟取半圈旋转的工夫。以 15k 转速为例:旋转工夫 = 1/(15000/60s/1000) * 1/2 = 2ms,7200 是 4.2ms
这就是你 PC 慢的起因。15k iops 估算:1s/(3 + 2)ms = 200 (最大值)
7.2k iops: 160

实际上磁盘应用不同的接口方式也能进步 IOPS 性能,机械盘的接口类型有,SCSI,SAS,SATA 这几种,15k 的 SATA 接口盘比 SCSI 接口的盘 IOPS 性能要好。

2. SSD 盘

SSD 盘没有旋转的概念,洽购的时候须要问分明厂商 IOPS 的数据。
SSD 盘按接口类型可分为 STAT ssd 和 PCIE ssd。

一般 SSD:(STAT 接口)

三星。
官网 IOPS 信息

4KB 随机读取(QD32): 最大 96,000 IOPS
4KB 随机写入(QD1): 最大 42,000 IOPS

IOPS 测试要跟雷同的 文件快大小比拟。4kb 文件块和 16kb 文件快 测试的数据没有可比性,不是一个概念。文件快越小,能力测出 IOPS 的最佳性能。
ssd 盘的 读写是不对称的,不想机械盘一样,这根 ssd 盘的存储原理无关。

下面的 IOPS 大抵能换算成随机 MB/s 的读写。
比方 随机写:(42000 * 4kb) /1024 = 164 Mb/s

比照 HDD 盘的 IOPS ,SSD 盘 IOPS 的晋升不是线性进步,而是指数级别的进步。对于 数据库服务器来讲,应用 SSD 存储,能够对 DB 速度有一个质的晋升。

PCIE SSD:

Intel。
厂商 IOPS 信息

512G 容量:

4KB 随机读取: 最大 340000 IOPS
4KB 随机写入: 最大 275000 IOPS

PCIE ssd 在 一般 ssd 的根底上 把 IOPS 性能 又晋升了 3-5 倍。

IOPS 指的是随机 I/O, 能无效的掂量磁盘的 I/O 性能。磁盘有预读页或者文件块的机制,程序 I/O 比 随机 I/O 要快的多,程序 I/O 通常不是咱们关注的对象。个别咱们对磁盘的操作随机 I/O 的 申请比例更多,如果在应用层把随机 I/O 优化成 程序 I/O(或者是逻辑上的 程序 I/O), 那么,利用的响应速度会快很多。Mysql innodb 存储引擎的 很多优化思维 就是这个逻辑,像索引,undo,redo 日志记录 等,尽可能的把 随机 I/O 变得有序。

正文完
 0