计算机原理探险系列(四)-- 磁盘存储探秘

简介: 计算机原理探险系列(四)-- 磁盘存储探秘

各位读者朋友们大家好,今天我们一起来聊聊关于计算机底层磁盘的读取原理。


磁盘的基本布局


磁盘的基本结构主要包含有以下几点,磁盘盘片,读写磁盘的指针,传动轴,主轴等。


网络异常,图片无法展示
|


每次用户程序从用户态发送一条指令给到操作系统内核,进行io读取数据的时候,cpu的ring3级别内核便会通过io总线发送一个指令给到读写磁头,然后由读写磁头定位到盘片的指定位置进行数据读写。最后再通过io总线将数据返回给到用户态的程序中。


下边是一张磁盘盘面的大致结构图:


网络异常,图片无法展示
|


在磁盘的盘面上通常会布有许多层的磁道,可以理解为图中的同心圆,然后每层磁道上分有不同范围的扇区,数据存储落在这些扇区的范围当中。磁盘指针头通常会落在盘道的一个位置点,然后朝一定方向旋转进行数据的搜索。


内围的磁道数据其实和外围的磁道数据是一样多的,这也就意味着外围的数据密度要比内围的小很多。现如今采用了区位记录的技术,保证了内围的磁道要比外围的磁道少,保证了密度的均匀性


影响磁盘指针定位数据的性能因素


寻道时间

磁盘指针定位到指定的盘道耗时


旋转延迟

指针定位到盘道之后进行旋转读取数据


数据传输

从内核态将数据传输给到用户态的耗时

通常技术人员会通过这么一条公式来推算一块磁盘的读写性能:


iops 指标:磁盘的每秒数据输入输出量,计算思路:1000ms / (数据寻道时间 + 旋转延迟时间 + 数据传输时间) 。


如今的硬件技术开始支持一些分散聚合DMA技术,能够支持将一些原先不连续的磁道数据进行组合读取,效率性更高。由于这种设备支持的磁道信息并不是一定连续的,所以有一个新的概念叫做段。


图片


磁盘毕竟是一个物理硬件层面的东西,那么早期的发明家则通过了一些抽象的概念在程序中对磁盘做访问。下边我们来介绍下经典的文件系统设计。


文件存储


在linux操作系统中,常说的一句话就是“一切皆文件“。


文件系统更像是一周抽象化的数据结构设计,其主要分为了两大模块,inode区和数据区。下边的文章我主要以ext2这种文件系统作为案例进行分析。


在ext2文件系统中磁盘数据通常是以block为单位进行存储的,多个连续的block的组合被称之为BlockGroup。


BlockGroup内部存储的数据较多,主要包含有两个模块:Inode区,Data Block区。Data Block区比较好理解,主要就是存储真实的文件信息,下边主要介绍下Inode区。


Inode区

每一份文件在进行存储的时除了需要记录文件内部的数据外,还会记录一些额外的元数据信息,例如说创建人,创建时间,修改时间,读写权限等。这些基础信息就统一存放在inode里面。


inode区内部主要包含以下内容:


  • 文件的字节数
  • 文件拥有者的User ID
  • 文件的Group ID
  • 文件的读、写、执行权限
  • 文件的时间戳 ,共有三个:ctime指inode上一次变动的时间,mtime指文件内容上一次变动的时间,atime指文件上一次打开的时间。
  • 链接数,即有多少文件名指向这个inode 文件数据block的位置

OS在实际打开一份文件的时候,其实并不是单纯依靠文件的名称和路径去查询对应数据的存储地址。每份文件在OS内部都会有一个指定编号对应,这个编号我们一般称之为inode 序号。


例如在OS接收用户点击鼠标打开一份word文档的时候,实际上会先根据用户点击文件的所在路径+文件名去查找对应的inode编号,根据这个编号找到inode块,再在inode块找到对应的数据指针,根据数据指针的地址获取到数据的真实信息。


查看inode的相关信息


[root@izwz9ic9ggky8kub9x1ptuz project]# stat ./log.file
  文件:"./log.file"
  大小:72545648    块:141704     IO 块:4096   普通文件
设备:fd01h/64769d  Inode:1185980     硬链接:1
权限:(0644/-rw-r--r--)  Uid:(    0/    root)   Gid:(    0/    root)
最近访问:2021-03-12 15:48:32.301232824 +0800
最近更改:2021-03-26 07:52:47.916795277 +0800
最近改动:2021-03-26 07:52:47.916795277 +0800
创建时间:
复制代码


有时候如果文件名称有乱码无法删除的话,可以通过删除inode号来实现删除效果。

数据存储在多个block区域中后,通常是在inode中会有1个数据指针负责多个block的映射,如果数据非常大,就需要有多个映射block的指针,但是inode的空间有限,一般是128kb,所以这里会有一种多级映射的设计,如同下图:


网络异常,图片无法展示
|


操作系统在读取数据的时候并不会一个一个扇区去读取数据,这样读取太慢了,通常是一个一个block(通常一个block包含有多个扇区)去读取的。


查看操作系统内部的inode数目


[root@izwz9ic9ggky8kub9x1ptuz project]# df -i
文件系统         Inode 已用(I) 可用(I) 已用(I)% 挂载点
/dev/vda1      2621440  300043 2321397      12% /
devtmpfs        233122     322  232800       1% /dev
tmpfs           235465       1  235464       1% /dev/shm
tmpfs           235465     391  235074       1% /run
tmpfs           235465      16  235449       1% /sys/fs/cgroup
tmpfs           235465       1  235464       1% /run/user/0
复制代码


硬连接和软连接


硬连接:每个文件本质都是用inode号码去识别的,所以如果我们用不同的命名指向同一个inode号码也可以达到同样效果。


ln 源文件 目标文件
复制代码


inode内部有个连接数,就是专门记录有多少个链接指向了自己。使用硬连接的方式需要对目标文件的inode内部连接数做修改+1操作。


[root@izwz9ic9ggky8kub9x1ptuz project]# ln ./log.file ./log2.file
[root@izwz9ic9ggky8kub9x1ptuz project]# ls
arthas         echarts.min.js  go             idea-blog.jar.original  log2.file  origin-jar  springboot-docker  stop.sh  test
arthas-output  files           idea-blog.jar  link                    log.file   project     start.sh           tank
复制代码


软连接可以理解为在源文件A内部注入目标文件B的所在地址。这样就意味着查看A文件的时候就能看到B文件的信息,但是如果B文件被删除,那么A文件就会丢失无法打开。

如何使用命令创建软连接:


ln -s 源文件 目标文件
复制代码


软连接和硬连接的本质区别:目标文件的链接数是否会增加


磁盘的IO读写


顺序读写和随机读写对于机械硬盘来说为什么性能差异巨大?

顺序读写=读取一个大文件

随机读写=读取多个小文件


顺序读写比随机读写快的原因

①顺序读写,主要时间花费在了传输时间,而这个时间两种读写可以认为是一样的。随机读写,需要多次寻道和旋转延迟。而这个时间可能是传输时间的许多倍。


②顺序读写,磁盘会预读,预读即在读取的起始地址连续读取多个页面

(现在不需要的页面也读取了,这样以后用时就不用再读取,当一个页面用到时,大多数情况下,它周围的页面也会被用到)。而随机读写,因为数据没有在一起,将预读浪费掉了。


③另一个原因是文件系统的overhead。

读写一个文件之前,得一层层目录找到这个文件,以及做一堆属性、权限之类的检查。写新文件时还要加上寻找磁盘可用空间的耗时。对于小文件,这些时间消耗的占比就非常大了。


常见的一些优化写性能的手段:


追加写


每次将数据添加到文件。由于完全是顺序的,所以可以具有非常好的写操作性能。但是这种方式也存在一些缺点:从文件中读一些数据时将会需要更多的时间:需要倒序扫描,直到找到所需要的内容。


文件合并和元数据优化


ext2文件系统在海量的小文件应用下性能表现情况其实并不佳,具体原因如下:

由于小文件数据内容较少,因此元数据的访问性能对小文件访问性能影响巨大。Ext2文件系统中Inode和Data Block分别保存在不同的物理位置上,一次读操作需要至少经过两次的独立访问。在海量小文件应用下,Inode的频繁访问,使得原本的并发访问转变为了海量的随机访问,大大降低了性能。另外,大量的小文件会快速耗尽Inode资源,导致磁盘尽管有大量Data Block剩余也无法存储文件,会浪费磁盘空间。


Ext2在Inode中使用多级指针来索引数据块。对于大文件,数据块的分配会尽量连续,这样会具有比较好的空间局部性。但是对于小文件,数据块可能零散分布在磁盘上的不同位置,并且会造成大量的磁盘碎片,不仅造成访问性能下降,还大量浪费了磁盘空间。数据块一般为1KB、2KB或4KB,对于小于4KB的小文件,Inode与数据的分开存储破坏了空间局部性,同时也造成了大量的随机I/O。


优化的策略


针对数据布局低效,采用小文件合并策略,将小文件合并为大文件。

针对元数据管理低效,优化元数据的存储和管理。针对这两种优化方式,业内也出现了许多优秀的开源软件。

目录
相关文章
|
7月前
|
存储 算法 索引
【头歌·计组·自己动手画CPU】三、存储系统设计(HUST)(理论版) 【计算机硬件系统设计】
【头歌·计组·自己动手画CPU】三、存储系统设计(HUST)(理论版) 【计算机硬件系统设计】
771 1
|
7月前
|
存储 缓存 Linux
计组存储层次简析
计组存储层次简析
95 0
|
存储 编译器 C语言
【这个“数据在内存中的存储(1)”讲解我能吹一辈子】
【这个“数据在内存中的存储(1)”讲解我能吹一辈子】
79 0
数据在内存中的存储(超级无敌究极详细!)
数据在内存中的存储(超级无敌究极详细!)
|
存储 缓存 数据可视化
CPU缓存读写以及一致性问题,你大学课堂睡过去的现在再温习下,绝对受益颇多
CPU缓存读写以及一致性问题,你大学课堂睡过去的现在再温习下,绝对受益颇多
|
存储 资源调度 算法
打通任督二脉:4000字,一文,从代码拆到计算机底层。
一个业务场景 假设我们要编写一个购买商品的程序,程序的内容很简单: 商品的库存数量存放在数据库中,每次完成库存数量-1。我们很快可以写出伪代码
76 0
|
存储 C语言
把玩数据在内存中的存储
前言:时光如梭,今天到了C语言进阶啦,基础知识我们已经有了初步认识, 是时候该拔高拔高自己了。 目标:掌握浮点数在内存的存储,整形在内存的存储。 鸡汤:时光易过,岁月蹉跎。
126 0
|
存储 小程序 编译器
【C/C++】庖丁解牛 深究数据在内存中如何存储
【C/C++】庖丁解牛 深究数据在内存中如何存储
175 0
数据结构上机实践第二周项目2- 程序的多文件组织
数据结构上机实践第二周项目2- 程序的多文件组织
112 0
数据结构上机实践第二周项目2- 程序的多文件组织
|
存储 算法 小程序
深度剖析数据在内存中的存储(修炼内功~吊打面试官)
深度剖析数据在内存中的存储(修炼内功~吊打面试官)
153 0
深度剖析数据在内存中的存储(修炼内功~吊打面试官)