HDFS工作机制和原理

HDFS是一种分部式的文件系统,在他出现以前就已经存在了很多中分布式文件系统,但是他们都是部署在服务器上,需要高的POSIX接口,同时他们默认服务器是稳定的可以提供大量资源。

我们都知道HDFS来自于Google的一篇开源论文GFS,而GFS系统由许多廉价的普通组件组成,组件失效是一种常态。系统必须持续监控自身的状态,它必须将组件失效(崩掉)作为一种常态,能够迅速地侦测、冗余并恢复失效的组件。

HDFS的优点

  • 扩容能力(Scalable):Hadoop是在可用的计算机集群间分配数据并完成计算任务的,HDFS可以很容易在上面加挂主机加挂主机时并不需要停掉整个服务。
  • 成本低(Economical):Hadoop通过普通廉价的机器组成服务器集群来分发以及处理数据,以至于成本很低。
  • 高效率(Efficient):通过并发数据,Hadoop可以在节点之间动态并行的移动数据,使得速度非常快。
  • 可靠性(Rellable):能自动维护数据的多份复制,默认为3份,并且在任务失败后能自动地重新部署(redeploy)计算任务。

HDFS还有几个特性,访问的透明性,用户访问本地文件和访问远程文件是一样的。并发控制,客户端对文件的读写不应该影响其他客户端对同一个文件的读写。HDFS控制并发的原理很简单,就是任何时间都只允许一个客户端进行写的操作,当客户端要进行写操作的时候会对这个文件申请一个租约,只有组约到期才能被释放,别人才可以写。资源的移动策略是就近,若一个Map任务是对某个数据块的操作,则这个操作必定是在存储这个数据块的节点上完成的,同时HDFS支持数据的多副本(默认为3个副本),存储任一副本的节点都可以执行Map任务的操作,JobTracker会把任务分配给距离客户端最近的,且存有副本的节点。

分布式文件系统与LinuxFS系统比较

LinuxFS是HDFS底层文件系统

  • 目录树:


    360截图17860612676058.png

两种文件系统都是选择树来组织文件,HDFS目录树中包含Linux文件(Inodefile),这是由于Linux中Inode上定义Block,但是Inodefile上定义Block。

  • 数据块

LinuxFS中读写的数据块的大小相同,默认为4MB,DataNode和Block之间的关系固定、不需要系统定义。
HDFS中数据块的大小可以自定义,默认为64MB,Block和DataNode的关系是动态的需要描述管理,集群中每一个Block至少存在三个备份,且一定在不同机器上。

  • 索引节点
    Linux中采用Dentry生成目录树,同时也记录文件指向Node的映射链接,包括软硬链接。
    HDFS中不存在Dentry,所以也不支持链接。
目录是不是文件?

LinuxFS中秉承linux系统中一切皆文件的概念,LinuxFS目录是文件,这类文件记录了Dentry的上下级关系,会以Block的形式保存在外存。

HDFS的目录不是文件,目录节点INodeDirectory只是承上启下的衔接点,没有具体内容,不会以Block的形式保存在外存,目录只占内存空间。

是否支持链接?

LinuxFS支持链接,HDFS目前不支持

HDFS文件系统设计的侧重点

1.节约NameNode的内存空间。HDFS没有Dentry,NodeFile没有子节点。

2.节约NameNode的外存空间。NodeDirectory没有以一组Block形式保存在外存。

HDFS体系结构

HDFS来说,它的主节点是NameNode,从节点是DataNode,还有一个更新最新状态的SecondaryNameNode

1.NameNode:名称节点

NameNode职责:

  • 管理、维护HDFS;
  • 接收客户端的请求:上传、下载、创建目录等;
  • 维护两个非常重要的文件:edits文件 –> 记录了操作日志;fsimage文件 –> 记录HDFS元信息
那什么是edits文件和fsimages文件?

Edits文件保存了自最后一次检查点之后所有针对HDFS文件系统的操作,比如:增加文件、重命名文件、删除目录等等 都是二进制文件,HDFS提供了一个工具:edits viewer 日志查看器,可以将操作日志转化为XML格式来查看。命令如下:

hdfs oev 命令将日志(二进制)输出为XML文件 -i表示输入,-o表示输出
hdfs oev -i edits_inprogress_0000000000000000208 -o ~/a.xml

fsimage是HDFS文件系统存于硬盘中的元数据检查点,里面记录了自最后一次检查点之前HDFS文件系统中所有目录和文件的序列化信息(数据块的位置、冗余信息).
也是二进制HDFS提供了一个工具:image viewer查看器,可以将操作日志转化为文本或者XML格式来查看:

hdfs oiv 命令将日志(二进制)输出为文本文件 -i表示输入,-o表示输出
hdfs oiv -i fsimage_0000000000000000207 -o ~/b.txt (文本)
hdfs oiv -i fsimage_0000000000000000207 -o ~/c.xml -p XML(xml文件)

2.DataNode:数据节点

数据块大小:
1.x版本 64M
2.x版本 128M
一个数据块在DataNode以文件存储在磁盘上,包括两个文件,一个是数据
本身,一个是元数据包括数据块的长度,块数据的校验和,以及时间戳DataNode启动后向NameNode注册,通过后,周期性(1小时)的向NameNode上报所有的块信息 心跳是每3秒一次,心跳返回结果带有NameNode给该DataNode的命令如复制块数据到另一台机器,或删除某个数据块。如果超过10分钟没有收到某
个DataNode的心跳,则认为该节点不可用。

3.SecondaryNameNode 第二名称节点

用来监控HDFS状态的辅助后台程序,每隔一段时间获取HDFS元数据的快照。

因为namenode本身的任务就非常重要,为了不再给namenode压力,日志合并到fsimage就引入了另一个角色secondarynamenode。secondarynamenode负责定期把editslog合并到fsimage,“定期”是namenode向secondarynamenode发送RPC请求的,是按时间或者日志记录条数为“间隔”的,这样即不会浪费合并操作又不会造成fsimage和内存元数据有很大的差距。因为元数据的改变频率是不固定的。

为什么hdfs不适合存储小文件?

这是因为每一个数据文件都会在namenode在内存中存储metadata。每个小文件至少都占150bytes。所以文件的数量越多内存越吃紧。

HDFS写、读数据分析

1.写数据

客户端要向HDFS写数据,首先要跟namenode通信以确认可以写文件并获得接收文件block的datanode,然后客户端按顺序将文件逐个block传递给相应datanode,并由接收到block的datanode负责向其他datanode复制block的副本。

1.客户端向namenode发送上传文件请求,namenode对要上传目录和文件进行检查,判断是否可以上传,并向客户端返回检查结果。

2.客户端得到上传文件的允许后读取客户端配置,如果没有指定配置则会读取默认配置(例如副本数和块大小默认为3和128M,副本是由客户端决定的)。向namenode请求上传一个数据块。

3.namenode会根据客户端的配置来查询datanode信息,如果使用默认配置,那么最终结果会返回同一个机架的两个datanode和另一个机架的datanode。这称为“机架感知”策略。

机架感知:三分之一的副本在一个节点上,三分之二的副本在一个机架上,其他副本均匀分布在剩下的机架中,这一策略在不损害数据可靠性和读取性能的情况下改进了写的性能。同一个机架内的两台机器间的带宽会比不同机架的两台机器间的带宽大。

4.客户端在开始传输数据块之前会把数据缓存在本地,当缓存大小超过了一个数据块的大小,客户端就会从namenode获取要上传的datanode列表。之后会在客户端和第一个datanode建立连接开始流式的传输数据,这个datanode会一小部分一小部分(4K)的接收数据然后写入本地仓库,同时会把这些数据传输到第二个datanode,第二个datanode也同样一小部分一小部分的接收数据并写入本地仓库,同时传输给第三个datanode,依次类推。这样逐级调用和返回之后,待这个数据块传输完成客户端后告诉namenode数据块传输完成,这时候namenode才会更新元数据信息记录操作日志。

5.第一个数据块传输完成后会使用同样的方式传输下面的数据块直到整个文件上传完成。

安全模式:Namenode启动后会进入一个称为安全模式的特殊状态。处于安全模式的Namenode是不会进行数据块的复制的。

2.读数据

客户端将要读取的文件路径发送给namenode,namenode获取文件的元信息(主要是block的存放位置信息)返回给客户端,客户端根据返回的信息找到相应datanode逐个获取文件的block并在客户端本地进行数据追加合并从而获得整个文件。

1.客户端向namenode发起RPC调用,请求读取文件数据。

2.namenode检查文件是否存在,如果存在则获取文件的元信息(blockid以及对应的datanode列表)。

3.客户端收到元信息后选取一个网络距离最近的datanode,依次请求读取每个数据块。客户端首先要校检文件是否损坏,如果损坏,客户端会选取另外的datanode请求。

4.datanode与客户端简历socket连接,传输对应的数据块,客户端收到数据缓存到本地,之后写入文件。

5.依次传输剩下的数据块,直到整个文件合并完成。
HDFS会检验从Datanode获取的数据跟相应的校验和文件中的校验和是否匹配,如果不匹配,客户端可以选择从其他Datanode获取该数据块的副本.

3.删数据

当用户或应用程序删除某个文件时,这个文件并没有立刻从HDFS中删除。实际上,HDFS会将这个文件重命名转移到/trash目录。只要文件还在/trash目录中,该文件就可以被迅速地恢复。文件在/trash中保存的时间是可配置的,当超过这个时间时,Namenode就会将该文件从名字空间中删除。删除文件会使得该文件相关的数据块被释放。注意,从用户删除文件到HDFS空闲空间的增加之间会有一定时间的延迟。只要被删除的文件还在/trash目录中,用户就可以恢复这个文件。如果用户想恢复被删除的文件,他/她可以浏览/trash目录找回该文件。/trash目录仅仅保存被删除文件的最后副本。/trash目录与其他的目录没有什么区别,除了一点:在该目录上HDFS会应用一个特殊策略来自动删除文件。目前的默认策略是删除/trash中保留时间超过6小时的文件。将来,这个策略可以通过一个被良好定义的接口配置。

当一个文件的副本系数被减小后,Namenode会选择过剩的副本删除。下次心跳检测时会将该信息传递给Datanode。Datanode遂即移除相应的数据块,集群中的空闲空间加大。同样,在调用setReplication API结束和集群中空闲空间增加间会有一定的延迟。

你可能感兴趣的:(HDFS工作机制和原理)