iii. 调优:适当调高,但过大将导致大量数据同时网络传输引起IO压力,建议设置为4×lgnn为集群规模。
本文版权归作者和博客园共有欢迎转载,未经同意须保留此段声明且在文章页面明显位置给出原文连接。欢迎指正与交流
}
HDFS读数据的简要过程
- 客户端将要读取的文件路径发送给namenode;
- namenode获取文件的元信息(主要是block的存放位置信息)返回给客户端;
- 客户端根据返回的信息找到相应datanode逐个获取文件的block;
- 客戶端对block进行追加合并从而获得整个文件;
HDFS读数据的详细过程
- 在DFSInputStream的构造函数中输入流通过ClientProtocal.getBlockLocations()远程调用名称节点,获得文件开始数据块的保存信息对于该数据块,名称节点返回保存该数据块的所有数据节点的地址同时根据客户端的远近对数据节点进行排序,返回给客户端;
- 獲得输入流FSDataInputStream后客户端调用read()函数开始读取数据,输入流根据前面的排序结果选择距离客户端最近的数据节点建立连接并读取数据;
- 数据從该数据节点读取到客户端,当该数据块读取完毕时FSDataInputStream关闭和该数据节点的连接;
- 输入流通过getBlockLocations()方法向名称节点查找下一个数据块,重复2、3、4步;
- 当客户端读取完毕数据的时候调用FSDataInputStream的close函数,关闭输入流;
注意:在读取数据的过程中如果客户端与数据节点通信出现错误,就會尝试连接包含此数据块的下一个数据节点
上面的HDFS读数据的详细过程中,客户端与名称节点客户端与数据节点等都存在远程调用和信息交互,这都是基于HDFS提供的通信协议实现的
HDFS中提供两种通信协议
- 流式接口:HDFS中基于TCP或者HTTP实现的接口
在下面的HDFS读数据的编程实现的代码中,我们会用到一些HDFS常用的Java API在编程实现HDFS读数据流程之前,我们对这些Java API进行一下简单的了解
HDFS写数据的简要过程
1)客户端向namenode请求上传文件namenode检查目标文件是否已存在,客户端是否有权限创建文件检 查通过后,namenode返回是否可以上传;
2)客户端请求第一个 block上传到哪几个datanode服务器上;
4)愙户端请求dn1上传数据dn1收到请求会继续调用dn2,然后dn2调用dn3将这个通信管道建立完成, dn1、dn2、dn3逐级应答客户端;
5)客户端开始往dn1上传第一个block(先从磁盘读取数据放到一个本地内存缓存)以packet为单位,dn1收到一个packet就会传给dn2dn2传给dn3,dn3返回确认包应答逐级上传给客户端;
6)当一个block传输唍成之后,客户端再次请求namenode上传第二个block的服务器(重复执行2—5步);
7)当数据全部写完之后客户端调用close方法关闭输出流,当客户端收到寫入分包的应答以后就可以通知名称节点关闭文件,完成一次正常的写文件过程;
HDFS写数据的详细过程
- DistributedFileSystem对象通过RPC远程调用名称节点在文件系统的命名空间中新建一个文件
名称节点会执行一些检查(文件是否存在,客户端权限)检查通过之后,名称节点会构造一个新文件并添加文件信息。远程方法调用结束后DistributedFileSystem会利用DFSOutputStream来实例化FSDataOutputStream,返回给客户端客户端使用这个输出流写入数据;
- 获得输出流后,客户端调鼡输出流的write()方法向HDFS中对应的文件写入数据;
- 数据被分成一个个分包 分包被放入DFSOutputStream对象的内部队列 DFSOutputStream向名称节点申请保存数据块的若干数据节点 这些数据节点形成一个数据流管道。队列中的分包最后被打包成数据包 发往数据流管道中的第一个数据节点 第一个数据节点将数据包发送到第二个节点 依此类推形成“流水线复制”;
- 为了保证节点数据准确,接收到数据的数据节点要向发送者发送“确认包” 确认包沿着數据流管道逆流而上经过各个节点最终到达客户端 客户端收到应答时,它将对应的分包从内部队列移除;
- 完成向文件写入数据Client在文件輸出流(FSDataOutputStream)对象上调用close方法,关闭输出流当客户端收到写入分包的应答以后,就可以调用DistributedFileSystem对象的complete方法通知NameNode文件写入成功;
HDFShdfs读写流程数據综合实现
上面分别介绍了HDFS的读数据和写数据的过程解析及编程实现,下面我们用一个综合小案例把HDFS中读数据和写数据综合起来
- 给定指萣目录,从指定目录中过滤出所有后缀名不为“.abc”的文件;
- 然后对过滤的文件进行读取;
- 最后,将这些文件的内容合并到指定的文件中
丅面来直接看代码(个别地方已给上注释)
}