- 目标
HDFS遵循一次写入多次读取模型。所以我们不能编辑已经在HDFS系统中存储的文件,但是我们可以重新打开文件,进行追加数据操作。在读写操作中,需要和NameNode进行交互。NameNode提供这样的权限,客户端可以轻松的读写数据块儿从各自的数据节点中。在这篇博客中,我们会讨论Hadoop HDFS中的读写操作。同时这篇文章还将包括客户端怎样从HDFS中读写数据和客户端如何与主、从节点交互进行读写操作的。
- Hadoop HDFS数据读写操作
HDFS - Hadoop Distribution File System 是Hadoop的数据存储层。它是地球上现存的可靠性最高的存储系统。HDFS以主从模式工作,NameNode是在主进程中的主进程,DataNode是在从节点上运行的从进程。
在应用HDFS文件之前,你的电脑中应该已经安装了Hadoop。
2.1 Hadoop HDFS Data 写操作
对于写一个HDFS文件,客户端需要访问主节点NameNode。这时候主节点返回从节点,也就是DataNode的地址,以供客户端写入数据。客户端会直接的在DataNode写入数据,所以DataNode需要关键数据写入管道。
第一个数据节点需要复制数据块给另一个数据节点,同时第二个数据节点还需要传递数据给第三个数据节点。当它们完成了创建数据副本的操作的时候会给返回通知。
a. HDFS 数据写入管道的工作流程
在前面曾经讲过HDFS的写入数据操作是分布式的,客户端在数据节点上分布式的复制数据,下面一步一步的解释了数据的写操作是如何进行的:
i) HDFS发送了一个创建的请求给分布式文件系统接口
ii) 分布式文件系统发起一个RPC调用给NameNode,让其在系统文件的命名空间里创建一个新文件。这个NameNode负责进行一系检查,确保文件系统中不存在这个文件和该客户端是否拥有创建这一文件的权限。当这些检查都通过了,NameNode会给这个新文件创建一条记录;反之,如果这个文件创建失败,客户端会抛出一个IO异常。
iii) 分布式文件系统返回FSDataOutputStream给客户端以便于开始写数据。当客户端开始写数据的时候,DFSOutputStream将文件打碎成小包,让后把它们写入一个内部队列,这个队列也叫做数据队列。这个数据队列会被DataStreamer使用,DataStreamer负责要求NameNode为这些新的数据块分配一个合理的地址列表以便将这些数据块儿和它们的副本存储起来。
iv) DataNode的列表行程一个管道,这里我问假设它的复制因子为3,所以在这个管道中有3个节点。DataStreamer使这些小包流向管道中的一个数据节点。同样的,第二个数据节点这些小包,并把他们推给管道中的第三个数据节点。
v) DFSOutputStream同时也负责维护一个数据块的内部队列,这个队列等待来自datanode的通知,这个队列叫做 ack queue。只有当管道中的数据节点收到来自DataNode的写入完成通知的时候,这个数据块儿才会被从ack queue中删除。当一个数据块的三个(默认是3个)副本都被创建完成的时候,DaTaNode才会发送一次通知。类似的,所有的blocks被存储和复制在不同的Datanodes下,所以这些写数据块是被平行复制的。
vi) 当客户端完成写数据操作时,它调用数据流上的close()方法。
vii) 这个操作冲刷所有在DataNode数据管道的遗留的小包并且等待一个在联系NameNode的一个文件完成的信号通知。NameNode已经知道这个文件中的数据块组成情况,所以它只需要等待成功返回前最低限度的数据块儿。
b. 怎么在HDFS文件中写数据 - JAVA 程序
下面的例子里是一个JAVA程序如何在HDFS系统中写入一个文件。
FileSystem fileSystem = FileSystem.get(conf);
// check if the file already exists
Path path = new Path("/path/to/file.ext");
if(fileSystem.exists(path)){
System.out.println("File " + dest + " already exists");
return;
}
// Create a new file and write data to it.
FSDataOutputStream out = fileSystem.create(path);
InputStream in = new BufferedInputStream(new FileInputStream(new File(source)));
byte[] b = new byte[1024];
int numBytes = 0;
while((numBytes = in.read(b)) > 0){
out.write(b,0,numBytes);
}
// Close all the file descripters
in.close();
out.close();
fileSystem.close();
网友评论