共计 4297 个字符,预计需要花费 11 分钟才能阅读完成。
导读 | Hadoop 分布式文件系统 (HDFS) 被设计成适合运行在通用硬件 (commodity hardware) 上的分布式文件系统。它和现有的分布式文件系统有很多共同点。但同时,它和其他的分布式文件系统的区别也是很明显的。HDFS 是一个高度容错性的系统,适合部署在廉价的机器上。 |
随着数据量越来越大,在 一个操作系统管辖的范围存不下了,那么就 分配到更多的操作系统管理的磁盘中,但是不方便管理和维护,迫切需要一种系统来管理多台机器上的文件,这就是分布式文件管理系统。
学术一点的定义就是:分布式文件系统是一种允许文件通过网络在多台主机上分享的 文件的系统,可让多机器上的多用户分享文件和存储空间。分布式文件管理系统很多,hdfsHDFS 只是其中一种。适用于一次写入、多次查询的情况,不支持并发写情况,小文件不合适。因为小文件也占用一个块,小文件越多(1000 个 1k 文件)块越 多,NameNode 压力越大。
我们通过 hadoop shell 上传的文件是存放在 DataNode 的 block 中,通过 linux shell 是看 不到文件的,只能看到 block。可以一句话描述 HDFS:把客户端的大文件存放在很多节点的数据块中。在这里,出现了三个关键词:文件、节点、数据块。HDFS 就是围绕着这三个关键词设计的,我们在学习的时候也要紧抓住这三个关键词来学习。
NameNode 的作用是 管理文件目录结构,接受用户的操作请求, 是管理数据节点的。名字节点维护两套数据,一套 是文件 目录与数据块之间的关系,另一套 是 数据块与节点之间的关系。前一套 数据是 静态的,是存放在磁盘上的,通过 fsimage 和 edits 文件来维护;后一套 数据是 动态的,不持久放到到磁盘的,每当集群启动的时候,会自动建立这些信息,所以一般都放在内存中。
所以他是整个文件系统的 管理节点。它维护着整个文件系统的 文件目录树,文件 / 目录的 元信息和每个文件对应的 数据块列表。接收用户的操作请求。
文件包括:
① fsimage(文件系统镜像): 元数据镜像文件。存储某一时段 NameNode 内存 元数据信息。
② edits: 操作日志文件。
③ fstime: 保存最近一次 checkpoint 的时间
以上这些文件是保存在 linux 的文件系统中
<1> 是一种允许文件 通过网络在多台主机上分享的文件系统,可让多机器上的多用户分享文件和存储空间。
<2> 通透性。让实际上是通过网络来访问文件的动作,由程序与用户看来,就像是访问本地的磁盘一般。
<3> 容错。即使系统中有某些节点脱机,整体来说系统仍然可以持续运作而不会有数据损失。
<4> 适用于 一次写入、多次查询的情况,不支持并发写情况,小文件不合适
<1> 既然 NameNode 维护这么多的信息, 那么 这些信息都存放在哪里呢?
在 hadoop 源代码中有个文件叫做 hdfs-default.xml
<2> 打开这个文件
在第 149 行和第 158 行,有两个配置信息,一个是 dfs.name.dir,另一个是 dfs.name.edits.dir。这两个文件表示的是 NameNode 的核心文件 fsimage 和 edits 的存放位置,如下图所示
在对应配置的 value 值有 ${},这是 变量的表示方式,ER 表达式,在程序读取文件时,会把变量的值读取出来。那么,第 150 行的变量 hadoop.tmp.dir 的值 (即 hadoop 临时存储路径),如下图所示。
但是在我们在上一章的配置文件 core-site.xml 中,配置的值是 /usr/local/hadoop/tmp。
<3> 我们可以进入 linux 文件系统
执行命令 cd /usr/local/hadoop/conf,more core-site.xml 查看,如下图所示
可以看出,这 两个文件的存储位置 是在 linux 文件系统的 /usr/local/hadoop/tmp/dfs/name 目录下。
<4> 我们进入这个目录
查看这个目录的内容,如下图所示
从图中可知,NameNode 的核心文件 fsimage 和 edits 的存放在 current 目录下,与此同时 name 目录下有一个文件 in_use.lock 而查看其内容的时候发现,内容为空,也就是说只能有一个 Namenode 进程能够访问该目录,读者可以自己试一下,当没有开启 hadoop 时,该目录下是没有文件 in_use.lock 的,当 hadoop 启动以后才会生成该文件。
<5> 文件 fsimage 是 NameNode 的核心文件
这个文件非常重要,丢失的话,Namenode 无法使用,那么如何防止该文件丢失而造成不良后果呢。我可以下再次看一下 hdfs-default.xml 中的一段代码,如下图所示
由其中的描述可知,该变量,决定 DFS NameNode 的 NameTable(fsimage)应该在本地文件系统上的存储位置。如果这是 一个用逗号分隔的列表的目录,那么 nametable,会被复复制到所有的目录中, 来冗余(备份来保证数据的安全性)。如 ${hadoop.tmp.dir}/dfs/name,~/name2,~/name3,~/name4。那么 fsimage 会分别复制到~/name1,~/name2,~/name3,~/name4 目录中。所以这些目录一般是在不同的机器, 不同的磁盘,不同的文件夹上,总之越分散越好,这样能保证数据的安全性。有人会问在多台机上怎么实现呢?其实在 Linux 中有 nfs 文件共享系统,这里不做详述。
<6> 看一下 edits 的描述
查看一下 hdfs-default.xml 中的一段代码,如下图所示
由其中的描述可知,该变量,决定 DFSNameNode 的 存储事务文件(edits)在本地文件系统上的位置。如果这是一个以逗号分隔的目录列表,那么,事务文件会被复制所有的目录中, 来冗余。默认值是 dfs.name.dir 一样。(edit 保存事务过程)
DataNode 的作用是 HDFS 中真正存储数据的。
<1> 如果一个文件非常大,比如 100GB,那么怎么存储在 DataNode 中呢?DataNode 在存储数据的时候是按照 block 为单位读写数据的。block 是 hdfs 读写数据的基本单位。
<2> 假设文件大小是 100GB,从字节位置 0 开始,每 64MB 字节划分为一个 block,依此类推,可以划分出很多的 block。每个 block 就是 64MB 大小。
2.1 我们看一下 org.apache.hadoop.hdfs.protocol.Block 类
这里面的属性有以下几个,下图所示。
由上图可知,类中的属性没有一个是可以存储数据的。所以 block 本质上是一个 逻辑概念,意味着 block 里面不会真正的存储数据,只是划分文件的。
2.2 为什么一定要划分为 64MB 大小呢?
因为这是在默认配置文件中设置的,我们查看 core-default.xml 文件,如下图所示。
上图中的参数 ds.block.name 指的就是 block 的大小,值是 67 108 864 字节,可以换算为 64MB。如果我们不希望使用 64MB 大小,可以在 core-site.xml 中覆盖该值。注意单位是字节。
2.3 副本
<1> 副本就是备份,目的当时是为了 安全。正是因为集群环境的 不可靠,所以才使用副本机制来保证数据的 安全性。
<2> 副本的缺点就是会占用大量的存储空间。副本越多,占用的空间越多。相比数据丢失的风险,存储空间的花费还是值得的。
<3> 那么,一个文件有几个副本合适呢?我们查看 hdfs-default.xml 文件,如下图所示。
从图 4.3 中可以看到,默认的副本数量是 3。意味着 HDFS 中的每个数据块都有 3 份。当然,每一份肯定会尽力分配在不同的 DataNode 服务器中。试想:如果备份的 3 份数据都在同一台服务器上,那么这台服务器停机了,是不是所有的数据都丢了啊?
3.1 DataNode 是按 block 来划分文件的
那么划分后的文件到底存放在哪里哪?我们查看文件 core-default.xml,如下图所示。
参数 dfs.data.dir 的值就是 block 存放在 linux 文件系统中的位置。变量 hadoop.tmp.dir 的值 前面已经介绍了,是 /usr/local/hadoop/tmp,那么 dfs.data.dir 的完整路径是 /usr/local/hadoop/tmp/dfs/data。通过 linux 命令查看,结果如图 4.5 所示。
3.2 上传一个文件
我们首先点击 PieTTY 打开另一个 Linux 终端,上传一个文件 jdk-6u24-linux-i586.bin,文件大小为 84927175k,如下图所示。
然后我们可以在原来终端,查看上传文件,就是在该 Linux 文件系统的 /usr/local/hadoop/tmp/dfs/data 目录下,如下图所示
上图中以“blk_”开头的文件就是 存储数据的 block。这里的命名是有规律的,除了 block 文件外,还有后 缀是“meta”的文件,这是 block 的源数据文件,存放一些元数据信息。因此,上图中只有 2 个 block 文件。
注意:我们从 linux 磁盘上传一个完整的文件到 hdfs 中,这个文件在 linux 是可以看到的,但是上传到 hdfs 后,就不会有一个对应的文件存在,而是被划分成很多的 block 存在的。而且由于我们的 hadoop 安装方式是 伪分布安装,只有一个节点,DataNode 和 NameNode 都在这一个节点上,所以上传的 block 块最终还是在该 Linux 系统中。
HA 的一个解决方案。但不支持热备。配置即可。由于数据操作越多 edits 文件膨胀越大,但不能让他无限的膨胀下去,所以要把日志过程转换出来 放到 fsimage 中。由于 NameNode 要接受用户的操作请求,必须能够快速响应用户请求,为了保证 NameNode 的快速响应给用户,所以将此项工 作交给了 SecondaryNode,所以他也备份一部分 fsimage 的一部分内容。
执行过程:从 NameNode 上 下载元数据信息(fsimage,edits),然后把二者合并,生成新的 fsimage,在本地保存,并将其推送到 NameNode,同时重置 NameNode 的 edits. 默认在安装在 NameNode 节点上,但这样 … 不安全!
合并原理 如下图所示。
![post-qrcode](https://www.xgss.net/wp-content/uploads/2023/07/二维码-微信公众号256x256.jpg)