文件及硬盘治理是计算机操作系统的重要组成部分,让微软走上成功之路的正是微软最早推出的个人电脑PC操作系统,这个操作系统就叫DOS,即Disk Operating System,硬盘操作系统。咱们每天应用电脑都离不开硬盘,硬盘既有大小的限度,通常大一点的硬盘也不过几T,又有速度限制,快一点的硬盘也不过每秒几百M。
文件是存储在硬盘上的,文件的读写访问速度必然受到硬盘的物理限度,那么如何能力1分钟实现一个100T大文件的遍历呢?
想要晓得这个问题的答案,咱们就必须晓得文件系统的原理。
做软件开发时,必然要常常和文件系统打交道,而文件系统也是一个软件,理解文件系统的设计原理,能够帮忙咱们更好地应用文件系统,另外设计文件系统时的各种考量,也对咱们本人做软件设计有诸多借鉴意义。
让咱们先从硬盘的物理构造说起。
硬盘
硬盘是一种可长久保留、屡次读写数据的存储介质。硬盘的模式次要两种,一种是机械式硬盘,一种是固态硬盘。
机械式硬盘的构造,次要蕴含盘片、主轴、磁头臂,主轴带动盘片高速旋转,当须要读写盘上的数据的时候,磁头臂会挪动磁头到盘片所在的磁道上,磁头读取磁道上的数据。读写数据须要挪动磁头,这样一个机械的动作,至多须要破费数毫秒的工夫,这是机械式硬盘拜访提早的次要起因。
如果一个文件的数据在硬盘上不是间断存储的,比方数据库的B+树文件,那么要读取这个文件,磁头臂就必须来回挪动,破费的工夫必然很长。如果文件数据是间断存储的,比方日志文件,那么磁头臂就能够较少挪动,相比离散存储的同样大小的文件,间断存储的文件的读写速度要快得多。
机械式硬盘的数据就存储在具备磁性特质的盘片上,因而这种硬盘也被称为磁盘,而固态硬盘则没有这种磁性特质的存储介质,也没有电机驱动的机械式构造。
其中主控芯片解决端口输出的指令和数据,而后管制闪存颗粒进行数据读写。因为固态硬盘没有了机械式硬盘的电机驱动磁头臂进行机械式物理挪动的环节,而是齐全的电子操作,因而固态硬盘的访问速度远快于机械式硬盘。
然而,到目前为止固态硬盘的老本还是显著高于机械式硬盘,因而在生产环境中,最次要的存储介质仍然是机械式硬盘。如果一个场景对数据访问速度、存储容量、老本都有较高要求,那么能够采纳固态硬盘和机械式硬盘混合部署的形式,即在一台服务器上既有固态硬盘,也有机械式硬盘,以满足不同文件类型的存储需要,比方日志文件存储在机械式硬盘上,而系统文件和随机读写的文件存储在固态硬盘上。
文件系统
作为应用程序开发者,咱们不须要间接操作硬盘,而是通过操作系统,以文件的形式对硬盘上的数据进行读写访问。文件系统将硬盘空间以块为单位进行划分,每个文件占据若干个块,而后再通过一个文件管制块FCB记录每个文件占据的硬盘数据块。
这个文件管制块在Linux操作系统中就是inode,要想拜访文件,就必须取得文件的inode信息,在inode中查找文件数据块索引表,依据索引中记录的硬盘地址信息拜访硬盘,读写数据。
inode中记录着文件权限、所有者、批改工夫和文件大小等文件属性信息,以及文件数据块硬盘地址索引。inode是固定构造的,可能记录的硬盘地址索引数也是固定的,只有15个索引。其中前12个索引间接记录数据块地址,第13个索引记录索引地址,也就是说,索引块指向的硬盘数据块并不间接记录文件数据,而是记录文件数据块的索引表,每个索引表能够记录256个索引;第14个索引记录二级索引地址,第15个索引记录三级索引地址,如下图:
这样,每个inode最多能够存储12+256+256*256+256*256*256个数据块,如果每个数据块的大小为4k,也就是单个文件最大不超过70G,而且即便能够扩充数据块大小,文件大小也要受单个硬盘容量的限度。这样的话,对于咱们结尾提出的一分钟实现100T大文件的遍历,Linux文件系统是无奈实现的。
那么,有没有更给力的解决方案呢?
RAID
RAID,即独立硬盘冗余阵列,将多块硬盘通过硬件RAID卡或者软件RAID的计划治理起来,使其独特对外提供服务。RAID的外围思路其实是利用文件系统将数据写入硬盘中不同数据块的个性,将多块硬盘上的闲暇空间看做一个整体,进行数据写入,也就是说,一个文件的多个数据块可能写入多个硬盘。
依据硬盘组织和应用形式不同,罕用RAID有五种,别离是RAID 0、RAID 1、RAID 10、RAID 5和RAID 6。
RAID 0将一个文件的数据分成N片,同时向N个硬盘写入,这样单个文件能够存储在N个硬盘上,文件容量能够扩充N倍,(实践上)读写速度也能够扩充N倍。然而应用RAID 0的最大问题是文件数据扩散在N块硬盘上,任何一块硬盘损坏,就会导致数据不残缺,整个文件系统全副损坏,文件的可用性极大地升高了。
RAID 1则是利用两块硬盘进行数据备份,文件同时向两块硬盘写入,这样任何一块硬盘损坏都不会呈现文件数据失落的状况,文件的可用性失去晋升。
RAID 10联合RAID 0和RAID 1,将多块硬盘进行两两分组,文件数据分成N片,每个分组写入一片,每个分组内的两块硬盘再进行数据备份。这样既扩充了文件的容量,又进步了文件的可用性。然而这种形式硬盘的利用率只有50%,有一半的硬盘被用来做数据备份。
RAID 5针对RAID 10硬盘节约的状况,将数据分成N-1片,再利用这N-1片数据进行位运算,计算一片校验数据,而后将这N片数据写入N个硬盘。这样任何一块硬盘损坏,都能够利用校验片的数据和其余数据进行计算失去这片失落的数据,而硬盘的利用率也进步到N-1/N。
RAID 5能够解决一块硬盘损坏后文件不可用的问题,那么如果两块文件损坏?RAID 6的解决方案是,用两种位运算校验算法计算两片校验数据,这样两块硬盘损坏还是能够计算失去失落的数据片。
实际中,应用最多的是RAID 5,数据被分成N-1片并发写入N-1块硬盘,这样既能够失去较好的硬盘利用率,也能失去很好的读写速度,同时还能保障较好的数据可用性。应用RAID 5的文件系统比简略的文件系统文件容量和读写速度都进步了N-1倍,然而一台服务器上能插入的硬盘数量是无限的,通常是8块,也就是文件读写速度和存储容量进步了7倍,这远远达不到1分钟实现100T文件的遍历要求。
那么,有没有更给力的解决方案呢?
分布式文件系统
咱们再回过头看下Linux的文件系统:文件的根本信息,也就是文件元信息记录在文件管制块inode中,文件的数据记录在硬盘的数据块中,inode通过索引记录数据块的地址,读写文件的时候,查问inode中的索引记录失去数据块的硬盘地址,而后拜访数据。
如果将数据块的地址改成分布式服务器的地址呢?也就是查问失去的数据块地址不只是本机的硬盘地址,还能够是其余服务器的地址,那么文件的存储容量就将是整个分布式服务器集群的硬盘容量,这样还能够在不同的服务器上同时并行读取文件的数据块,文件访问速度也将极大的放慢。
这样的文件系统就是分布式文件系统,分布式文件系统的思路其实和RAID是一脉相承的,就是将数据分成很多片,同时向N台服务器上进行数据写入。针对一片数据失落就导致整个文件损坏的状况,分布式文件系统也是采纳数据备份的形式,将多个备份数据片写入多个服务器,以保障文件的可用性。当然,也能够采纳RAID 5的形式通过计算校验数据片的形式进步文件可用性。
咱们以Hadoop分布式文件系统HDFS为例,看下分布式文件系统的具体架构设计。
HDFS的要害组件有两个,一个是DataNode,一个是NameNode。
DataNode负责文件数据的存储和读写操作,HDFS将文件数据宰割成若干数据块(Block),每个DataNode存储一部分数据块,这样文件就散布存储在整个HDFS服务器集群中。应用程序客户端(Client)能够并行对这些数据块进行拜访,从而使得HDFS能够在服务器集群规模上实现数据并行拜访,极大地提高了访问速度。在实践中,HDFS集群的DataNode服务器会有很多台,个别在几百台到几千台这样的规模,每台服务器配有数块硬盘,整个集群的存储容量大略在几PB到数百PB。
NameNode负责整个分布式文件系统的元数据(MetaData)治理,也就是文件路径名、拜访权限、数据块的ID以及存储地位等信息,相当于Linux零碎中inode的角色。HDFS为了保证数据的高可用,会将一个数据块复制为多份(缺省状况为3份),并将多份雷同的数据块存储在不同的服务器上,甚至不同的机架上。这样当有硬盘损坏,或者某个DataNode服务器宕机,甚至某个交换机宕机,导致其存储的数据块不能拜访的时候,客户端会查找其备份的数据块进行拜访。
有了HDFS,能够实现繁多文件存储几百T的数据,再配合大数据计算框架MapReduce或者Spark,能够对这个文件的数据块进行并发计算。也能够应用Impala这样的SQL引擎对这个文件进行结构化查问,在数千台服务器上并发遍历100T的数据,1分钟都是入不敷出的。
总结
文件系统从简略操作系统文件,到RAID,再到分布式文件系统,其设计思路其实是具备统一性的。这种统一性一方面体现在文件数据如何治理,也就是如何通过文件管制块管理文件的数据,这个文件管制块在Linux零碎中就是inode,在HDFS中就是NameNode。
另一方面体现在如何利用更多的硬盘实现越来越大的文件存储需要和越来越快的读写速度需要,也就是将数据分片后同时写入多块硬盘。单服务器咱们能够通过RAID来实现,多服务器则能够将这些服务器组成一个文件系统集群,独特对外提供文件服务,这时候,数千台服务器的数万块硬盘以繁多存储资源的形式对文件使用者提供服务,也就是一个文件能够存储数百T的数据,并在一分钟实现这样一个大文件的遍历。
本文由mdnice多平台公布