我们学习了Linux文件系统的工作原理,文件系统是对存储设备上的文件,进行组织管理的一种机制,在Linux的不同文件系统的实现之上,还抽象了一层虚拟文件系统VFS,定义了一组通用的接口
应用程序只需要和VFS提供的统一接口进行交互,而不需要关注文件系统的具体实现,对于具体的文件系统来说,只需要按照VFS的标准,就可以无缝支持各种应用程序
而在实际的磁盘中,包含了目录项 索引节点 逻辑块 超级快等不同的数据结构,磁盘具体如何工作的?又有哪些指标可以用来衡量它的性能呢?
那么我们必然需要了解一些磁盘的基本知识
磁盘分为两种,分别是机械磁盘和固态磁盘
机械磁盘又名硬盘驱动器 Hard Disk Driver,缩写为HDD,由盘片和读写磁片组成,数据存储在盘片的环状磁道中,读写数据前,移动读写磁头,定位到数据所在的磁道,进行访问数据
如果IO请求在磁盘上连续,就可以连续读取,不移动磁头,如果是随机IO,则需要不停的移动磁头
固态磁盘指的是SSD,不需要寻址,所以性能好得多
但是无论哪种磁盘,随机IO都是一种无意义的消耗,即使是SSD,也存在先擦除,在写入的限制,随机读写导致大量的垃圾回收
在很多IO性能优化的方案中,利用连续读来增强IO性能是一种常见的解决方案,在Java中,有着环形数组这种利用连续IO的方式
此外,SSD和HDD质检,还有着读写单位的不同的区别,机械磁盘的最小读写单位是一个扇区,一般为512字节,SSD的最小单位是页,一般是4KB
HDD为了加强读写性能,会将连续的扇区或者页,组成逻辑块
在磁盘的分类之上,还有着不同的组织架构,简单点的就是,可以直接作为独立磁盘设备来使用,这些磁盘,根据需要分为不同的逻辑分区
或者将多个磁盘组成一个逻辑磁盘,形成冗余独立磁盘阵列,就是RAID,来增强数据可靠性
RAID可以根据读写性能和可靠性不同,分为不同级别 RAID0 -10
RAID读写性能最优,但是不提供冗余功能
其他级别的RAID,则是提供冗余的基础之上,优化了读写性能
还有就是,讲磁盘组合成一个网络存储集群,通过NFS等网络存储协议,暴露给服务器使用
实际上,在Linux中,磁盘是作为一个块设备进行管理的,以块为单位进行读写数据,并且支持随机读写,每个块设备都会被赋予两个设备号,分别是主和次,主设备用于驱动程序,此设备则是编号
同样,在文件系统VFS之下,为了减少不同的块设备类型带来的差异,Linux也提供了一个统一的通用块层,管理不同的块设备
通用块层,就是处于文件系统和磁盘驱动中间的块设备抽象层,向上为整个文件系统,提供统一的块设备访问接口,向下,将不同架构的磁盘抽象为统一的块设备,只要块设备符合通用块的接入,即可进行接入
并且,通用块层还提供了一些优化功能,比如重新排序 请求合并等方式,提高磁盘读写效率
在通用块层,对IO请求重新排序,就是熟悉的IO调度算法,常见的有None Noop CFQ DeadLine
None则是不进行调度算法
Noop则是一个先入先出的队列,只进行基本的请求合并,常用于SSD
CFQ,为完全公平调度器,为每一个进程维护了一个IO调度队列,按照时间片来均匀分布每个进程的I/O请求
最后则是DeadLine,分为了读和写请求队列,如果有IO到达了deadline的期限,则会被优先处理,DeadLine算法,多用于IO压力重的场景,比如数据库
整体整理一下
磁盘和通用块层的工作原理获取到了之后,我们结合我们上一期讲过的文件系统原理,来看整体的IO原理
我们将VFS和实际的文件系统实现称为文件系统层,提供标准的文件访问接口,向下通过通用块层,存储和管理磁盘数据
通用块层,包括块设备IO队列和IO调度器,会对文件系统的IO请求进行排队,然后通过重新排序和请求合并的方式,发送给下一级的设备层
设备层则是物理设备的IO操作
对于存储系统.Linux本身做了不少的优化手段,比如页缓存,索引节点缓存,目录项缓存等多种缓存方式,减少对块设备的直接调用
接下来,下节,我们会讲如何评测磁盘的IO性能,以及常见的IO性能工具