HDFS笔记

按照官方文档的架构一节,进行整理和扩充。同时借鉴网上的一些资料。先对HDFS有个整体上的认知,后面的具体细节再通过源码去看。

声明:本文是基于Apache Hadoop 2.9.1文档进行总结的。

架构


写文件流程

下面这个图片总结性的描述了读文件时客户端与 HDFS 中的 namenode, datanode 之间的数据流动。


1.Client调用DistributedFileSystem对象的create方法,创建一个文件输出流(FSDataOutputStream)对象
2.通过DistributedFileSystem对象与Hadoop集群的NameNode进行一次RPC远程调用,在HDFS的Namespace中创建一个文件条目(Entry),该条目没有任何的Block
3.通过FSDataOutputStream对象,向DataNode写入数据,数据首先被写入FSDataOutputStream对象内部的Buffer中,然后数据被分割成一个个Packet数据包
4.以Packet最小单位,基于Socket连接发送到按特定算法选择的HDFS集群中一组DataNode(正常是3个,可能大于等于1)中的一个节点上,在这组DataNode组成的Pipeline上依次传输Packet。
5.这组DataNode组成的Pipeline反方向上,发送ack,最终由Pipeline中第一个DataNode节点将Pipeline ack发送给Client
6.完成向文件写入数据,Client在文件输出流(FSDataOutputStream)对象上调用close方法,关闭流
7.调用DistributedFileSystem对象的complete方法,通知NameNode文件写入成功

读文件流程

1.打开分布式文件:调用分布式文件 DistributedFileSystem.open( ) 方法;
2.寻址请求:从 NameNode 处得到 DataNode 的地址,DistributedFileSystem使用 RPC 方式调用了NameNode,NameNode 返回存有该副本的DataNode 地址,DistributedFileSystem 返回了一个输入流对象(FSDataInputStream),该对象封装了输入流 DFSInputStream;
3.连接到DataNode:调用输入流 FSDataInputStream.read( ) 方法从而让DFSInputStream 连接到 DataNodes;
4.从 DataNode 中获取数据:通过循环调用 read( ) 方法,从而将数据从 DataNode 传输到客户端;
5.读取另外的 DataNode 直到完成:到达块的末端时候,输入流 DFSInputStream 关闭与 DataNode 连接, 寻找下一个 DataNode;
6.完成读取,关闭连接:即调用输入流 FSDataInputStream.close( );

副本放置策略

简要概况起来3点:

  • 1st replica. 如果写请求方所在机器是其中一个datanode,则直接存放在本地,否则随机在集群中选择一个datanode.
  • 2nd replica. 第二个副本存放于不同第一个副本的所在的机架.
  • 3rd replica.第三个副本存放于第二个副本所在的机架,但是属于不同的节点.

如果副本数大于3,那么第四个以及后面的副本放置是随机的,但是要满足下面两个条件:

  • 1个节点最多放置一个副本
  • 一个机架不超过(replicas - 1) / racks + 2个副本

所以总的存放效果图如下所示


这里橙色区域表示的就是writer写请求者,绿色区域就是1个副本.从这里可以看出,HDFS在容错性的设计上还是做了很多的思考的.从下文开始主要分析的就是BlockPlacementPolicyDefault默认放置策略,至于BlockPlacementPolicyWithNodeGroup也会稍微提一提,但是二者主要区别其实不大.

副本选择策略

NameNode对文件的读优化的实现很简单,基本原理就是按照客户端与DataNode节点之间的距离进行排序,距客户端越近的DataNode节点越被放在前面,该算法的基本思路如下:

1.如果该Block的一个副本存在于客户端,则客户端优先从本地读取该数据块;

2.如果该Block的一个副本与客户端在同一个机架上,且没有一个副本存放在客户端,则客户端优先读取这个同机架上的副本;否则客户端优先读取同机器的副本,失败的情况下然后再优先考虑这个同机架上的副本;

3.如果该Block既没有一个副本存在客户端,又没有一个副本与客户端在同一个机架上,则随机选择一个DataNode节点作为优先节点。

安全模式

安全模式是HDFS所处的一种特殊状态,在这种状态下,文件系统只接受读数据请求,而不接受删除、修改等变更请求。在NameNode主节点启动时,HDFS首先进入安全模式,DataNode在启动的时候会向namenode汇报可用的block等状态,当整个系统达到安全标准时,HDFS自动离开安全模式。如果HDFS处于安全模式下,则文件block不能进行任何的副本复制操作,因此达到最小的副本数量要求是基于datanode启动时的状态来判定的,启动时不会再做任何复制(从而达到最小副本数量要求)。

安全模式相关的配置
系统什么时候才离开安全模式,需要满足哪些条件?当收到来自datanode的状态报告后,namenode根据配置,确定 1)可用的block占总数的比例、2)可用的数据节点数量符合要求之后,离开安全模式。如果有必要,也可以通过命令强制离开安全模式。与安全模式相关的主要配置在hdfs-site.xml文件中,主要有下面几个属性
dfs.namenode.replication.min: 最小的文件block副本数量,默认为1.
dfs.namenode.safemode.threshold-pct: 副本数达到最小要求的block占系统总block数的百分比,当实际比例超过该配置后,才能离开安全模式(但是还需要其他条件也满足)。默认为0.999f,也就是说符合最小副本数要求的block占比超过99.9%时,并且其他条件也满足才能离开安全模式。如果为小于等于0,则不会等待任何副本达到要求即可离开。如果大于1,则永远处于安全模式。
dfs.namenode.safemode.min.datanodes: 离开安全模式的最小可用(alive)datanode数量要求,默认为0.也就是即使所有datanode都不可用,仍然可以离开安全模式。
dfs.namenode.safemode.extension: 当集群可用block比例,可用datanode都达到要求之后,如果在extension配置的时间段之后依然能满足要求,此时集群才离开安全模式。单位为毫秒,默认为1.也就是当满足条件并且能够维持1毫秒之后,离开安全模式。 这个配置主要是对集群的稳定程度做进一步的确认。避免达到要求后马上又不符合安全标准。

总结一下,要离开安全模式,需要满足以下条件:
1)达到副本数量要求的block比例满足要求;
2)可用的datanode节点数满足配置的数量要求;
3) 1、2 两个条件满足后维持的时间达到配置的要求。

EditLog 和 FsImage的相关问题

fsimage:保存了最新的元数据checkpoint,包含了整个HDFS文件系统的所有目录和文件的信息(fsimage是存储在文件系统中的序列化文件)。对于文件来说包括了数据块描述信息、修改时间、访问时间等;对于目录来说包括修改时间、访问权限控制信息(目录所属用户,所在组)等。

editlog:主要是在NameNode已经启动情况下对HDFS进行的各种更新操作进行记录,HDFS客户端执行所有的写操作都会被记录到editlog中。

简单来想,NameNode维护了文件与数据块的映射表以及数据块与数据节点的映射表,什么意思呢?就是一个文件,它切分成了几个数据块,以及这些数据块分别存储在哪些datanode上,namenode一清二楚。fsimage就是在某一时刻,整个hdfs 的快照,就是这个时刻hdfs上所有的文件块和目录,分别的状态,位于哪些个datanode,各自的权限,各自的副本个数。然后客户端对hdfs所有的更新操作,比如说移动数据,或者删除数据,都会记录在editlog中。

为了避免editlog不断增大,secondary namenode会周期性合并fsimage和editlog成新的fsimage,新的操作记录会写入新的editlog中,这个周期可以自己设置(editlog到达一定大小或者定时)。
dfs.namenode.checkpoint.period
dfs.namenode.checkpoint.txns

下面介绍合并fsimage和editlog的过程


第一步:将hdfs更新记录写入一个新的文件——edits.new。
第二步:将fsimage和editlog通过http协议发送至secondary namenode。
第三步:将fsimage与editlog合并,生成一个新的文件——fsimage.ckpt。这步之所以要在secondary namenode中进行,是因为比较耗时,如果在namenode中进行,或导致整个系统卡顿。
第四步:将生成的fsimage.ckpt通过http协议发送至namenode。
第五步:重命名fsimage.ckpt为fsimage,edits.new为edits。

通信协议

客户端建立与NameNode机器建立一个可配置TCP端口的连接,客户端通过ClientProtocol 与NameNode进行通信。DataNode通过DataNode Protocol与NameNode通信。RPC将这两种协议抽象出来。特别注意的是,NameNode从不会发起任何RPC,它只是响应客户端或DataNode发起的RPC请求。

鲁棒性

  • 数据磁盘失效、心跳机制以及重备份
  • 集群再均衡
  • 数据完整性
  • 元数据磁盘失效
  • 快照

空间回收

当trash configuration使用时,在FS Shell删除的文件不会被立即的从HDFS中移除。相反,HDFS把他移动到一个垃圾箱目录下(每个用户都有自己的垃圾箱目录 /user//.Trash)。只要文件还在垃圾箱中就可以被恢复。

你可能感兴趣的:(HDFS笔记)