HDFS数据流-剖析文件读取及写入
HDFS数据流-剖析文件读取及写入
文件读取
1. 客户端通过调用FileSystem对象的open方法来打开希望读取的文件,对于HDFS来说,这个对象是分布式文件系统的一个实例。
2. DistributedFileSystem通过使用RPC来调用namenode,以确定文件起始块的位置。对于每一个块,namenode返回存有该块副本的datanode地址。此外,这些datanode根据他们与客户端的距离来排序(根据集群的网络拓扑)。如果该客户端本身就是一个namenode,并保存有相应数据块的一个副本时,该节点就会从本地datanode读取数据。DistributedFileSystem类返回一个FSDataInputStream对象(一个支持文件定位的输入流)给客户端并读取数据。FSDataInputStream类转而封装DFSInputStream对象,该对象管理着datanode和namenode的I/O
3. 客户端对这个输入流调用read()方法。
4. 存储着文件起始几个块的datanode地址的DFSInputStream随机连接距离最近的datanode。通过对数据流反复调用read方法,可以将数据从datanode传输到客户端
5. 到达块的末端时,DFSInputStream关闭与该datanode的连接,然后寻找下一个块的最佳datanode。客户端只需要读取连续的流,并且对于客户端都是透明的。
6. 客户端从流中读取数据时,块是按照打开DFSInputStream与datanode新建连接的顺序读取的。他也会根据需要询问namenode来检索下一批数据块的datanode的位置。一旦客户端完成读取,就对FSDataInputStream调用close()方法。
在读取数据时,如果DFSInputStream在与datanode通信时遇到错误,会尝试从这个块的另一个最邻近datanode读取数据。它也会记住那个故障datanode,以保证以后不会反复读取该节点上后续的块。DFSInputStream也会通过校验和确认从datanode发来的数据是否完整。如果发现有损坏的块,就在DFSInputStream试图从其他datanode读取其复本之前通知namanode.
这个设计的一个重点是,namenode告知客户端每个块中最佳的datanode,并让客户端直接连接到该datanode检索数据。由于数据流分散在集群中的所有datanode,所以这种设计能是HDFS可扩展到大量的并发客户端。同时,namenode只需要相应块位置的请求(这些信息存储在内存中,因而非常高效),无需相应数据请求,否则随着客户端数量的增长,namenode会很快成为瓶颈。
文件写入
1. 客户端通过对DistributedFileSystem对象调用create方法来新建文件
2. DistributedFileSystem对namenode创建一个RPC调用,在文件系统的命名空间中新建一个文件,此时该文件中还没有相应的数据块。Namenode执行各种不同的检查以确保这个文件不存在以及客户端有新建该文件的权限。如果这些检查均通过,namenode就会为创建新文件记录一条记录;否则,文件创建失败并向客户端抛出一个IOException异常。DistributedFileSystem向客户端返回一个FSDataOutputStream对象,由此客户端可以开始写入数据。就像读取时间一项,FSDataOutputStream封装一个DFSOutputStream对象,该对象负责处理datanode和namenode之间的通信。
3. 在客户端写入数据时,DFSOutputStream将它分成一个个的数据包,并写入内部队列,称为数据队列(data queue)。DataStreamer处理数据队列,它的责任是根据datanode构成一个管线--假设复本数为3,所以管线中有3个节点。
4. DataStreamer将数据包流式传输到管线中第一个datanode,该datanode存储数据包并将它发送到管线中的第二个datanode。同样第二个datanode存储该数据包并且发送给管线中的第三个(也是最后一个)datanode。
5. DFSOutputStream也维护着一个内部数据包队列来等待datanode的收到确认回执,称为确认队列(ack queue)。收到管线中所有datanode确认信息后,该数据包才会从确认队列删除。
如果在数据写入期间datanode发生故障,则执行以下操作
(1)首先关闭管线,确认把队列中的所有数据包都添加回数据队列的最前端,以确保故障节点下游的datanode不会漏掉任何一个数据包。
(2)为存储在另一正常datanode的当前数据块指定一个新的标识,并将该标识传送给namenode,以便故障datanode在恢复后可以删除存储的部分数据块。
(3)从管线中删除故障数据节点并且把余下的数据块写入管线中另外两个正常的datanode。
(4)Namenode注意到块副本数量不足时,会在另一个节点上创建一个新的副本。
只要写入了dfs.replication.min的复本数(默认为1),写操作就会成功,并且这个块可以在集群中异步复制,直到达到其目标复本数(dfs.replication默认为3)
6. 客户端完成数据的写入后,对数据流调用close方法。
7. 该操作将剩余的所有数据包写入datanode管线,并在联系到namenode且发送文件写入完成信号之前,等待确认。Namenode已经知道文件由哪些块组成(通过DataStreamer请求分配数据块),所以它在返回成功前只需要等待数据块进行最小量的复制。
HDFS数据流-剖析文件读取及写入的更多相关文章
- python文件读取和写入案例
python文件读取和写入案例 直接上代码吧 都是说明 百度上找了很多,最终得出思路 没有直接可以读取修改的扩展,只能先读取,然后复制一份,然后在复制出来的文件里面追加保存 然后删除读的那个,但是缺 ...
- Java底层代码实现单文件读取和写入(解决中文乱码问题)
需求: 将"E:/data/车站一次/阿坝藏族羌族自治州.csv"文件中的内容读取,写入到"E:/data//车站一次.csv". 代码: public cla ...
- Apache commons-io实现单文件读取和写入
Apache commons-io提供了很多类,这里只介绍FileUtils类. FileUtils类提供了一些操作文件对象的实用方法,包括文件的读取.写入.复制和比较等. 比如逐句读取和写入一个文件 ...
- properties文件读取与写入
将peoperties文件的读取和写入封装成了一个工具类: import java.io.BufferedInputStream; import java.io.FileInputStream; im ...
- java===java基础学习(5)---文件读取,写入操作
文件的写入读取有很多方法,今天学到的是Scanner和PrintWriter 文件读取 Scanner in = new Scanner(Paths.get("file.txt") ...
- Delphi txt文件读取及写入
简介:Delphi支持三种文件类型:文本文件.记录文件.无类型文件.文本文件的读... 在进行win32开发中对文件的读写是最常用的操作之一 Delphi 支持三种文件类型: 文本文件.记录文件 ...
- MATLAB中TXT数据文件读取并写入元胞数组的方法与步骤
一. TXT数据文件读取 Data = load('train.txt'); %简单的文件读取,这时在工作区可以看到导入的大数据变量Data 二.大数据变量Data装入元胞数组中 D = cell ...
- Java底层代码实现多文件读取和写入
需求: "E:/data/"目录下有四个文件夹,如下: 每个文件夹下有几个.csv文件,如下: 将每个文件夹下的.csv文件合并成一个以该文件夹命名的.csv文件. 做法: 找到& ...
- Apache commons-io实现多文件读取和写入
需求: "E:/data/"目录下有四个文件夹,如下: 每个文件夹下有几个.csv文件,如下: 将每个文件夹下的.csv文件合并成一个以该文件夹命名的.csv文件. 做法: 找到& ...
随机推荐
- PHP 规划(收藏的一些好博文)
2014-10-15 01:30 36870人阅读 评论(34) 收藏 举报 分类: PHP/DHTML/Other(237) 版权声明:本文为博主原创文章,未经博主允许不得转载. PHP程序员的技术 ...
- EasyDSS流媒体服务器软件支持HTTPS-启用https服务申请免费证书
EasyDSS流媒体服务器软件,提供一站式的转码.点播.直播.时移回放服务,极大地简化了开发和集成的工作. 其中,点播功能主要包含:上传.转码.分发.直播功能,主要包含:直播.录像, 直播支持RTMP ...
- HashMap和ConcurrentHashMap的区别,HashMap的底层源码。
Hashmap本质是数组加链表.根据key取得hash值,然后计算出数组下标,如果多个key对应到同一个下标,就用链表串起来,新插入的在前面. ConcurrentHashMap:在hashMap的基 ...
- android菜鸟学习笔记28----Android中的Service生命周期及本地和远程服务绑定的实现
Service是Android中长期在后台运行的没有界面的组件,使用服务的优势在于:能够提高进程的优先级,系统不容易回收掉进程,即便回收了,内存充足的时候,会把进程重新创建. 1.服务的简单使用示例: ...
- go build说明
go build命令用于编译我们指定的源码文件或代码包以及它们的依赖包. 例如,如果我们在执行go build命令时不后跟任何代码包,那么命令将试图编译当前目录所对应的代码包.例如,我们想编译goc2 ...
- 巨蟒python全栈开发linux之centos5
1.nginx安装使用 2.nginx访问日志和压测命令 3.nginx反向代理配置 nginx的404页面 访问:淘宝官网的一个错误地址:http://taobao.com/eeeeeeee 淘宝的 ...
- spark2.0.2基于hadoop2.4搭建分布式集群
一.Scala安装 因为spark的版本原因,所以Scala我用的2.11.7. 下载目录http://www.scala-lang.org/download/ 拷贝到要安装的地址,我的地址是/usr ...
- python系列七:Python3字典dict
#!/usr/bin/python #Python3 字典#字典是支持无限极嵌套的citys={ '北京':{ '朝阳':['国贸','CBD','天阶','我爱我家','链接地产 ...
- [翻译] flask-SocketIO
最近开发工作需要用到websocket去替代老办法轮询,因为我们的web系统使用flask搭建,所以使用flask-SocketIO作为我们的websocket方案,因此顺手翻译官方文档 *** Fl ...
- 微信开发模板--easywechat
链接地址:https://easywechat.org/zh-cn/docs/installation.html