文件系统原理

news2025/3/12 9:32:17

文件及硬盘管理是计算机操作系统的重要组成部分,让微软走上成功之路的正是微软最早推出的个人电脑PC操作系统,这个操作系统就叫DOS,即Disk Operating System,硬盘操作系统。我们每天使用电脑都离不开硬盘,硬盘既有大小的限制,通常大一点的硬盘也不过几T,又有速度限制,快一点的硬盘也不过每秒几百M。

文件是存储在硬盘上的,文件的读写访问速度必然受到硬盘的物理限制,那么如何才能1分钟完成一个100T大文件的遍历呢?

想要知道这个问题的答案,我们就必须知道文件系统的原理。

做软件开发时,必然要经常和文件系统打交道,而文件系统也是一个软件,了解文件系统的设计原理,可以帮助我们更好地使用文件系统,另外设计文件系统时的各种考量,也对我们自己做软件设计有诸多借鉴意义。

让我们先从硬盘的物理结构说起。

硬盘

硬盘是一种可持久保存、多次读写数据的存储介质。硬盘的形式主要两种,一种是机械式硬盘,一种是固态硬盘。

机械式硬盘的结构,主要包含盘片、主轴、磁头臂,主轴带动盘片高速旋转,当需要读写盘上的数据的时候,磁头臂会移动磁头到盘片所在的磁道上,磁头读取磁道上的数据。读写数据需要移动磁头,这样一个机械的动作,至少需要花费数毫秒的时间,这是机械式硬盘访问延迟的主要原因。

如果一个文件的数据在硬盘上不是连续存储的,比如数据库的B+树文件,那么要读取这个文件,磁头臂就必须来回移动,花费的时间必然很长。如果文件数据是连续存储的,比如日志文件,那么磁头臂就可以较少移动,相比离散存储的同样大小的文件,连续存储的文件的读写速度要快得多。

机械式硬盘的数据就存储在具有磁性特质的盘片上,因此这种硬盘也被称为磁盘,而固态硬盘则没有这种磁性特质的存储介质,也没有电机驱动的机械式结构。

其中主控芯片处理端口输入的指令和数据,然后控制闪存颗粒进行数据读写。由于固态硬盘没有了机械式硬盘的电机驱动磁头臂进行机械式物理移动的环节,而是完全的电子操作,因此固态硬盘的访问速度远快于机械式硬盘。

但是,到目前为止固态硬盘的成本还是明显高于机械式硬盘,因此在生产环境中,最主要的存储介质依然是机械式硬盘。如果一个场景对数据访问速度、存储容量、成本都有较高要求,那么可以采用固态硬盘和机械式硬盘混合部署的方式,即在一台服务器上既有固态硬盘,也有机械式硬盘,以满足不同文件类型的存储需求,比如日志文件存储在机械式硬盘上,而系统文件和随机读写的文件存储在固态硬盘上。

文件系统

作为应用程序开发者,我们不需要直接操作硬盘,而是通过操作系统,以文件的方式对硬盘上的数据进行读写访问。文件系统将硬盘空间以块为单位进行划分,每个文件占据若干个块,然后再通过一个文件控制块FCB记录每个文件占据的硬盘数据块。

alt

这个文件控制块在Linux操作系统中就是inode,要想访问文件,就必须获得文件的inode信息,在inode中查找文件数据块索引表,根据索引中记录的硬盘地址信息访问硬盘,读写数据。

inode中记录着文件权限、所有者、修改时间和文件大小等文件属性信息,以及文件数据块硬盘地址索引。inode是固定结构的,能够记录的硬盘地址索引数也是固定的,只有15个索引。其中前12个索引直接记录数据块地址,第13个索引记录索引地址,也就是说,索引块指向的硬盘数据块并不直接记录文件数据,而是记录文件数据块的索引表,每个索引表可以记录256个索引;第14个索引记录二级索引地址,第15个索引记录三级索引地址,如下图:

alt

这样,每个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。

alt

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为例,看下分布式文件系统的具体架构设计。

alt

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 多平台发布

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/640563.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

黑龙江二造开始报名!文件指出建设单位对现场人员配备达标负首责

注意!2023年黑龙江二级造价考试报名时间公布!!!可以开始报名! ✨考试时间:7月9日 ✨报名时间:6月6日—6月14日 ✨缴费时间:6月6日—6月16日 ✨打印准考证时间:7月4日&am…

程序运行原理

程序是如何运行起来的 软件被开发出来,是文本格式的代码,这些代码通常不能直接运行,需要使用编译器编译成操作系统或者虚拟机可以运行的代码,即可执行代码,它们都被存储在文件系统中。不管是文本格式的代码还是可执行…

ChatGPT付费创作系统V2.0.2独立版+小程序安装教程

ChatGPT付费创作系统V2.0.2独立版播播资源测试了下相比,本版核心WEB端进行升级优化,前端增加了创作、模拟、使用帮助等选项,小程序端相比上一版无大的变化。体验下来问答速度感觉体验更好。小程序端有更新请对应开发工具更新上传,…

HAL库记录-SDRAM的使用

正点原子--阿波罗开发板STM32F429IGT6 CLK 时钟信号,在该时钟的上升沿采集输入信号 CKE 时钟使能,禁止时钟时,SDRAM 会进入自刷新模式 CS# 片选信号,低电平有效 RAS# 行地址选通信号&#xff…

剑指offer57.和为s的两个数字

双指针i从左往右,j从右往左,如果大于目标值,j往左走否则i往右走,直到等于目标值 class Solution {public int[] twoSum(int[] nums, int target) {int[] res new int[2];int i 0; int j nums.length-1;int sum nums[i] nums…

docker指令

镜像命令 镜像命令 命令描述docker images php查看名字为php的镜像docker images查看所有镜像docker search搜索镜像docker pull 镜像名:tag 拉取镜像docker rmi php删除php镜像 (保存php镜像到目录) docker image save php > D:\phpstudy_pro\WWW\docker\php.tgz 或者 …

【利用AI让知识体系化】简要了解面向对象编程设计

文章目录 I. 面向对象编程简介面向对象编程的定义与发展历程面向对象编程的优点和特点面向对象和面向过程和面向函数式编程之间的对比 II. 面向对象编程的基本概念类和对象抽象和封装继承和多态封装、继承和多态之间的一些对比 III. 面向对象编程设计原则单一职责原则&#xff…

如何搭建高可用redis架构?

题记 Redis 是一个开源的使用 ANSI C 语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value 数据库,并提供多种语言的 API。 如今,互联网业务的数据正以更快的速度在增长,数据类型越来越丰富,这对数据处理的速度和能力提…

chatgpt赋能python:Python怎么建网站的SEO

Python怎么建网站的SEO 介绍 Python是一种流行的编程语言,其灵活性和可靠性使其成为了许多网站开发人员的首选语言之一。Python可以用于构建各种类型的网站,包括电子商务和企业级应用程序等。但是,构建一个网站是不够的,您还需要…

力扣刷题记录--二叉树相关问题

目录 二叉树的前中后序遍历递归方法迭代方法(未统一写法)前序迭代中序迭代后序迭代 迭代方法(统一模板)二叉树遍历LeetCode 144. 二叉树的前序遍历LeetCode 145. 二叉树的后序遍历LeetCode 94. 二叉树的中序遍历 n叉树的遍历LeetC…

树莓派(raspbian2)上开发OpenCv_C++

树莓派[raspbian2]上开发OpenCv_C 背景故事一.首先就是搭建环境了1.该位置是环境下载地址2.远程连接3.安装OpenCV(如果使用的是上面的镜像,则不用安装) 二.代码示例1.打开摄像头2.采集图像 以上是2023-06-12的日志,接下来还有四天的实训!继续更新! 背景故事 最近刚好赶上学校的…

chatgpt赋能python:Python怎样进行快速复制?

Python怎样进行快速复制? 如果你经常使用Python编程,那么你了解到实现复制粘贴操作的重要性。可以通过快速复制代码片段,提高您的生产力和效率。在这篇文章中,我们将讨论一些Python中的技巧和工具,以便您进行快速复制…

《剑指 Offer--LeetCode 学习计划》-- 链表

剑指 Offer 06. 从尾到头打印链表&#xff08;Easy&#xff09; 题目描述 输入一个链表的头节点&#xff0c;从尾到头反过来返回每个节点的值&#xff08;用数组返回&#xff09;。限制&#xff1a;0 < 链表长度 < 10000。 举例说明 示例 1&#xff1a; 输入&#xf…

谈谈几个常见数据结构的原理

数组 数组是最常用的数据结构&#xff0c;创建数组必须要内存中一块 连续 的空间&#xff0c;并且数组中必须存放 相同 的数据类型。比如我们创建一个长度为10&#xff0c;数据类型为整型的数组&#xff0c;在内存中的地址是从1000开始&#xff0c;那么它在内存中的存储格式如…

【送书福利-第十期】清华社 IT BOOK 多得图书活动 ~!

大家好&#xff0c;我是洲洲&#xff0c;欢迎关注&#xff0c;一个爱听周杰伦的程序员。关注公众号【程序员洲洲】即可获得10G学习资料、面试笔记、大厂独家学习体系路线等…还可以加入技术交流群欢迎大家在CSDN后台私信我&#xff01; 本文目录 一、前言二、内容介绍三、抽奖方…

第一章JUC概述

文章目录 什么是JUC为什么学习好多线程很重要硬件来说软件来说存在的问题 Java多线程相关概念一把锁两个并三个程进程和程序的联系线程和进程的联系管程 用户线程和守护线程JAVA线程 什么是JUC 在 Java 5.0 提供了 java.util.concurrent &#xff08; 简称JUC &#xff09; 包…

Spring Cloud Alibaba - Sentinel源码分析

目录 一、Sentinel核心源码分析 1、Sentinel核心概念 1.1、Node之间的关系 2、Sentinel源码入口 2.1、SlotChain解析 2.2、NodeSelectorSlot解析 2.3、ClusterBuilderSlot解析 一、Sentinel核心源码分析 Sentinel是分布式系统的防御系统。以流量为切入点&#xff0c;通过…

001安装Jenkins

安装JenkinsJenkins 是一个开源自动化服务器http://www.jenkins.io/zh/doc/book/installing/#%E7%B3%BB%E7%BB%9F%E8%A6%81%E6%B1%82 docker docker run \-u root \--rm \-d \-p 8080:8080 \-p 50000:50000 \-v jenkins-data:/var/jenkins_home \-v /var/run/docker.sock:/va…

传感器融合概念及对比

1.多传感器融合的定义 传感器数据融合的定义可以概括为把分布在不同位置的多个同类或不同类传感器所提供的局部数据资源加以综合&#xff0c;采用计算机技术对其进行分析&#xff0c;消除多传感器信息之间可能存在的冗余和矛盾&#xff0c;加以互补&#xff0c;降低其不确实性…

记录好项目D2

记录好项目 你好呀&#xff0c;这里是我专门记录一下从某些地方收集起来的项目&#xff0c;对项目修改&#xff0c;进行添砖加瓦&#xff0c;变成自己的闪亮项目。修修补补也可以成为毕设哦 本次的项目是个旅游门户网站 技术栈&#xff1a;JSPjQueryAjaxechartsSpringSpring…