HDFS数据读写过程和代码解析

   FileSystem是一个通用文件系统的抽象基类,可以被分布式文件系统继承,所有可能使用Hadoop文件系统的代码,都要使用这个类

  Hadoop为FileSystem这个抽象类提供了多种具体实现
  DistributedFileSystem就是FileSystem在HDFS文件系统中的具体实现
  FileSystem的open()方法返回的是一个输入流FSDataInputStream对象,在HDFS文件系统中,具体的输入流就是DFSInputStream;

  FileSystem中的create()方法返回的是一个输出流FSDataOutputStream对象,在HDFS文件系统中,具体的输出流就是DFSOutputStream。

 

1、读数据过程

 

(1)打开文件,创建输入流对象;

(2)获取数据块信息

  HDFS客户端通过客户端协议ClientProtocal.getBlockLocations()远程调用名称节点,获得文件开始部分数据块的位置。对于该数据块,名称节点返回保存该数据块的所有数据节点的地址,并根据距离客户端远近进行排序。

(3)读取请求

  客户端获得输入流FSDataInputStream以后调用read()函数开始读取数据。输入流根据前面的排序结果,选择距离客户端最近的数据节点建立连接并读取数据

(4)读取数据

HDFS客户端通过客户端数据节点协议ClientDatanodeProtocol把数据从数据节点读到客户端,当该数据块读取完毕时FSDataInputStream关闭和该数据节点的连接

(5)获取下一个数据块信息

如果文件有更多数据块,则客户端通过ClientProtocal.getBlockLocations()从名称节点查找下一个数据块,名称节点安装步骤(2)中描述返回数据库相关信息;

(6)读取下一个数据块

重复步骤(3)的读过程;

(7)关闭文件和hdfs

2、读数据代码

import java.io.BufferedReader;
import java.io.InputStreamReader;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.fs.FSDataInputStream;

public class Chapter3
{
public static void main(String[] args)
{
try
{
Configuration conf = new Configuration();  //新的xml格式配置对象
conf.set("fs.defaultFS","hdfs://localhost:9000");   //设置fs.defaultFS配置项的值
//读数据的过程
conf.set("fs.hdfs.impl","org.apache.hadoop.hdfs.DistributedFileSystem");  //设置配置项的值
FileSystem fs = FileSystem.get(conf);  //HDFS后台实际创建DistributedFileSystem对象
Path file = new Path("test");
FSDataInputStream getIt = fs.open(file); //创建输入流对象,HDFS后台封装DFSInputStream对象进行读操作
BufferedReader d = new BufferedReader(new InputStreamReader(getIt));  //创建读文件对象
String content = d.readLine(); //读取文件一行
System.out.println(content);
d.close(); //关闭文件
fs.close(); //关闭hdfs
} catch (Exception e) {
e.printStackTrace();
}
}
}

3、写数据过程

 

(1)创建文件请求

客户端收到创建文件请求,创建输出流对象

(2)创建文件元数据

客户端RPC远程调用名称节点,在文件系统的命名空间中新建一个文件.名称节点会执行一些检查(文件是否存在,客户端权限等)

(3)写入数据包到数据节点

要写入文件的数据被分成一个个分包分包被放入DFSOutputStream对象的内部队列。DFSOutputStream向名称节点申请保存数据块的若干数据节点

(4)数据节点接收确认包

  这些数据节点形成一个数据流管道。队列中的分包最后被打包成数据包发往数据流管道中的第一个数据节点。第一个数据节点将数据包发送到第二个节点。依此类推,形成“流水线复制”。这样满足冗余副本数量的要求。

  为了保证节点数据准确,接收到数据的数据节点要向发送者发送“确认包”。确认包沿着数据流管道逆流而上,经过各个节点最终到达客户端。客户端收到应答时,它将对应的分包从内部队列移除。

(5)客户端关闭文件

(6)写操作完成

DFSOutputStream调用ClientProtocal.complete()方法通知名称节点关闭文件

4、写数据代码

 import org.apache.hadoop.conf.Configuration; 

import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.FSDataOutputStream;
import org.apache.hadoop.fs.Path;
public class Chapter3 {
public static void main(String[] args) {
try {
Configuration conf = new Configuration();
conf.set("fs.defaultFS","hdfs://localhost:9000");
conf.set("fs.hdfs.impl","org.apache.hadoop.hdfs.DistributedFileSystem");
FileSystem fs = FileSystem.get(conf);
byte[] buff = "Hello world".getBytes(); // 要写入的内容
String filename = "test"; //要写入的文件名
FSDataOutputStream os = fs.create(new Path(filename));  //创建输出流对象,HDFS后台封装DFSOutputStream对象进行写操作
os.write(buff,0,buff.length);
System.out.println("Create:"+ filename);
os.close();
fs.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}

posted on 2017-05-30 14:48  ostin  阅读(1473)  评论(0)    收藏  举报