HDFS架构与原理浅析

当需要存储的数据集的大小超过了一台独立的物理计算机的存储能力时,就需要对数据进行分区并存储到若干台计算机上去。管理网络中跨多台计算机存储的文件系统统称为分布式文件系统(distributed fileSystem)

分布式文件系统由于其跨计算机的特性,所以依赖于网络的传输,势必会比普通的本地文件系统更加复杂,比如:如何使得文件系统能够容忍节点的故障并且保证不丢失数据,这就是一个很大的挑战。

(一)HDFS简介

HDFS(Hadoop Distributed File System)是hadoop生态系统的一个重要组成部分,是hadoop中的的存储组件,在整个Hadoop中的地位非同一般,是最基础的一部分,因为它涉及到数据存储,MapReduce等计算模型都要依赖于存储在HDFS中的数据。HDFS是一个分布式文件系统,以流式数据访问模式存储超大文件,将数据分块存储到一个商业硬件集群内的不同机器上。

这里重点介绍其中涉及到的几个概念:

  1. 超大文件。目前的hadoop集群能够存储几百TB甚至PB级的数据。
  2. 流式数据访问。HDFS的访问模式是:一次写入,多次读取,更加关注的是读取整个数据集的整体时间。
  3. 商用硬件。HDFS集群的设备不需要多么昂贵和特殊,只要是一些日常使用的普通硬件即可,正因为如此,hdfs节点故障的可能性还是很高的,所以必须要有机制来处理这种单点故障,保证数据的可靠。
  4. 不支持低时间延迟的数据访问。hdfs关心的是高数据吞吐量,不适合那些要求低时间延迟数据访问的应用。
  5. 单用户写入,不支持任意修改。hdfs的数据以读为主,只支持单个写入者,并且写操作总是以添加的形式在文末追加,不支持在任意位置进行修改。

1.HDFS数据块

每个磁盘都有默认的数据块大小,这是文件系统进行数据读写的最小单位。这涉及到磁盘的相应知识,这里我们不多讲。

HDFS同样也有数据块的概念,默认一个块(block)的大小为128MB(HDFS的块这么大主要是为了最小化寻址开销),要在HDFS中存储的文件可以划分为多个分块,每个分块可以成为一个独立的存储单元。与本地磁盘不同的是,HDFS中小于一个块大小的文件并不会占据整个HDFS数据块

对HDFS存储进行分块有很多好处:

  1. 一个文件的大小可以大于网络中任意一个磁盘的容量,文件的块可以利用集群中的任意一个磁盘进行存储。
  2. 使用抽象的块,而不是整个文件作为存储单元,可以简化存储管理,使得文件的元数据可以单独管理。
  3. 冗余备份。数据块非常适合用于数据备份,进而可以提供数据容错能力和提高可用性。每个块可以有多个备份(默认为三个),分别保存到相互独立的机器上去,这样就可以保证单点故障不会导致数据丢失。

2.namenode和datanode

HDFS集群的节点分为两类:namenode和datanode,以管理节点-工作节点的模式运行,即一个namenode和多个datanode,理解这两类节点对理解HDFS工作机制非常重要。

namenode作为管理节点,它负责整个文件系统的命名空间,并且维护着文件系统树和整棵树内所有的文件和目录,这些信息以两个文件的形式(命名空间镜像文件和编辑日志文件)永久存储在namenode 的本地磁盘上。除此之外,同时,namenode也记录每个文件中各个块所在的数据节点信息,但是不永久存储块的位置信息,因为块的信息可以在系统启动时重新构建。

datanode作为文件系统的工作节点,根据需要存储并检索数据块,定期向namenode发送他们所存储的块的列表。

由此可见,namenode作为管理节点,它的地位是非同寻常的,一旦namenode宕机,那么所有文件都会丢失,因为namenode是唯一存储了元数据、文件与数据块之间对应关系的节点,所有文件信息都保存在这里,namenode毁坏后无法重建文件。因此,必须高度重视namenode的容错性。

元数据是指从信息资源中抽取出来的用于说明其特征、内容的结构化的数据(如题名,版本、出版数据、相关说明,包括检索点等),用于组织、描述、检索、保存、管理信息和知识资源。

为了使得namenode更加可靠,hadoop提供了两种机制:

  1. 第一种机制是备份那些组成文件系统元数据持久状态的文件,比如:将文件系统的信息写入本地磁盘的同时,也写入一个远程挂载的网络文件系统(NFS),这些写操作实时同步并且保证原子性。
  2. 第二种机制是运行一个辅助namenode,用以保存命名空间镜像的副本,在namenode发生故障时启用。(也可以使用热备份namenode代替辅助namenode)。

3.块缓存

数据通常情况下都保存在磁盘,但是对于访问频繁的文件,其对应的数据块可能被显式的缓存到datanode的内存中,以堆外缓存的方式存在,一些计算任务(比如mapreduce)可以在缓存了数据的datanode上运行,利用块的缓存优势提高读操作的性能。

4.联邦HDFS

namenode在内存中保存了文件系统中每个文件和每个数据块的引用关系,这意味着,当文件足够多时,namenode的内存将成为限制系统横向扩展的瓶颈。hadoop2.0引入了联邦HDFS允许系统通过添加namenode的方式实现扩展,每个namenode管理文件系统命名空间中的一部分,比如:一个namenode管理/usr下的文件,另外一个namenode管理/share目录下的文件。

5.HDFS的高可用性

通过备份namenode存储的文件信息或者运行辅助namenode可以防止数据丢失,但是依旧没有保证了系统的高可用性。一旦namenode发生了单点失效,那么必须能够快速的启动一个拥有文件系统信息副本的新namenode,而这个过程需要以下几步:

(1)将命名空间的副本映像导入内存 (2)重新编辑日志 (3)接收足够多来自datanode的数据块报告,从而重建起数据块与位置的对应关系。

上述实际上就是一个namenode的冷启动过程,但是在数据量足够大的情况下,这个冷启动可能需要30分钟以上的时间,这是无法忍受的。

Hadoop2.0开始,增加了对高可用性的支持。采用了双机热备份的方式。同时使用一对活动-备用namenode,当活动namenode失效后,备用namenode可以迅速接管它的任务,这中间不会有任何的中断,以至于使得用户根本无法察觉。

为了实现这种双机热备份,HDFS架构需要作出以下几个改变:

  1. 两个namenode之间要通过高可用共享存储来实现编辑日志的共享
  2. datanode要同时向两个namenode发送数据块的报告信息
  3. 客户端要使用特定机制来处理namenode的失效问题
  4. 备用namenode要为活动namenode设置周期性的检查点,从中判断活动namenode是否失效

HDFS系统中运行着一个故障转移控制器,管理着将活动namenode转移为备用namenode的转换过程。同时,每一个namenode也运行着一个轻量级的故障转移控制器,主要目的就是监视宿主namenode是否失效,并在失效时实现迅速切换。

(二)HDFS详解

我们前面已经知道了HDFS是一个分布式的文件系统,具体这个分布式文件系统是如何实现的呢?

DFS的全称是Hadoop Distributed File System ,Hadoop的 分布式 文件 系统

它是一种允许文件通过网络在多台主机上分享的文件系统,可以让多台机器上的多个用户分享文件和存储空间

其实分布式文件管理系统有很多,HDFS只是其中一种实现而已

还有 GFS(谷歌的)、TFS(淘宝的)、S3(亚马逊的)

为什么会有多种分布式文件系统呢?这样不是重复造轮子吗?

不是的,因为不同的分布式文件系统的特点是不一样的,HDFS是一种适合大文件存储的分布式文件系统,不适合小文件存储,什么叫小文件,例如,几KB,几M的文件都可以认为是小文件

1.HDFS的Shell介绍

针对HDFS,我们可以在shell命令行下进行操作,就类似于我们操作linux中的文件系统一样,但是具体命令的操作格式是有一些区别的

格式如下:

使用hadoop bin目录的hdfs命令,后面指定dfs,表示是操作分布式文件系统的,这些属于固定格式

HDFS的schemahdfsauthority集群中namenode所在节点的ip和对应的端口号,把ip换成主机名也是一样的,path是我们要操作的文件路径信息

其实后面这一长串内容就是core-site.xml配置文件中fs.defaultFS属性的值,这个代表的是HDFS的地址

bin/hdfs dfs -ls / # 看hdfs根目录下的内容,功能类似于 -ls hdfs://bigdata01:9000/
bin/hdfs dfs -put README.txt / # 从本地上传文件
bin/hdfs dfs -cat /README.txt # 查看HDFS文件内容
bin/hdfs dfs -get /README.txt README.txt.bak # 下载文件到本地,并重命名
bin/hdfs dfs -rm -r /README.txt # 删除文件/文件夹
bin/hdfs dfs -mkdir -p /abc/test # 创建文件夹

其实后面hdfs的url这一串内容在使用时默认是可以省略的,因为hdfs在执行的时候会根据HADOOP_HOME自动识别配置文件中的fs.defaultFS属性

2.HDFS体系结构

HDFS支持主从结构,主节点称为 NameNode ,是因为主节点上运行的有NameNode进程,NameNode支持多个,目前我们的集群中只配置了一个从节点称为 DataNode ,是因为从节点上面运行的有DataNode进程,DataNode支持多个。HDFS中还包含一个 SecondaryNameNode 进程,这个进程从字面意思上看像是第二个NameNode的意思,其实不是。

在这大家可以这样理解:

  • 公司BOSS:NameNode
  • 秘书:SecondaryNameNode
  • 员工:DataNode

3.NameNode介绍

首先是NameNode,NameNode是整个文件系统的管理节点

它主要维护着整个文件系统的文件目录树,文件/目录的信息 和 每个文件对应的数据块列表,并且还负责接收用户的操作请求

  • 目录树:表示目录之间的层级关系,就是我们在hdfs上执行ls命令可以看到的那个目录结构信息。
  • 文件/目录的信息:表示文件/目录的的一些基本信息,所有者 属组 修改时间 文件大小等信息
  • 每个文件对应的数据块列表:如果一个文件太大,那么在集群中存储的时候会对文件进行切割,这个时候就类似于会给文件分成一块一块的,存储到不同机器上面。所以HDFS还要记录一下一个文件到底被分了多少块,每一块都在什么地方存储着

我们现在可以到集群的9870界面查看一下,随便找一个文件看一下,点击文件名称,可以看到Block information 但是文件太小,只有一个块 叫Block 0

NameNode主要包括以下文件:

这些文件所在的路径是由hdfs-default.xmldfs.namenode.name.dir属性控制的

hdfs-default.xml文件在哪呢?

它在hadoop-3.2.0\share\hadoop\hdfs\hadoop-hdfs-3.2.0.jar中,这个文件中包含了HDFS相关的所有默认参数,我们在配置集群的时候会修改一个hdfs-site.xml文件,hdfs-site.xml文件属于hdfs-default.xml的一个扩展,它可以覆盖掉hdfs-default.xml中同名的参数。

<property>
  <name>dfs.namenode.name.dir</name>
  <value>file://${hadoop.tmp.dir}/dfs/name</value>
</property>

这个属性的值是由hadoop.tmp.dir属性控制的,这个属性的值默认在core-default.xml文件中。大家还有没有印象,我们在修改core-site.xml的时候设置的有hadoop.tmp.dir属性的值,值是/root/test_hadoop/tmp,所以说core-site.xml中的hadoop.tmp.dir属性会覆盖掉core-default.xml中的值,最终dfs.namenode.name.dir属性的值就是:root/test_hadoop/tmp/dfs/name

  • fsimage: 元数据镜像文件,存储某一时刻NameNode内存中的元数据信息,就类似是定时做了一个快照操作。【这里的元数据信息是指文件目录树、文件/目录的信息、每个文件对应的数据块列表】

  • edits: 操作日志文件【事务文件】,这里面会实时记录用户的所有操作

  • seentxid: 是存放transactionId的文件,format之后是0,它代表的是namenode里面的edits*文件的尾数,namenode重启的时候,会按照seen_txid的数字,顺序从头跑edits_0000001~到seen_txid的数字。如果根据对应的seen_txid无法加载到对应的文件,NameNode进程将不会完成启动以保护数据一致性。

  • VERSION:保存了集群的版本信息

4.SecondaryNameNode介绍

SecondaryNameNode主要负责定期的把edits文件中的内容合并到fsimage中

这个合并操作称为checkpoint,在合并的时候会对edits中的内容进行转换,生成新的内容保存到fsimage文件中。

  • 注意:在NameNode的HA架构中没有SecondaryNameNode进程,文件合并操作会由standby NameNode负责实现

所以在Hadoop集群中,SecondaryNameNode进程并不是必须的。

5.DataNode介绍

DataNode是提供真实文件数据的存储服务

针对datanode主要掌握两个概念,一个是block,一个是replication

首先是block

HDFS会按照固定的大小,顺序对文件进行划分并编号,划分好的每一个块称一个Block,HDFS默认Block大小是 128MB

Blokc块是HDFS读写数据的基本单位,不管你的文件是文本文件 还是视频 或者音频文件,针对hdfs而言 都是字节。

我们之前上传的一个user.txt文件,他的block信息可以在fsimage文件中看到,也可以在hdfs web界面上面看到, 里面有block的id信息,并且也会显示这个数据在哪个节点上面

datanode中数据的具体存储位置是由dfs.datanode.data.dir来控制的

<property>
  <name>dfs.datanode.data.dir</name>
  <value>file://${hadoop.tmp.dir}/dfs/data</value>
</property>

下面看一下副本

副本表示数据有多少个备份

我们现在的集群有两个从节点,所以最多可以有2个备份,这个是在hdfs-site.xml中进行配置的,dfs.replication

默认这个参数的配置是3。表示会有3个副本。

副本只有一个作用就是保证数据安全。

6.NameNode总结

注意:block块存放在哪些datanode上,只有datanode自己知道,当集群启动的时候,datanode会扫描自己节点上面的所有block块信息,然后把节点和这个节点上的所有block块信息告诉给namenode。这个关系是每次重启集群都会动态加载的【这个其实就是集群为什么数据越多,启动越慢的原因】

namenode维护了两份关系:

  • 第一份关系:file 与block list的关系,对应的关系信息存储在fsimage和edits文件中,当NameNode启动的时候会把文件中的元数据信息加载到内存中

  • 第二份关系:datanode与block的关系,对应的关系主要在集群启动的时候保存在内存中,当DataNode启动时会把当前节点上的Block信息和节点信息上报给NameNode

注意了,刚才我们说了NameNode启动的时候会把文件中的元数据信息加载到内存中,然后每一个文件的元数据信息会占用150字节的内存空间,这个是恒定的,和文件大小没有关系,咱们前面在介绍HDFS的时候说过,HDFS不适合存储小文件,其实主要原因就在这里,不管是大文件还是小文件,一个文件的元数据信息在NameNode中都会占用150字节,NameNode节点的内存是有限的,所以它的存储能力也是有限的,如果我们存储了一堆都是几KB的小文件,最后发现NameNode的内存占满了,确实存储了很多文件,但是文件的总体大小却很小,这样就失去了HDFS存在的价值

7.HDFS的回收站

HDFS会为每一个用户创建一个回收站目录:/user/用户名/.Trash/,每一个被用户在Shell命令行删除的文件/目录,会进入到对应的回收站目录中,在回收站中的数据都有一个生存周期,也就是当回收站中的文件/目录在一段时间之内没有被用户恢复的话,HDFS就会自动的把这个文件/目录彻底删除,之后,用户就永远也找不回这个文件/目录了。

默认情况下hdfs的回收站是没有开启的,需要通过一个配置来开启,在core-site.xml中添加如下配置,value的单位是分钟,1440分钟表示是一天的生存周期

<property>
    <name>fs.trash.interval</name>
    <value>1440</value>
</property>

回收站的文件也是可以下载到本地的。其实在这回收站只是一个具备了特殊含义的HDFS目录。

注意:如果删除的文件过大,超过回收站大小的话会提示删除失败 需要指定参数 -skipTrash ,指定这个参数表示删除的文件不会进回收站

8.HDFS的安全模式

大家在平时操作HDFS的时候,有时候可能会遇到这个问题,特别是刚启动集群的时候去上传或者删除文件,会发现报错,提示NameNode处于safe mode。

这个属于HDFS的安全模式,因为在集群每次重新启动的时候,HDFS都会检查集群中文件信息是否完整,例如副本是否缺少之类的信息,所以这个时间段内是不允许对集群有修改操作的,如果遇到了这个情况,可以稍微等一会,等HDFS自检完毕,就会自动退出安全模式。

或者通过hdfs命令也可以查看当前的状态

bin/hdfs dfsadmin -safemode get 

Safe mode is OFF

 

posted @ 2023-05-23 20:47  ImreW  阅读(222)  评论(0编辑  收藏  举报