Hadoop - HDFS的数据流剖析
阐发文件的读取
为了理解客户端及与之交互的HDFS、namenode 和 datanode之间的数据流是什么样的
客户端经过进程调用FileSystem对象的open()方法来打开渴望读取的文件,对于HDFS来说,这个对象是分布式文件系统(图中步骤1)的一个实例。
DistributedFileSystem 经过进程利用RPC来调用namenode,以确定文件起始块的位置(步骤2)。对于每个块,namenode前去存有该块副本的datanode所在。
别的,这些datanode根据它们与客户端的距离来排序。如果该客户端本身就是一个datanode(比如,在一个MapReduce任务中),并保存有相应数据块的一个副本时,该节点就会从本地datanode读取数据。
DistributedFileSystem类前去一个FSDataInputStream对象(一个支持文件定位的数据流)给客户端并读取数据。FSDataInputStream类转而封装DFSInputStream对象,该对象管理着datanode和namenode的I/O。
接着,客户端对这个输入流调用 read()方法(步骤3)。存储着文件起始几个块的datanode所在的DFSInputStream随即连接距离最近的datanode。
经过进程对数据反复调用read()方法,可以或许将数据从datanode传输到客户端(步骤4)。到达块的末端时,DFSInputStream关闭与该datanode的连接,尔后寻找下一个块的最佳datanode(步骤5)。客户端只要要读取连续的流,并且对客户端都是透明的。
客户端从流中读取数据时,块是按照打开DFSInputStream与datanode新建连接的顺序读取的。它也会根据需要扣问namenode来检索下一批数据块的datanode的位置。一旦客户端完成读取,就对FSDataInputStream调用close()方法。
在读取数据的时候,如果DFSInputStream在与datanode通信时碰着错误,会考试考试从这个块的别的一个最邻近datanode读取数据。
它也会记取那个错误datanode,以担保往后不会反复读取该节点上后续的块。DFSInputStream也会经过进程校验和确认从datanode发来的数据可否完整。
如果创造有损坏的块,就在DFSInputStream试图从别的datanode读取其副本曩昔通知namenode。
这个筹划的一个重点是,namenode奉告客户端每个块中最佳的datanode,并让客户端间接连接到该datanode检索数据。由于数据流分散在急民众的统统datanode,以是这种筹划能使HDFS可扩展到大量的并发客户端。
同时,namenode只要要相应块位置的哀求(这些信息存储在内存中,是以异常高效),无需相应数据哀求,否则随着客户端数目标增长,namenode会很快成为瓶颈。
阐发文件的写入
接下来我们看看文件时如何写入HDFS的,尽管比较详细,但对于理解数据流还是很有用的,由于它清楚地说明了HDFS的一致模型。
我们要考虑的情况是如何新建一个文件,把数据写入该文件,最后关闭该文件。
客户端经过进程对DistributedFileSystem对象调用create()函数来新建文件。DistributedFileSystem对namenode创建一个RPC调用,在文件系统的命名空间中新建一个文件,此时该文件中还没有相应的数据。
amenode实行各种不同的检查以确保这个文件不存在和客户端有新建文件的权限。如果这些检查均经过进程,namenode就会为创建新文件记录一条记录;
否则,文件创建失败并向客户端抛出一个IOException异常。DistributedFileSystem向客户端前去一个FSDataOutputStream对象,由此客户端可以或许开始写入数据。
就像读取事件异常,FSDataOutputStream封装一个DFSoutPutstream对象,该对象负责处理datanode和namenode之间的通信。
在客户端写入数据时,DFSOutputStream将它分红一个个的数据包,并写入内部行列步队,称为“数据行列步队”(data queue)。
DataStreamer处理数据行列步队,它的任务是根据datanode列表来哀求namenode分配适合的新块来存储数据复本。这一组datanode组成一个管线——我们假设复本数为3,以是管线中有3个节点。
DataStreamer将数据包流式传输到管线中第一个datanode,该datanode存储数据包并将它发送到管线中的第二个datanode。
异常,第二个datanode存储该数据包并且发送给管线中的第三个(也是最后一个)datanote。
DFSOutputStream也维护着一个内部数据包行列步队来等待datanode的收到确认回执,称为“确认行列步队”(ack queue)。收到管道中统统datanode确认信息后,该数据包才会从确认行列步队删除。
如果数据在写入期间datanode发生错误,则实行以下把持(对写入数据的客户端是透明的)。首先关闭管线,确认把行列步队中的统统数据包都增长回数据行列步队的最前端,以确保错误节点下流的datanode不会漏掉任何一个数据包。
为存储在别的一变态datanode的往后数据结块指定一个新的标识,并将该标识传送给namenode,以便错误datanode在规复后可以或许删除存储的部分数据块。
从管线中删除错误数据节点并且把余下的数据块写入管线中别的两个变态的datanode。namenode注意到块复本量不足时,会在别的一个节点上创建一个新的复本。后续的数据块承继变态接管处理。
在一个块被写入期间可以或许会有多个datanode同时发生错误,但异常少见。只要写入了dfs.replication.min的复本数(默感到1),写把持就会成功,并且这个块可以或许在集群中异步复制,直到到达其目标复本数(dfs.replication的默认值为3)。
客户端完成数据的写入后,对数据流调用close()方法。该把持将残剩的统统数据包写入datanode管线,并在联系到namenode且发送文件写入完成旗子灯号曩昔,等待确认。
amenode已经知道文件由哪些块组成(经过进程Datastreamer哀求分配数据块),以是它在前去成功曩昔只要要等待数据块结束最小量的复制。
想知道更多关于IT行业的信息吗?想远远不如行动,行动起来,一起加入光环大数据,一起进入IT行业,跟着光环大数据的脚步,一起走进如今的互联网信息时代,带给你不一样的色彩生活——【深圳大数据培训】