文档章节

HDFS分布式文件系统(3) HDFS数据流

为为02
 为为02
发布于 2017/02/13 21:37
字数 2170
阅读 362
收藏 11

数据流

HDFS是hadoop最常用的分布式文件系统,分布式文件系统操作的工作对象就是数据,本文主要讲述hadoop中数据流的基本知识概念,了解客户端与HDFS,namenode,datanode之间的数据到底是如何传递的。

1. 文件读取

客户端通过调用FileSystem对象的open()方法来打开希望读取的文件,对于HDFS来说,这个对象是分布式u文件系统(图2步骤1)的一个实例.DistributedFileSystem通过使用RPC来调用namenode,以确定文件文件的起始块位置(步骤2)。对于每一块,namenode返回存有该块副本的datanode地址。此外,这些datanode根据它们与客户端的距离来排序(根据集群的网络拓扑)如果该客户端本身就是一个datanode(比如在一个MapReduce任务中),并保存有相应的数据块的一个副本时,该节点就会从本地datanode直接读取数据。

hdfs图片读取顺序 图2

DistributedFileSystem类返回一个FSDataInputStream对象(一个支持文件定位的输入流)给客户端并读取数据。FSDataInputStream类转而封装DFSInpuStream对象,该对象管理着datanode和namenode的I/O。 接着,客户端对这个输入流调用read()方法(步骤3)。存储着文件的起始几个块的datanode地址的DFSInputStream随即连接距离最近的datanode。通过对数据流的反复调用read()方法,可以将数据从datanode传输到客户端(步骤4)。到达块的尾端时,DFSInputStream关闭与该datanode的连接,然后寻找下一个最佳datanode(步骤5)。客户端只需要读取连续的流,并且对于客户端来说都是透明的。 客户端从流中读取数据时,块是按照打开DFSInputStream与datanode的顺序读取的。它也会根据需要询问namenode来检索下一批数据块的datanode的位置。一旦客户端完成读取,就对FSDataInputStream的close()方法(步骤6)。

在读取数据的时候,如果DFSInputStream在与datanode通信时遇到错误,会尝试从这个块的另外一个最临近的datanode读取数据。它也记住那个故障datanode,以保证以后不会反复读取该节点上后续的块。DFSInputStream也会通过校验和确认同datanode发来的数据是否完整。如果发现有损坏的块,就在DFSInputStream试图从其它datanode读取其副本之前通知namenode。

这个设计的重点是:namenode告诉客户端每个块中最佳的datanode,并让客户端直接连接到该datanode检索数据。由于数据流分散在集群的所有datanode,所以这种数据能使HDFS可扩展到大量的并发客户端。同时,namenode只需要响应块位置的请求(这些信息存储在内存中,因而非常高效),无需响应数据请求,否则随着客户端数量的增长,namenode很快就会成为发展的瓶颈。

2. 文件写入

客户端通过对DistributedFileSystem对象调用create()函数来新建文件, (图3中的步骤1)。DistributesFileSystem对象对namenode创建一个RPC调用,在文件系统的命名空间中新建一个文件,此时该文件中还没有相应的数据块(步骤2)。namenode执行各种不同的检查以确保这个文件不存在以及客户端有新建该文件的权限。如果这些检查都通过,namenode就会为创建新文件记录一条记录;否则,文件创建失败并向客户端抛出一个IOException异常。DistributedFileSystem向客户端返回一个FSDataOutputStream对象,由此客户端可以开始写入数据。就像读取时间一样,FSDataOutputStream对象还封装一个DFSOutputStream对象,该对象负责处理datanode和namenode之间的通信。

hdfs图片写入顺序图3

在客户端写入数据时(步骤3),DFSOutputStream将它分成一个个的数据包,,并写入内部队列,称为“数据队列”(data queue)。DataStreamer处理数据队列,它的责任是根据datanode列表来要求namenode分配适合的新块来存储数据的副本。这一组datanode构成一个管线---我们假设副本数是3,所以管线中有三个节点。DataStreamer将数据包流式传输到管线中的第一个datanode,该datanode存储数据包并将它发送到传输管线中的第2个datanode。同样第2个datanode存储该数据包并且发送给管线中的第3个(也是最后一个)datanode(步骤4)。 DFSOutputStream也维护着一个内部数据包队列来等待datanode的收到确认,称为“确认队列”(ack queue)。收到管道中所有datanode确认信息后,该数据包才会从确认队列删除。(步骤5)

如果在数据写入期间datanode发生故障,则执行以下操作(对写入数据的客户端是透明的)。首先关闭管线,确认把队列中的所有数据包都添加回数据队列的最前端,以确保节点最下游的datanode不会漏掉任何一个数据包。为存储在另一个正常datanode的当前数据块指定一个新标识,并将该标识传递给namenode,以便故障datanode在恢复后可以删除存储的部分数据块。从管线中删除故障数据节点并且把余下的数据块写入管线中的另外两个正常的datanode。namenode注意到块副本数量不足时,会在另一个节点上创建一个新的副本。后续的数据快继续正常接受处理。 在一个块被写入期间可能会有多个datanode同时发生故障,但非常少见。只要写入了dfs.replication.min的副本数(默认为1),写操作就会成功,并且这个块可以在集群中异步复制,直到达到了其目标副本数(dfs.replication的默认值是3)。

客户端完成数据写入后,对数据流调用close()方法。该操作将所有剩余的数据包写入管线,并在联系到namenode且发送文件写入信号完成之前,等待确认(步骤7)。namenode已经知道文件由哪些组成的(通过DataStreamer请求分配数据块),所以它在返回成功前只需要等待数据块进行最小量的复制。

3. 一致模型

文件系统的一致模型(coherency model)描述了文件读/写数据的可见行。HDFS为了性能牺牲一些POSIX要求,因此某些操作可能跟料想的有点不同。

新建一个文件之后,它能在文件系统的命名空间中立即可见,如下所示:

    Path path = new Path("p");
    Fs.create(p);
    assertThat(fs.exists(p),is(true));

但是,写入文件的内容并不保证立即可见,即使数据流已经刷新并存储。所以文件长度显示为0:

                Path path = new Path("p");
                OutputStream out = fs.create(path);
                out.write("content".getBytes("UTF-8"));
                out.flush();
                assertThat(fs.getFileStatus(path).getLen(),is(0L));

当写入的数据超过一个块后,地一个数据块对新的reader就是可见的。之后的块也不例外。总之,当前正在写入的块对其他reader不可见。

HDFS提供一个方法来使所有缓存与数据节点强制同步,即对FSDataOutputStream调用sync()方法。当sync()方法返回成功后,对所有新的reader而言,HDFS能保证文件中带目前位置写入的数据均到达所有datanode的写入管道并且对所有新的reader均可见:

            Path path = new Path("p");
            FSDataOutputStream out = fs.create(path);
            out.write("content".getBytes("UTF-8"));
            out.flush();
            out.hflush();
            assertThat(fs.getFileStatus(path).getLen(),is((long)"content".length()));

该操作类似于POSIX中的fsync系统调用,该调用提交的是一个文件描述符的缓冲数据。

对应用设计的重要性

这个一致性模型和设计应用程序息息相关。如果不调用hsync()方法,就要准备好在客户端或系统发生故障时可能会丢失数据块。这对很多应用来说是不可接受的,所以需要在适当的地方调用hsync()方法,例如在写入一定的记录或字节之后。尽管hsync()设计时就考虑到要尽量减少HDFS负载,但它仍然有许多额外的性能开销,所以在数据的完整性和吞吐量之间就应该有所取舍。

© 著作权归作者所有

为为02
粉丝 51
博文 44
码字总数 99356
作品 0
海淀
程序员
私信 提问
Hadoop技术体系解读

在一个张口闭口都是大数据云计算的今天,我们有必要思考一下,在目前主流的技术体系层面它所代表的意义是什么,期望我的博文能够给后来人一些启示,少绕一些弯路。 我们还是从Hadoop生态系统...

牧师-Panda
2016/10/16
132
0
Hadoop之HDFS原理与操作

HDFS原理 HDFS(Hadoop Distributed File System)是一个分布式文件系统,是谷歌的GFS山寨版本。它具有高容错性并提供了高吞吐量的数据访问,非常适合大规模数据集上的应用,它提供了一个高度...

莫问viva
2016/02/16
98
0
flume的基本概念,数据流模型

1.flume的基本概念 本文中所有与flume相关术语都采用斜体英文表示,这些术语的含义如下所示。 flume 一个可靠的,分布式的,用于采集,聚合,传输海量日志数据的系统。 Web Server 一个产生 ...

张欢19933
2016/01/20
132
0
大数据Hadoop中HDFS用法详细解析

Hadoop--HDFS Edits和Fsimage机制详解 概述 fsimage镜像文件包含了整个HDFS文件系统的所有目录和文件的indoe(节点)信息,比如:/node01/node,会记录每个节点nodeid,以及节点之间父子路径...

金铭鼎IT教育
2018/12/20
18
0
什么是 Hadoop 生态系统

https://www.facebook.com/hadoopers 在一些 Teiid 的一些文章和示例上都会有关于 JBoss Data Virtualization (Teiid) 通过 Hive 使用 Hadoop 作为数据源的信息。当使用 Hadoop 环境创建 Da...

oschina
2015/07/30
11.1K
10

没有更多内容

加载失败,请刷新页面

加载更多

rime设置为默认简体

转载 https://github.com/ModerRAS/ModerRAS.github.io/blob/master/_posts/2018-11-07-rime%E8%AE%BE%E7%BD%AE%E4%B8%BA%E9%BB%98%E8%AE%A4%E7%AE%80%E4%BD%93.md 写在开始 我的Arch Linux上......

zhenruyan
今天
4
0
简述TCP的流量控制与拥塞控制

1. TCP流量控制 流量控制就是让发送方的发送速率不要太快,要让接收方来的及接收。 原理是通过确认报文中窗口字段来控制发送方的发送速率,发送方的发送窗口大小不能超过接收方给出窗口大小。...

鏡花水月
今天
8
0
OSChina 周日乱弹 —— 别问,问就是没空

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @tom_tdhzz :#今日歌曲推荐# 分享容祖儿/彭羚的单曲《心淡》: 《心淡》- 容祖儿/彭羚 手机党少年们想听歌,请使劲儿戳(这里) @wqp0010 :周...

小小编辑
今天
874
10
golang微服务框架go-micro 入门笔记2.1 micro工具之micro api

micro api micro 功能非常强大,本文将详细阐述micro api 命令行的功能 重要的事情说3次 本文全部代码https://idea.techidea8.com/open/idea.shtml?id=6 本文全部代码https://idea.techidea8....

非正式解决方案
今天
5
0
Spring Context 你真的懂了吗

今天介绍一下大家常见的一个单词 context 应该怎么去理解,正确的理解它有助于我们学习 spring 以及计算机系统中的其他知识。 1. context 是什么 我们经常在编程中见到 context 这个单词,当...

Java知其所以然
昨天
6
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部