HDFS架构和读写流程详解

来源:互联网 发布:访问服务器8080端口 编辑:程序博客网 时间:2024/05/21 10:55

一、前言
  Hadoop是一个开发和运行处理大规模数据的软件平台,是Apache的一个用Java语言实现开源软件框架,实现在大量计算机组成的集群中对海量数据进行分布式计算。用户可以在不了解分布式底层细节的情况下,开发分布式程序,充分利用集群的威力高速运算和存储。
  Hadoop框架中最核心设计就是:HDFS和MapReduce。HDFS提供了海量数据的存储,MapReduce提供了对数据的计算。HDFS在Hadoop中扮演了非常基础的作用,以文件系统的形式为上层应用提供海量数据的存储服务。
  HDFS作为一个分布式文件系统,具有高容错的特点。它可以部署在廉价的通用硬件上,提供高吞吐率(Throughput)的数据访问,特别适合那些需要处理海量数据集的应用程序。它没有遵循POSIX的要求,不支持ls,cp这样标准的UNIX命令,也不支持fopen和fread这样的文件读写方法。它采用全新的设计,提供了一套特有的,基于Hadoop抽象文件系统的API,支持以流的方式访问文件系统的数据。
  
二、基本概念
1.HDFS(Hadoop Distributed File System):
  分布式文件系统,将一个文件分成多个块,分别存储(拷贝)到不同的节点上,它是Hadoop体系中数据存储管理的基础。它是一个高度容错的系统,能检测和应对硬件故障,用于在低成本的通用硬件上运行。HDFS简化了文件的一致性模型,通过流式数据访问,提供高吞吐量应用程序数据访问功能,适合带有大型数据集的应用程序。
HDFS的特征与局限:

序号 特性 详述 1 支持超大文件 理论上,HDFS上的单个文件可以存储到整个集群的所有存储空间 2 硬件故障快速恢复 集群包含成百上千个节点,硬件故障是常见问题。故障检测和自动恢复在HDFS设计之初就是很重要的设计目标 3 流式数据访问 HDFS处理的数据规模都比较大,应用一次需要访问大量的数据。同时,这些应用一般是批量处理,而不是用户交互式处理。HDFS使应用程序能够以stream的方式访问数据集,注重的是数据的吞吐量,而不是数据访问的速度 4 简化的一致性模型 HDFS的文件一旦创建,只能追加,不能对已有数据进行修改。这样简单的一致性模型有利于提供高吞吐量的数据访问

正是由于上面的一些设计特征,因此HDFS并不适合以下应用:

序号 局限 详述 1 低延时数据访问 在用户交互性的应用中,应用需要在ms或者几个s的时间内得到响应。由于HDFS为高吞吐率做了设计,也因此牺牲了快速响应。对于低延时的应用,可以考虑使用HBase或者Cassandra 2 大量的小文件 标准的HDFS数据块大小是128M,存储小文件并不会浪费实际的存储空间,但无疑增加NN上的元数据,大量的小文件会影响整个集群的性能。前面我们知道,Btrfs为小文件做了优化-inline file,对于小文件有很好的空间优化和访问时间优化 3 多用户写入、修改文件 HDFS的文件只能有一个写入者,而且写操作只能在文件结尾以追加的方式进行。它不支持多个写入者,也不支持在文件写入后,对文件的任意位置的修改

  但是在大数据领域,分析的是已经存在的数据,这些数据一旦产生就不会修改,因此,HDFS的这些特性和设计局限也就很容易理解了。HDFS为大数据领域的数据分析,提供了非常重要而且十分基础的文件存储功能。
2.Namenode:
  NN是HDFS主从结构中主节点上运行的主要进程,它负责管理从节点DN。NN维护着整个文件系统的文件目录树,文件目录的元信息和文件的数据块索引。这些信息以两种信息保存在本文文件系统中,一种是文件系统镜像(fsimage),另一种是fsimage的编辑日志(edits)。
  fsimage中保存着某一特定时刻HDFS的目录树、元信息和文件数据块的索引等信息,后续的对这些信息的改动,则保存在编辑日志中,它们一起提供了一个完整的NN的第一关系。
  同时,通过NN,Client还可以了解到数据块所在的DN的信息。需要注意的是,NN中关于DN的信息是不会保存到NN的本地文件系统的,也就是上面提到的fsimage和edits中。NN每次启动时,都会通过每个DN的上报来动态的建立这些信息。这些信息也就构成了NN第二关系。
  另外,NN还能通过DN获取HDFS整体运行状态的一些信息,比如系统的可用空间,已经使用的空间,各个DN的当前状态等。
3.Datanode:
  DN是HDFS中硬盘IO最忙碌的部分:将HDFS的数据块写到Linux本地文件系统中,或者从这些数据块中读取数据。DN作为从节点,会不断的向NN发送心跳。初始化时,每个DN将当前节点的数据块上报给NN。NN也会接收来自NN的指令,比如创建、移动或者删除本地的数据块,并且将本地的更新上报给NN。
4.Secondary Namenode:
  SSN是用于定期合并fsimage和edits的。与NN一样,每个集群都有一个SNN,在大规模部署的条件下,一般SNN也独自占用一台服务器。SNN按照集群配置的时间间隔,不停的获取HDFS某一个时间点的fsimage和edits,合并它们得到一个新的fsimage。该fsimage上传到NN后会替换NN的老的fsimage。
  从上面可以看出,SNN会配合NN,为NN的第一关系提供了一个简单的CheckPoint机制,并避免出现edits过大,导致NN启动时间过长的问题。
  注意,SNN并不是NN的strandby。NN是HDFS集群中的SPOF(Single Point of Failure)。通过SNN,可以减少NN的启动时间并且降低NN元数据丢失的风险。但是,在HA出现前,NN的失效是要通过人工干预的。

二、HDFS架构详解
HDFS结构图
这里写图片描述
Namenode工作流程:

  1. 主节点启动NN进程,首先装载fsimage文件,然后在应用edits文件,将最新的文件系统的文件目录树,文件目录的元信息和文件的数据块索引装载到内存中。
  2. 将最新的目录树信息更新到新的fsimage文件中,然后启用新的edits文件,记录对目录结构的增加,删除,修改等操作。
  3. DN每隔3秒向NN发送一个心跳包,每隔10个心跳向NN发送一个blockreport,包含文件与block的关系、block和DN节点的关系,并存储在内存中,注意这两种关系是DN实时按blockreport汇报给NN的,不会存储在fsimage里面,也就不会存储在disk上。
  4. 当ND结点关闭的时候,也不会将fsimage与edits文件进行合并。

注意:
如果NN10分钟没有收到DN心跳,则认为其已经lost,并copy其他DN的相同副本到出现问题的DN。

副本放置策略:
第一副本:放置在上传文件的DN上,如果是集群外提交,则随机挑选一台磁盘 不太慢,CPU不太忙的节点
第二副本:放置在第一副本不同机架的节点上
第三副本:放置在第二副本相同机架的不同节点上
其他更多副本:随机放置在节点中

注意:
如果副本数设置为3,但DN机器只有2台,那整个Hadoop是不能工作存不了数据的。一个DN节点不能有两个相同内容的block。

Secondary Namenode工作图解
这里写图片描述
Secondary Namenode工作流程:

  1. SNN通知ND准备提交edits文件,此时主节点产生edits.new。
  2. SSN通过http get方式获取ND的fsimage与edits文件(在SSN的current同级目录下可见到temp.check-point或者previous-checkpoint目录,这些目录中存储着从NN拷贝来的镜像文件)。
  3. SSN开始合并获取的上述两个文件,产生一个新的fsimage文件fsimage.ckpt。
  4. SSN用http post方式发送fsimage.ckpt至ND。
  5. ND将fsimage.ckpt与edits.new文件分别重命名为fsimage与edits,然后更新fstime,整个checkpoint过程到此结束。

注意:
在新版本的Hadoop中(Hadoop0.21.0),SSN两个作用被两个节点替换,checkpoint node与backupnode。SSN备份由三个参数控制:fs.checkpoint.period控制周期,fs.checkpoint.size控制日志文件超过多少大小时合并,dfs.http.address表示http地址,这个参数在SSN为单独节点时需要设置。

HDFS文件读流程:

这里写图片描述

  1. 首先调用FileSystem对象的open方法,其实是一个DistributedFileSystem的实例。
  2. DistributedFileSystem通过RPC获得文件的第一批block的locations,同一block按照重复数(replication)会返回多个locations,这些locations按照hadoop拓扑结构排序,距离客户端近的排在前面。
  3. 前两步会返回一个FSDataInputStream对象,该对象会被封装成DFSInputStream对象,DFSInputStream可以方便的管理DN和NN数据流。客户端调用read方法,DFSInputStream最会找出离客户端最近的DN并连接。
  4. 数据从DN源源不断的流向客户端。
  5. 如果第一块的数据读完了,就会关闭指向第一块的DN连接,接着读取下一块。这些操作对客户端来说是透明的,客户端的角度看来只是读一个持续不断的流。
  6. 如果第一批block都读完了,DFSInputStream就会去NN拿下一批blocks的location,然后继续读,如果所有的块都读完,Client调用FSDataInputStream.close()方法,关闭输入流。

注意:

  • 如果在读数据的时候,DFSInputStream和DN的通讯发生异常,就会尝试正在读的block的排第二近的DN,并且会记录哪个DN发生错误,剩余的blocks读的时候就会直接跳过该DN。DFSInputStream也会检查block数据校验,如果发现一个坏的block,就会先报告到NN节点,然后DFSInputStream在其他的DN上读该block的镜像。
  • 该设计的方向就是客户端直接连接DN来检索数据并且ND来负责为每一个block提供最优的DN,ND仅仅处理block location的请求,这些信息都加载在ND的内存中,HDFS通过DN集群可以承受大量客户端的并发访问。

HDFS文件写流程:
这里写图片描述

  1. 客户端通过调用DistributedFileSystem的create方法创建新文件。
  2. DistributedFileSystem通过RPC调用ND去创建一个没有blocks关联的新文件,创建前,ND会做各种校验,比如文件是否存在,客户端有无权限去创建等。如果校验通过,ND就会记录下新文件,否则就会抛出IO异常。
  3. 前两步结束后会返回FSDataOutputStream的对象,与读文件的时候相似,FSDataOutputStream被封装成DFSOutputStream,他可以协调NN和DN。客户端开始写数据到DFSOutputStream,DFSOutputStream会把数据切成一个个小packet,然后排成队列data quene。
  4. DataStreamer会去处理接受data quene,他先问询ND这个新的block最适合存储的在哪几个DN里(参考第二小节),比如重复数是3,那么就找到3个最适合的DN,把他们排成一个pipeline,DataStreamer把packet按队列输出到管道的第一个DN中,第一个DN又把packet输出到第二个ND中,以此类推。
  5. DFSOutputStream还有一个对列叫ack quene,也是由packet组成,等待DN的收到响应,当pipeline中的所有DN都表示已经收到的时候,这时akc quene才会把对应的packet包移除掉。
  6. 客户端完成写数据后调用close方法关闭写入流。
  7. DataStreamer把剩余得包都刷到pipeline里然后等待ack信息,收到最后一个ack后,Client调用FSDataOutputStream.close()方法,关闭输出流,flush缓存区的数据包。
  8. 调用FileSystem.complete()方法,告诉NN节点写入成功。

注意:
如果在写的过程中某个datanode发生错误,会采取以下几步:
1) pipeline被关闭掉
2)为了防止防止丢包ack quene里的packet会同步到data quene里
3)把产生错误的datanode上当前在写但未完成的block删掉
4)block剩下的部分被写到剩下的两个正常的datanode中
5)NN找到另外的DN去创建这个块的复制。当然,这些操作对客户端来说是无感知的。
  另外要注意得一点,客户端执行write操作后,写完得block才是可见的,正在写的block对客户端是不可见的,只有调用sync方法,客户端才确保该文件被写操作已经全部完成,当客户端调用close方法时会默认调用sync方法。是否需要手动调用取决你根据程序需要在数据健壮性和吞吐率之间的权衡。

原创粉丝点击