1、磁盘
- 机械磁盘:也称硬盘驱动器(Hard Disk Driver)(HDD)。主要由盘片和读写磁头组成,数据就存储在盘片的环状磁道中。在读写数据前,需要移动读写磁头,定位到数据所在的磁道,才能访问数据。最小的读写单位是 扇区,一般大小 512 字节。
- 固态磁盘:(Solid State Disk)(SSD)。由固态电子元器件组成。不需要磁道寻址,因此不管连续 I/O ,还是随机 I/O ,性能都较好。最小的读写单位是 页,一般是 4KB、8KB。
针对 I/O 来说,相同磁盘的随机 I/O 都要比连续 I/O 慢很多,原因:
1、对于机械磁盘来说,随机 I/O 需要更多的磁头寻道和盘片旋转
2、对于固态磁盘来说,存在“先擦除再写入”的限制。随机读写会造成大量的垃圾回收。因此,随机 I/O 的性能比 连续 I/O ,性能要差
3、连续 I/O 可以通过预读的方式,减少 I/O 请求次数
在Linux中,磁盘实际上以作为一个 块设备 来管理的,也就是以 块 为单位读写数据,并且支持随机读写。每个块设备都会被赋予两个设备号,分别是 主、次设备号。主设备号用在驱动程序中,用来区分设备类型;次设备号用来给多个同类设备编号。
2、通用块层
处在文件系统和磁盘驱动中间的一个块设备抽象层,主要有两个功能:
- 第一个,跟虚拟文件系统的功能类似。向上,为文件系统和应用程序,提供访问块设备的标准接口;向下,把各种异构的磁盘设备抽象为统一的块设备,并提供统一框架来管理这些设备的驱动程序
- 第二个,通用块层会给文件系统和应用程序发来的 I/O 请求排队,并通过重新排序、请求合并等方式,提高磁盘读写的效率。
对于 I/O 请求排序的过程,也就是 I/O 调度,Linux支持四种 I/O 调度算法,
- NONE:更确切来说,并不能算 I/O 调度算法。因为它完全不使用任何 I/O 调度器,对文件系统和应用程序的 I/O 其实不做任何处理,常用在虚拟机中(此时磁盘 I/O 调度完全由物理机负责)。
- NOOP:先入先出的队列,只做一些最基本的请求合并,常用于 SSD 磁盘
- CFQ(Completely Fair Scheduler):完全公平调度器,它为每个进程维护了一个 I/O 调度队列,按照时间片来均匀分布每个进程的 I/O 请求
- DeadLine调度算法:分别为读、写请求创建了不同的 I/O 队列,可以提高机械磁盘的吞吐量,并确保达到最终期限(deadline)的请求被优先处理。多用在 I/O 压力较重的场景,如数据库等
3、I/O 栈
Linux存储系统的 I/O 栈,由上到下分为三层:文件系统层、通用块层、设备层
- 文件系统层:包括虚拟文件系统和其他各种文件系统的具体实现,它为上层的应用程序,提供标准的文件访问接口;对下会通过通用块层,来存储和管理磁盘数据。
- 通用块层:包括块设备 I/O 队列和 I/O 调度器。它会对文件系统的 I/O 请求进行排队,再通过重新排序和请求合并,然后才要发送给下一级的设备层。
设备层:包括存储设备和相应的驱动程序,负责最终物理设备的 I/O 操作。
4、性能指标
使用率:指磁盘处理 I/O 的时间百分比。过高的使用率,通常意味着磁盘 I/O 存在性能瓶颈
- 饱和度:指磁盘处理 I/O 的繁忙成都。当饱和度为 100% 时,磁盘无法接收新的 I/O 请求
- IOPS(Input/Output Per Second):每秒的 I/O 请求数
- 吞吐量:每秒的 I/O 请求大小
-
5、磁盘 I/O 观测:iostat
# -d -x 表示显示所有磁盘 I/O 的指标iostat -d -x 1

第一列是 磁盘设备的名字
注意: %util:就是磁盘 I/O 使用率
- r/s + w/s:就是 IOPS
- rkB/s + wkB/s:就是吞吐量
-
6、进程 I/O 观测:
1、pidstat
# -d 查看进程的 I/O 情况pidstat -d 1

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

第一行:进程的磁盘读写大小总数
- 第二行:进程的磁盘真实的读写大小总数
以为缓冲、缓存区、I/O 合并等因素的影响,可能不相等
