HDFS的优缺点和读、写数据流程详解

目录

一、hadoop的运行模式

1. 本地运行模式

2. 伪分布式运行模式

3. 完全分布式运行模式(开发重点)

二、hdfs的优缺点

1. hdfs的优点

2. hdfs的缺点

三、hdfs的读写流程

1. hdfs的写入流程

2. hdfs的读取流程


一、hadoop的运行模式

1. 本地运行模式

  • 无需任何守护进程,所有的程序都运行在同一个JVM上执行。在独立模式下调试MR程序非常高效方便。所以一般该模式主要是在学习或者开发阶段调试使用

2. 伪分布式运行模式

  • Hadoop守护进程运行在本地机器上,模拟一个小规模的集群,换句话说,可以配置一台机器的Hadoop集群,伪分布式是完全分布式的一个特例。

3. 完全分布式运行模式(开发重点)

  • Hadoop守护进程运行在一个集群上,需要使用多台机器来实现完全分布式服务的安装

二、hdfs的优缺点

1. hdfs的优点

(1) 高容错性

1) 数据自动保存多个副本。它通过增加副本的形式,提高容错性。

2) 某一个副本丢失以后,它可以自动恢复,这是由 HDFS 内部机制实现的,我们不必关心。

(2) 适合批处理

1) 它是通过移动计算而不是移动数据。

2) 它会把数据位置暴露给计算框架。

(3) 适合大数据处理

1) 数据规模:能够处理数据规模达到 GB、TB、甚至PB级别的数据。

2) 文件规模:能够处理百万规模以上的文件数量,数量相当之大。

3) 节点规模:能够处理10K节点的规模。

(4) 流式数据访问

1) 一次写入,多次读取,不能修改,只能追加。

2) 它能保证数据的一致性。

(5) 可构建在廉价机器上

1) 它通过多副本机制,提高可靠性。

2) 它提供了容错和恢复机制。比如某一个副本丢失,可以通过其它副本来恢复。

2. hdfs的缺点

(1) 不适合低延时数据访问;

1) 比如毫秒级的来存储数据,这是不行的,它做不到。

2) 它适合高吞吐率的场景,就是在某一时间内写入大量的数据。但是它在低延时的情况 下是不行的,比如毫秒级以内读取数据,这样它是很难做到的。

(2) 无法高效的对大量小文件进行存储

1) 存储大量小文件的话,它会占用 NameNode大量的内存来存储文件、目录和块信息。这样是不可取的,因为NameNode的内存总量是有限的。

2) 小文件存储的寻道时间会超过读取时间,它违反了HDFS的设计目标。 改进策略

(3) 并发写入、文件随机修改

1) 一个文件只能有一个写,不允许多个线程同时写。

2) 仅支持数据 append(追加),不支持文件的随机修改。

三、hdfs的读写流程

1. hdfs的写入流程

HDFS的优缺点和读、写数据流程详解

文件上传流程如下:

  • 创建文件:

  • ①HDFS client向HDFS写入数据,先调用DistributedFileSystem.create()

  • ②RPC调用namenode的create(),会在HDFS目录树中指定的路径,添加新文件;并将操作记录在edits.log中 namenode.create()方法执行完后,返回一个FSDataOutputStream,它是DFSOutputStream的包装类

  • 建立数据流管道pipeline

  • ③client调用DFSOutputStream.write()写数据(先写第一个块的数据,暂时叫blk1)

  • ④DFSOutputStream通过RPC调用namenode的addBlock,向namenode申请一个空的数据块block

  • ⑤addBlock返回LocatedBlock对象;此对象中包含了当前blk要存储在哪三个datanode的信息,比如dn1、dn2、dn3

  • ⑥客户端,根据位置信息,建立数据流管道(图中蓝色线条)

  • 向数据流管道写当前块的数据

  • ⑦写数据时,先将数据写入一个检验块chunk中,写满512字节后,对此chunk计算校验和checksum值(4字节)

  • ⑧然后将chunk及对应校验和写入packet中,一个packet是64KB

  • ⑨随着源源不断的带校验和的chunk写入packet,当packet写满后,将packet写入dataqueue数据队列中

  • ⑩packet从队列中取出,沿pipeline发送到dn1,再从dn1发送到dn2,再从dn2发送到dn3

  • ⑪同时,此packet会保存一份到一个确认队列ack queue中

  • ⑫packet到达最后一个datanode即dn3后,做校验,将校验结果逆着pipeline方向回传到客户端,具体是校验结果从dn3传到dn2,dn2也会做校验,校验结果再 传到dn1,dn1也做校验;结果再传回客户端

  • ⑬客户端根据校验结果,如果“成功”,则将将保存在ack queue中的packet删除;如果失败,则将packet取出,重新放回到data queue末尾,等待再次沿pipeline发送

  • ⑭如此,将block中的一个数据一个个packet发送出去;当此block发送完毕, 即dn1、dn2、dn3都接受了blk1的完整的副本,那么三个dn分别RPC调用namenode的blockReceivedAndDeleted(), namenode会更新内存中block与datanode的对应关系(比如dn1上多了一个blk1副本)

  • 关闭dn1、dn2、dn3构建的pipeline;且文件还有下一个块时,再从④开始;直到文件全部数据写完

  • ⑮最终,调用DFSOutputStream的close()

  • ⑯客户端调用namenode的complete(),告知namenode文件传输完成

写数据——容错

如果当前的pipeline是由dn1、dn2、dn3构成的,那么在传输数据的过程中,dn2挂了或通信不畅导致当前pipeline中断,HDFS会如何做?

  • 先将ack queue中的所有packet全部放回到data queue中

  • 客户端RPC调用namenode的updateBlockForPipeline(),为当前block(假设是blk1)生成新的版本比如ts1(本质是时间戳) 故障dn2会从pipeline中删除

  • DFSOutputStream再RPC调用namenode的getAdditionalDatanode(),让namenode分配新的datanode,比如是dn4 输出流将原dn1、dn3与新的dn4组成新的管道,他们上边的blk1版本设置为新版本ts1

  • 由于新添加的dn4上没有blk1的数据,客户端告知dn1或dn3,将其上的blk1的数据拷贝到dn4上 新的数据管道建立好后,DFSOutputStream调用updatePipeline()更新namenode元数据 至此,pipeline恢复,客户端按正常的写入流程,完成文件的上传

  • 故障datanode重启后,namenode发现它上边的block的blk1的时间戳是老的,会让datanode将blk1删除掉

HDFS的优缺点和读、写数据流程详解

2. hdfs的读取流程

HDFS的优缺点和读、写数据流程详解

文件读取流程如下:

  • 1、client端读取HDFS文件,client调用文件系统对象DistributedFileSystem的open方法

  • 2、返回FSDataInputStream对象(对DFSInputStream的包装)

  • 3、构造DFSInputStream对象时,调用namenode的getBlockLocations方法,获得file的开始若干block(如blk1, blk2, blk3, blk4)的存储datanode(以下简称dn)列表;针对每个block的dn列表,会根据网络拓扑做排序,离client近的排在前;

  • 4、调用DFSInputStream的read方法,先读取blk1的数据,与client最近的datanode建立连接,读取数据

  • 5、读取完后,关闭与dn建立的流

  • 6、读取下一个block,如blk2的数据(重复步骤4、5、6)

  • 7、这一批block读取完后,再读取下一批block的数据(重复3、4、5、6、7)

  • 8、完成文件数据读取后,调用FSDataInputStream的close方法

读数据——容错

  • 情况一:读取block过程中,client与datanode通信中断

    • client与存储此block的第二个datandoe建立连接,读取数据

    • 记录此有问题的datanode,不会再从它上读取数据

  • 情况二:client读取block,发现block数据有问题

    • client读取block数据时,同时会读取到block的校验和,若client针对读取过来的block数据,计算检验和,其值与读取过来的校验和不一样,说明block数据损坏

    • client从存储此block副本的其它datanode上读取block数据(也会计算校验和)

    • 同时,client会告知namenode此情况;