Hdfs 架构浅析

本文介绍了HDFS的特点,如一次写入多次读取、适合批量处理和低成本。详细解析了HDFS的架构,包括NameNode、DataNode和SeconaryNameNode的角色和功能,特别是NameNode的元数据管理和DataNode的数据存储。还讨论了副本机制,以及HDFS的数据健壮性和读写文件原理。
摘要由CSDN通过智能技术生成

    导读:最近因工作需要,学习了下hdfs,将学习笔记分享出来,与大家共勉,也欢迎大家指正。

一、HDFS的特点

    1:一次写入,多次读取:HDFS适合一次写入多次读取的模式,不支持对文件系统进行大量的随机修改。简化数据一致性处理。
  2:适合批量处理文件,不建议大量存储小文件,其更倾向于高吞吐而不是低延迟。
  3:成本低廉,廉价的机器就可以组成一个大集群。


二、HDFS的架构

        在hadoop1.x版本中,HDFS主要有3部分组织,NameNode,DataNode,SeconaryNameNode。HDFS的架构类似于master/slave,一个NameNode,多个DataNode,而SeconaryNameNode主要是打杂用的(Hadoop2.x版本不需要SeconaryNameNode了,这个咱们后面再讲)。

   

    NameNode是整个集群的中心,管理着文件系统的元数据信息,元数据包括文件名,数据块等信息,当客户端有一个读请求过来时,首先需要和NameNode通讯获取文件对应数据块对应的Datanode信息,然后才开读取数据块并最终合并。当客户端有写请求过来时,首先NameNode会记录edits操作日志。真正的IO操作时在DataNode上执行。NameNode和DataNode通过心跳机制通讯,每个数据块默认3块副本。
  2.1 NameNode
       NameNode是hdfs的master节点,管理文件系统的命名空间和元数据,负责client读文件的处理(提供block和dataNode之间的映射关系)
   NameNode支持将文件的元数据持久化到磁盘文件,分别为fsimage(命名空间镜像)和edits(操作日志)。NameNode会周期性的和DataNode之间通过心跳机制收集数据块信息(可以抽象理解为Map<String,dataNodes>()),块状态报告包含了一个DataNode上所有的数据块的列表。从而使NameNode持有数据块和dataNode之间的映射关系,然而在hadoop1.x版本NameNode存在单点问题,一旦出现故障,整个HDFS集群将不可用。
   fsimage:元数据镜像文件(存储在磁盘,二进制文件)。存储某一时段NameNode内存元数据信息,当NameNode重启的时候,NameNode会合并edits操作到fsimage文件中然后一次性加载到内存,这样内存中就有了元数据了。所以fsimage文件非常重要,我们可以将其写入多个硬盘,如果NameNode主机发生故障,最简单的办法就是使用写入远程文件系统的fsimage副本。

   NameNode启动时的操作如图:

     由于fsimage是二进制文件,单独打开不好查看,hdfs提供了命令来查看

 hadoop oiv -i
          /usr/local/hadoop/tmp/dfs/name/current/fsimage_0000000000000002095 -o
          /hadooplog/fsimaage.xml -p XML

   表示将fsimage_0000000000000002095文件转成xml格式的fsimage.xml。

   edits:存储对文件系统的操作信息,比如创建,更新等,edits文件会随着集群的操作会越来越大,每次合并时间会越来越长,这就是一会我们要讲的secondaryNameNode的作用。

   那么如何查看edits文件呢?

hdfs oev -i
          /usr/local/hadoop/tmp/dfs/name/current/edits_0000000000000001850
          -0000000000000002030 -o /hadooplog/edit.xml

    metadata:元数据,存储在内存。
 2.2 DataNode
      DataNode是HDFS的slave节点,存储文件系统真实的数据信息,客户端对hdfs的IO操作实际是和DataNode打交道,当DataNode启动的时候,会像NameNode注册,注册通过后周期性的像NameNode汇报块信息,同时NameNode通过心跳检测来判断DataNode是否存活,如果DataNode故障会将该节点上的数据块转移到其它可用的DataNode节点.
 2.3 SeconaryNameNode
     前面我们提到,fsiamge和edits文件每次在NameNode重启的时候会合并一次然后加载在内存中,随机集群运行时间的不断加长,加上NameNode不可能总是重启,那么就会有几个问题
     1、edits文件越来越大,如何维护
     2、如果依靠NameNode重启来合并文件,edits越大,重启时间越长
     为了克服这些问题,SeconaryNameNode就出现了,它是NN的一个助手,定期通过http get的方式获取NN上的fsiamge和edits文件进行合并,然后通过http post的方式将最新的文件给NN,最后NN利用最新的fsimage替换旧fsiamge。

    其工作图如下:

   

 

三、副本

     hdfs为了数据的可靠性引进了副本机制,一个数据块默认有3块副本,并且每块副本存放在不同的节点上,副本的存放依赖于机架感知功能
    第一个副本默认放在客户端节点所在的节点上(rack1/01.node)
    第二个副本放在不同于第一个节点机架的某个节点上(rack2/01.node)
    第三个副本放在不同于第二个节点不同集群的某个节点(rack1/02.node)
    更多的副本随机存储
 3.1 副本选择
     当客户端需要读取文件的时候,首先需要向NN获取对应的元数据,NN会告知客户端数据块和DataNode的映射关系,
    比如一个文件有256M就是有2个block,返回的时候类似
    Map<String,String> map = new ConcurrentHashMap<String,String>();
    map.put("block1","node1,node2");
    map.put("block2","node1,node2");
    hdfs实现肯定不是这样,大家可以这样去想象,然后客户端会依次读取数据块直到将文件所对应的数据块读取完。
   其实NameNode在返回给客户端数据对应的DataNode的时候已经进行了排序
   1.将离客户端最近的DataNode排在前面
   2.客户端机架上的其他副本节点
   3.同一个数据中心集群的其他节点副本
   4.不同数据中心集群节点副本

      比如有如下的集群环境

   

    其中数据中心C1下面的集群RK1下面的D1,D2,D3是同一个机架下,客户端在读取数据的时候,假如客户端就在C1/RK1/D1那么它就会优先读取D1上的数据副本。
 四、HDFS的数据健壮性
   1.NameNode出错
    NamoNode出错一般是元数据损坏,HDFS支持配置多个Fsimage和edits的拷贝,任何对FsImage或者Editlog的修改,都将同步到它们的副本上。
  2.DataNode出错
     Datanode出错可能引起一些block的副本数目低于指定值,NameNode不断地跟踪需要复制的 block,在任何需要的情况下启动复制。
  3、其它网络原因
     主要通过NN的心跳机制实现,标记一些失效的节点,复制block到其他节点上。

五、HDFS写文件原理

   hadoop RPC的函数之间调用主要是通过JAVA的动态代理和反射机制实现,而网络层则是通过tcp/ip进行通信,而hdfs的文件上传主要也是通过hadoop的rpc机制实现。

   当客户端需要上传一个文件的时候,主要执行下面几步操作:

  1、首先需要初始化一个DistributeFileSystem,DistributeFileSystem对象通过RPC和NameNode进行通信,首先NameNode需要将客户端的写操作记录在edit.log里面,然后返回给客户端分配给它的DataNode列表(哪些DataNode可用),DistributedFileSystem返回DFSOutputStream给客户端开始写数据。

  2、DFSOutputStream准备写数据:首先其会将数据根据配置的数据块大小进行分块存储在dataQueue队列里面(比如一个256M的数据块会被分为2个block),然后Data Streamer开始读取数据块写入DataNode。根据备份数和NameNode返回的DataNode列表构成一个管道线(比如备份数是3,那么这个管道线里面就有3个DataNode),当第一个DataNode写入成功后开始复制操作,即第一个复制到第二个DataNode,第二个DataNode复制block到第三个DataNode,当一个block写入成功后,ackQueue会移除这个block,这样一个数据块就写入成功了,然后依次写入第二个直到该文件被成功上传。当我们在写入的过程中失败了,那么ackQueue也会移除block并把其重新放到dataQueue的队首重新开始写入。在一个管道中,假如有3台DataNode机器,1->2->3,当某台机器宕机后,在还在正常运行的datanode上的当前block上做一个标志,这样当宕掉的datanode重新启动以后namenode就会知道该datanode上哪个block是刚才宕机时残留下的局部损坏block,从而可以把它删掉,根据备份数,nameNode知道目前管道里面的dataNode不足,就会再找一个节点加入到管道里面,后续数据的写入继续。

六、HDFS读文件原理

     hdfs文件的读取比文件的写入要简单很多,主要分为以下几步:

    1、客户端通过调用FileSystem对象的open()方法来打开文件。

    2、DistributedFileSystem通过RPC调用询问NameNode来得到此文件最开始几个block的文件位置。对每一个block来说,namenode返回拥有此block备份的所有datanode的地址信息。如果客户端本身就是一个datanode(如客户端是一个mapreduce任务)并且此datanode本身就有所需文件block的话,客户端便从本地读取文件。
   3、以上步骤完成后,DistributedFileSystem会返回一个FSDataInputStream客户端可以从FSDataInputStream中读取数据。FSDataInputStream包装了一个DFSInputSteam类,用来处理namenode和datanode的I/O操作。
   4、客户端然后执行read()方法,DFSInputStream连接到第一个datanode(也即最近的datanode)来获取数据。通过重复调用read()方法,文件内的数据就被流式的送到了客户端。当读到该block的末尾时,DFSInputStream就会关闭指向该block的流,转而找到下一个block的位置信息然后重复调用read()方法继续对该block的流式读取。
   5、当整个文件读取完毕时,客户端调用FSDataInputSteam中的close()方法关闭文件输入流。
   6、如果在读某个block是DFSInputStream检测到错误,DFSInputSteam就会连接下一个datanode以获取此block的其他备份,同时他会记录下以前检测到的坏掉的datanode以免以后再无用的重复读取该datanode。DFSInputSteam也会检查从datanode读取来的数据的校验和,如果发现有数据损坏,它会把坏掉的block报告给namenode同时重新读取其他datanode上的其他block备份。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值