- 目標(biāo)
HDFS遵循一次寫入多次讀取模型。所以我們不能編輯已經(jīng)在HDFS系統(tǒng)中存儲的文件,但是我們可以重新打開文件,進(jìn)行追加數(shù)據(jù)操作。在讀寫操作中,需要和NameNode進(jìn)行交互。NameNode提供這樣的權(quán)限,客戶端可以輕松的讀寫數(shù)據(jù)塊兒從各自的數(shù)據(jù)節(jié)點(diǎn)中。在這篇博客中,我們會討論Hadoop HDFS中的讀寫操作。同時這篇文章還將包括客戶端怎樣從HDFS中讀寫數(shù)據(jù)和客戶端如何與主、從節(jié)點(diǎn)交互進(jìn)行讀寫操作的。
- Hadoop HDFS數(shù)據(jù)讀寫操作
HDFS - Hadoop Distribution File System 是Hadoop的數(shù)據(jù)存儲層。它是地球上現(xiàn)存的可靠性最高的存儲系統(tǒng)。HDFS以主從模式工作,NameNode是在主進(jìn)程中的主進(jìn)程,DataNode是在從節(jié)點(diǎn)上運(yùn)行的從進(jìn)程。
在應(yīng)用HDFS文件之前,你的電腦中應(yīng)該已經(jīng)安裝了Hadoop。
2.1 Hadoop HDFS Data 寫操作
對于寫一個HDFS文件,客戶端需要訪問主節(jié)點(diǎn)NameNode。這時候主節(jié)點(diǎn)返回從節(jié)點(diǎn),也就是DataNode的地址,以供客戶端寫入數(shù)據(jù)??蛻舳藭苯拥脑贒ataNode寫入數(shù)據(jù),所以DataNode需要關(guān)鍵數(shù)據(jù)寫入管道。
第一個數(shù)據(jù)節(jié)點(diǎn)需要復(fù)制數(shù)據(jù)塊給另一個數(shù)據(jù)節(jié)點(diǎn),同時第二個數(shù)據(jù)節(jié)點(diǎn)還需要傳遞數(shù)據(jù)給第三個數(shù)據(jù)節(jié)點(diǎn)。當(dāng)它們完成了創(chuàng)建數(shù)據(jù)副本的操作的時候會給返回通知。
a. HDFS 數(shù)據(jù)寫入管道的工作流程
在前面曾經(jīng)講過HDFS的寫入數(shù)據(jù)操作是分布式的,客戶端在數(shù)據(jù)節(jié)點(diǎn)上分布式的復(fù)制數(shù)據(jù),下面一步一步的解釋了數(shù)據(jù)的寫操作是如何進(jìn)行的:
i) HDFS發(fā)送了一個創(chuàng)建的請求給分布式文件系統(tǒng)接口
ii) 分布式文件系統(tǒng)發(fā)起一個RPC調(diào)用給NameNode,讓其在系統(tǒng)文件的命名空間里創(chuàng)建一個新文件。這個NameNode負(fù)責(zé)進(jìn)行一系檢查,確保文件系統(tǒng)中不存在這個文件和該客戶端是否擁有創(chuàng)建這一文件的權(quán)限。當(dāng)這些檢查都通過了,NameNode會給這個新文件創(chuàng)建一條記錄;反之,如果這個文件創(chuàng)建失敗,客戶端會拋出一個IO異常。
iii) 分布式文件系統(tǒng)返回FSDataOutputStream給客戶端以便于開始寫數(shù)據(jù)。當(dāng)客戶端開始寫數(shù)據(jù)的時候,DFSOutputStream將文件打碎成小包,讓后把它們寫入一個內(nèi)部隊(duì)列,這個隊(duì)列也叫做數(shù)據(jù)隊(duì)列。這個數(shù)據(jù)隊(duì)列會被DataStreamer使用,DataStreamer負(fù)責(zé)要求NameNode為這些新的數(shù)據(jù)塊分配一個合理的地址列表以便將這些數(shù)據(jù)塊兒和它們的副本存儲起來。
iv) DataNode的列表行程一個管道,這里我問假設(shè)它的復(fù)制因子為3,所以在這個管道中有3個節(jié)點(diǎn)。DataStreamer使這些小包流向管道中的一個數(shù)據(jù)節(jié)點(diǎn)。同樣的,第二個數(shù)據(jù)節(jié)點(diǎn)這些小包,并把他們推給管道中的第三個數(shù)據(jù)節(jié)點(diǎn)。
v) DFSOutputStream同時也負(fù)責(zé)維護(hù)一個數(shù)據(jù)塊的內(nèi)部隊(duì)列,這個隊(duì)列等待來自datanode的通知,這個隊(duì)列叫做 ack queue。只有當(dāng)管道中的數(shù)據(jù)節(jié)點(diǎn)收到來自DataNode的寫入完成通知的時候,這個數(shù)據(jù)塊兒才會被從ack queue中刪除。當(dāng)一個數(shù)據(jù)塊的三個(默認(rèn)是3個)副本都被創(chuàng)建完成的時候,DaTaNode才會發(fā)送一次通知。類似的,所有的blocks被存儲和復(fù)制在不同的Datanodes下,所以這些寫數(shù)據(jù)塊是被平行復(fù)制的。
vi) 當(dāng)客戶端完成寫數(shù)據(jù)操作時,它調(diào)用數(shù)據(jù)流上的close()方法。
vii) 這個操作沖刷所有在DataNode數(shù)據(jù)管道的遺留的小包并且等待一個在聯(lián)系NameNode的一個文件完成的信號通知。NameNode已經(jīng)知道這個文件中的數(shù)據(jù)塊組成情況,所以它只需要等待成功返回前最低限度的數(shù)據(jù)塊兒。
b. 怎么在HDFS文件中寫數(shù)據(jù) - JAVA 程序
下面的例子里是一個JAVA程序如何在HDFS系統(tǒng)中寫入一個文件。
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();