深入理解HDFS

来源:互联网 发布:北京电信网络 编辑:程序博客网 时间:2024/06/07 07:02

1、HDFS架构
 

Namenode: 一个hdfs cluster包含一个NameNode和若干的DataNode,NameNode是master,主要负责管理HDFS文件系统,具体地包括namespace管理(其实就是目录结构),block管理(其中包括 filename->block,block->ddatanode list的对应关系)。Namenode提供的是始终被动接收服务的server,主要有三类协议接口:ClientProtocol接口、DatanodeProtocol接口、NamenodeProtocol接口。

Datanode:Datanode(简称Datanode)主要是用来存储数据文件,HDFS将一个文件分割成一个个的block,这些block可能存储在一个Datanode上或者是多个Datanode上。Datanode负责实际的底层的文件的读写,如果客户端client程序发起了读HDFS 上的文件的命令,那么首先将这些文件分成block,然后Namenode将告知client这些block数据是存储在那些Datanode上的,之后,client将直接和Datanode交互。

Secondary NameNode:  该部分主要是定时对NameNode进行数据snapshots进行备份,这样尽量降低NameNode崩溃之后,导致数据的丢失,其实所作的工作就是从Namenode获得fsimage和edits把二者重新合并然后发给Namenode,这样,既能减轻Namenode的负担又能保险地备份。

2、数据复制
 
Secondary NameNode
Secondary NameNode定期合并fsimage和edits日志,将edits日志文件大小控制在一个限度下。

Secondary NameNode处理流程
     1、namenode响应Secondary namenode请求,将edit log推送给Secondary namenode, 开始重新写一个新的edit log。
     2、Secondary namenode收到来自namenode的fsimage文件和edit log。
     3、Secondary namenode将fsimage加载到内存,应用edit log,并生成一个新的fsimage文件。
     4、Secondary namenode将新的fsimage推送给Namenode。
     5、Namenode用新的fsimage取代旧的fsimage,在fstime文件中记下检查点发生的时间点。

副本摆放策略

集群只有三个Datanode,hadoop系统replication=4时,会出现什么情况?

对于上传文件到hdfs上时,当时hadoop的副本系数是几, 这个文件的块数副本数就会有几份,无论以后你怎么更改系统副本系统,这个文件的副本数都不会改变,也就说上传到分布式系统上的文件副本数由当时的系统副本数决定,不会受replication的更改而变化,除非用命令来更改文件的副本数。因为dfs.replication实质上是client参数,在create文件时可以指定具体replication,属性dfs.replication是不指定具体replication时的采用默认备份数。文件上传后,备份数已定,修改dfs.replication是不会影响以前的文件的,也不会影响后面指定备份数的文件。只影响后面采用默认备份数的文件。但可以利用hadoop提供的命令后期改某文件的备份数:hadoop fs -setrep -R 1。如果你是在hdfs-site.xml设置了dfs.replication,这并一定就得了,因为你可能没把conf文件夹加入到你的project的classpath里,你的程序运行时取的dfs.replication可能是hdfs-default.xml里的 dfs.replication,默认是3。可能这个就是造成你为什么dfs.replication老是3的原因。你可以试试在创建文件时,显式设定replication。replication一般到3就可以了,大了意义也不大。

3、HDFS文件读写解析

文件读取流程

流程分析
    1、使用HDFS提供的客户端开发库Client,向远程的Namenode发起RPC请求;
    2、Namenode会视情况返回文件的部分或者全部block列表,对于每个block,Namenode都会返回有该block拷贝            的DataNode地址;
    3、客户端开发库Client会选取离客户端最接近的DataNode来读取block;如果客户端本身就是DataNode,那么将从本地直接获取数据.
    4、读取完当前block的数据后,关闭与当前的DataNode连接,并为读取下一个block寻找最佳的DataNode;
    5、当读完列表的block后,且文件读取还没有结束,客户端开发库会继续向Namenode获取下一批的block列表。
    6、读取完一个block都会进行checksum验证,如果读取datanode时出现错误,客户端会通知Namenode,然后再从下一个拥有该block拷贝的datanode继续读。

文件写入流程

流程分析
    1、使用HDFS提供的客户端开发库Client,向远程的Namenode发起RPC请求;
    2、Namenode会检查要创建的文件是否已经存在,创建者是否有权限进行操作,成功则会为文件创建一个记录,否则会让客户端抛出异常;
    3、当客户端开始写入文件的时候,会将文件切分成多个packets,并在内部以数据队列”data queue”的形式管理这些packets,并向Namenode申请新的blocks,获取用来存储replicas的合适的datanodes列表,列表的大小根据在Namenode中对replication的设置而定。
    4、开始以pipeline(管道)的形式将packet写入所有的replicas中。把packet以流的方式写入第一个datanode,该datanode把该packet存储之后,再将其传递给在此pipeline中的下一个datanode,直到最后一个datanode,这种写数据的方式呈流水线的形式。
    5、最后一个datanode成功存储之后会返回一个ack packet,在pipeline里传递至客户端,在客户端的开发库内部维护着”ack queue”,成功收到datanode返回的ack packet后会从”ack queue”移除相应的packet。
    6、如果传输过程中,有某个datanode出现了故障,那么当前的pipeline会被关闭,出现故障的datanode会从当前的pipeline中移除,剩余的block会继续剩下的datanode中继续以pipeline的形式传输,同时Namenode会分配一个新的datanode,保持replicas设定的数量。

流水线复制
当客户端向HDFS文件写入数据的时候,一开始是写到本地临时文件中。假设该文件的副本系数设置为3,当本地临时文件累积到一个数据块的大小时,客户端会从Namenode获取一个Datanode列表用于存放副本。然后客户端开始向第一个Datanode传输数据,第一个Datanode一小部分一小部分(4 KB)地接收数据,将每一部分写入本地仓库,并同时传输该部分到列表中的第二个Datanode节点。第二个Datanode也是这样,一小部分一小部分地接收数据,写入本地仓库,并同时传给第三个Datanode。最后,第三个Datanode接收数据并存储在本地。因此,Datanode能流水线式地从前一个节点接收数据,并在同时转发给下一个节点,数据以流水线的方式从前一个Datanode复制到下一个。

更细节的原理
客户端创建文件的请求其实并没有立即发送给Namenode,事实上,在刚开始阶段HDFS客户端会先将文件数据缓存到本地的一个临时文件。应用程序的写操作被透明地重定向到这个临时文件。当这个临时文件累积的数据量超过一个数据块的大小,客户端才会联系Namenode。Namenode将文件名插入文件系统的层次结构中,并且分配一个数据块给它。然后返回Datanode的标识符和目标数据块给客户端。接着客户端将这块数据从本地临时文件上传到指定的Datanode上。当文件关闭时,在临时文件中剩余的没有上传的数据也会传输到指定的Datanode上。然后客户端告诉Namenode文件已经关闭。此时Namenode才将文件创建操作提交到日志里进行存储。如果Namenode在文件关闭前宕机了,则该文件将丢失。

参考:

1、http://www.uml.org.cn/sjjm/201309044.asp

2、http://blog.csdn.net/happyjin2010/article/details/17887671

0 0