Hadoop原理之——HDFS原理

gamebus發表於2021-09-09

1、大資料檔案,非常適合上T級別的大檔案或者一堆大資料檔案的儲存,如果檔案只有幾個G甚至更小就沒啥意思了。

2、檔案分塊儲存,HDFS會將一個完整的大檔案平均分塊儲存到不同計算器上,它的意義在於讀取檔案時可以同時從多個主機取不同區塊的檔案,多主機讀取比單主機讀取效率要高得多得都。

3、流式資料訪問,一次寫入多次讀寫,這種模式跟傳統檔案不同,它不支援動態改變檔案內容,而是要求讓檔案一次寫入就不做變化,要變化也只能在檔案末新增內容。

4、廉價硬體,HDFS可以應用在普通PC機上,這種機制能夠讓給一些公司用幾十臺廉價的計算機就可以撐起一個大資料叢集。

5、硬體故障,HDFS認為所有計算機都可能會出問題,為了防止某個主機失效讀取不到該主機的塊檔案,它將同一個檔案塊副本分配到其它某幾個主機上,如果其中一臺主機失效,可以迅速找另一塊副本取檔案。


1、Block:將一個檔案進行分塊,通常是64M。

2、NameNode:儲存整個檔案系統的目錄資訊、檔案資訊及分塊資訊,這是由唯一 一臺主機專門儲存,當然這臺主機如果出錯,NameNode就失效了。在 Hadoop2.* 開始支援 activity-standy 模式----如果主 NameNode 失效,啟動備用主機執行 NameNode。

3、DataNode:分佈在廉價的計算機上,用於儲存Block塊檔案。


1、NameNode和DataNode節點初始化完成後,採用RPC進行資訊交換,採用的機制是心跳機制,即DataNode節點定時向NameNode反饋狀態資訊,反饋資訊如:是否正常、磁碟空間大小、資源消耗情況等資訊,以確保NameNode知道DataNode的情況;

2、NameNode會將子節點的相關後設資料資訊快取在記憶體中,對於檔案與Block塊的資訊會透過fsImage和edits檔案方式持久化在磁碟上,以確保NameNode知道檔案各個塊的相關資訊;

3、NameNode負責儲存fsImage和edits後設資料資訊,但fsImage和edits後設資料檔案需要定期進行合併,這時則由SecondNameNode程式對fsImage和edits檔案進行定期合併,合併好的檔案再交給NameNode儲存。 

1、NameNode初始化時會產生一個edits檔案和一個fsimage檔案,edits檔案用於記錄操作日誌,比如檔案的刪除或新增等操作資訊,fsImage用於儲存檔案與目錄對應的資訊以及edits合併進來的資訊,即相當於fsimage檔案在這裡是一個總的後設資料檔案,記錄著所有的資訊;

2、隨著edits檔案不斷增大,當達到設定的一個閥值的時候,這時SecondaryNameNode會將edits檔案和fsImage檔案透過採用http的方式進行復制到SecondaryNameNode下(在這裡考慮到網路傳輸,所以一般將NameNode和SecondaryNameNode放在相同的節點上,這樣就無需走網路頻寬了,以提高執行效率),同時NameNode會產生一個新的edits檔案替換掉舊的edits檔案,這樣以保證資料不會出現冗餘;

3、SecondaryNameNode拿到這兩個檔案後,會在記憶體中進行合併成一個fsImage.ckpt的檔案,合併完成後,再透過http的方式將合併後的檔案fsImage.ckpt複製到NameNode下,NameNode檔案拿到fsImage.ckpt檔案後,會將舊的fsimage檔案替換掉,並且改名成fsimage檔案。  

透過以上幾步則完成了edits和fsimage檔案的合併,依此不斷迴圈,從而到達保證後設資料的正確性。

1、HDFS客戶端提交寫操作到NameNode上,NameNode收到客戶端提交的請求後,會先判斷此客戶端在此目錄下是否有寫許可權,如果有,然後進行檢視,看哪幾個DataNode適合存放,再給客戶端返回存放資料塊的節點資訊,即告訴客戶端可以把檔案存放到相關的DataNode節點下;

2、客戶端拿到資料存放節點位置資訊後,會和對應的DataNode節點進行直接互動,進行資料寫入,由於資料塊具有副本replication,在資料寫入時採用的方式是先寫第一個副本,寫完後再從第一個副本的節點將資料複製到其它節點,依次類推,直到所有副本都寫完了,才算資料成功寫入到HDFS上,副本寫入採用的是序列,每個副本寫的過程中都會逐級向上反饋寫進度,以保證實時知道副本的寫入情況;

3、隨著所有副本寫完後,客戶端會收到資料節點反饋回來的一個成功狀態,成功結束後,關閉與資料節點互動的通道,並反饋狀態給NameNode,告訴NameNode檔案已成功寫入到對應的DataNode。



@Test


public void Test1() throws IOException {


// 載入配置檔案


Configuration conf = new Configuration();


FileSystem fs = FileSystem.get(conf);


Path path = new Path("/gyb/student.txt");


// 產生IO流


FSDataOutputStream fsio = fs.create(path);


// 包裝輸出IO流


BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(fsio));


// 包裝輸入IO流


BufferedReader br = new BufferedReader(


new InputStreamReader(new FileInputStream("student.txt")));


String line = null;


while ((line = br.readLine()) != null) {


bw.write(line);


bw.newLine();


bw.flush();


}


bw.close();


br.close();


}

1、HDFS客戶端提交讀操作到NameNode上,NameNode收到客戶端提交的請求後,會先判斷此客戶端在此目錄下是否有讀許可權,如果有,則給客戶端返回存放資料塊的節點資訊,即告訴客戶端可以到相關的DataNode節點下去讀取資料塊;

2、客戶端拿到塊位置資訊後,會去和相關的DataNode直接構建讀取通道,讀取資料塊,當所有資料塊都讀取完成後關閉通道,並給NameNode返回狀態資訊,告訴NameNode已經讀取完畢。

程式碼實現



@Test


public void Test3() throws IOException {


// 載入配置類


Configuration conf = new Configuration();


FileSystem fs =FileSystem.newInstance(conf);


Path path = new Path("/gyb/student.txt");


FileStatus[] fileStatus = fs.listStatus(path);


for (FileStatus fileStatus2 : fileStatus) {


if(fileStatus2 != null && fileStatus2.isFile()) {


//open方法只能傳檔案


FSDataInputStream fsi = fs.open(path);


// 包裝IO流


BufferedReader br = new BufferedReader(new InputStreamReader(fsi));


while(br.ready()) {


System.out.println(br.readLine());


}


}


}


System.out.println("--------over--------");


}



作者:大資料首席資料師
連結:


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/4687/viewspace-2815218/,如需轉載,請註明出處,否則將追究法律責任。

相關文章