Hadoop原理之——HDFS原理

 

 

Hadoop 3個核心組件:

分佈式文件系統:Hdfs——實現將文件分佈式存儲在不少的服務器上(hdfs是一個基於Linux本地文件系統上的文件系統)

分佈式運算編程框架:Mapreduce——實如今不少機器上分佈式並行運算

分佈式資源調度平臺:Yarn——幫用戶調度大量的mapreduce程序,併合理分配運算資源

 

HDFS的設計特色是:

一、大數據文件,很是適合上T級別的大文件或者一堆大數據文件的存儲,若是文件只有幾個G甚至更小就沒啥意思了。html

二、文件分塊存儲,HDFS會將一個完整的大文件平均分塊存儲到不一樣計算器上,它的意義在於讀取文件時能夠同時從多個主機取不一樣區塊的文件,多主機讀取比單主機讀取效率要高得多得都。編程

三、流式數據訪問,一次寫入屢次讀寫,這種模式跟傳統文件不一樣,它不支持動態改變文件內容,而是要求讓文件一次寫入就不作變化,要變化也只能在文件末添加內容。緩存

四、廉價硬件,HDFS能夠應用在普通PC機上,這種機制可以讓給一些公司用幾十臺廉價的計算機就能夠撐起一個大數據集羣。服務器

五、硬件故障,HDFS認爲全部計算機均可能會出問題,爲了防止某個主機失效讀取不到該主機的塊文件,它將同一個文件塊副本分配到其它某幾個主機上,若是其中一臺主機失效,能夠迅速找另外一塊副本取文件。網絡

 

HDFS的關鍵元素:

一、Block:將一個文件進行分塊,一般是64M。框架

二、NameNode:保存整個文件系統的目錄信息、文件信息及分塊信息,這是由惟一 一臺主機專門保存,固然這臺主機若是出錯,NameNode就失效了。在 Hadoop2.* 開始支持 activity-standy 模式----若是主 NameNode 失效,啓動備用主機運行 NameNode。分佈式

三、DataNode:分佈在廉價的計算機上,用於存儲Block塊文件。oop

若是你想了解大數據的學習路線,想學習大數據知識以及須要免費的學習資料能夠加羣:784789432.歡迎你的加入。天天下午三點開直播分享基礎知識,晚上20:00都會開直播給你們分享大數據項目實戰。post

 

1、HDFS運行原理

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

二、NameNode會將子節點的相關元數據信息緩存在內存中,對於文件與Block塊的信息會經過fsImage和edits文件方式持久化在磁盤上,以確保NameNode知道文件各個塊的相關信息;

三、NameNode負責存儲fsImage和edits元數據信息,但fsImage和edits元數據文件須要按期進行合併,這時則由SecondNameNode進程對fsImage和edits文件進行按期合併,合併好的文件再交給NameNode存儲。 

2、HDFS數據合併原理

一、NameNode初始化時會產生一個edits文件和一個fsimage文件,edits文件用於記錄操做日誌,好比文件的刪除或添加等操做信息,fsImage用於存儲文件與目錄對應的信息以及edits合併進來的信息,即至關於fsimage文件在這裏是一個總的元數據文件,記錄着全部的信息;

二、隨着edits文件不斷增大,當達到設定的一個閥值的時候,這時SecondaryNameNode會將edits文件和fsImage文件經過採用http的方式進行復制到SecondaryNameNode下(在這裏考慮到網絡傳輸,因此通常將NameNode和SecondaryNameNode放在相同的節點上,這樣就無需走網絡帶寬了,以提升運行效率),同時NameNode會產生一個新的edits文件替換掉舊的edits文件,這樣以保證數據不會出現冗餘;

三、SecondaryNameNode拿到這兩個文件後,會在內存中進行合併成一個fsImage.ckpt的文件,合併完成後,再經過http的方式將合併後的文件fsImage.ckpt複製到NameNode下,NameNode文件拿到fsImage.ckpt文件後,會將舊的fsimage文件替換掉,而且更名成fsimage文件。  

經過以上幾步則完成了edits和fsimage文件的合併,依此不斷循環,從而到達保證元數據的正確性。

3、HDFS寫原理

一、HDFS客戶端提交寫操做到NameNode上,NameNode收到客戶端提交的請求後,會先判斷此客戶端在此目錄下是否有寫權限,若是有,而後進行查看,看哪幾個DataNode適合存放,再給客戶端返回存放數據塊的節點信息,即告訴客戶端能夠把文件存放到相關的DataNode節點下;

二、客戶端拿到數據存放節點位置信息後,會和對應的DataNode節點進行直接交互,進行數據寫入,因爲數據塊具備副本replication,在數據寫入時採用的方式是先寫第一個副本,寫完後再從第一個副本的節點將數據拷貝到其它節點,依次類推,直到全部副本都寫完了,纔算數據成功寫入到HDFS上,副本寫入採用的是串行,每一個副本寫的過程當中都會逐級向上反饋寫進度,以保證明時知道副本的寫入狀況;

三、隨着全部副本寫完後,客戶端會收到數據節點反饋回來的一個成功狀態,成功結束後,關閉與數據節點交互的通道,並反饋狀態給NameNode,告訴NameNode文件已成功寫入到對應的DataNode。

代碼實現

  1.  
    /*
  2.  
    * 測試HDFS寫入數據
  3.  
    */
  4.  
    @Test
  5.  
    public void Test1() throws IOException {
  6.  
    // 加載配置文件
  7.  
    Configuration conf = new Configuration();
  8.  
    FileSystem fs = FileSystem.get(conf);
  9.  
    Path path = new Path("/gyb/student.txt");
  10.  
    // 產生IO流
  11.  
    FSDataOutputStream fsio = fs.create(path);
  12.  
    // 包裝輸出IO流
  13.  
    BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(fsio));
  14.  
    // 包裝輸入IO流
  15.  
    BufferedReader br = new BufferedReader(
  16.  
    new InputStreamReader(new FileInputStream("student.txt")));
  17.  
    String line = null;
  18.  
    while ((line = br.readLine()) != null) {
  19.  
    bw.write(line);
  20.  
    bw.newLine();
  21.  
    bw.flush();
  22.  
    }
  23.  
    bw.close();
  24.  
    br.close();
  25.  
    }

4、HDFS讀原理

一、HDFS客戶端提交讀操做到NameNode上,NameNode收到客戶端提交的請求後,會先判斷此客戶端在此目錄下是否有讀權限,若是有,則給客戶端返回存放數據塊的節點信息,即告訴客戶端能夠到相關的DataNode節點下去讀取數據塊;

二、客戶端拿到塊位置信息後,會去和相關的DataNode直接構建讀取通道,讀取數據塊,當全部數據塊都讀取完成後關閉通道,並給NameNode返回狀態信息,告訴NameNode已經讀取完畢。

代碼實現

  1.  
    /*
  2.  
    * 測試HDFS讀出的操做
  3.  
    */
  4.  
    @Test
  5.  
    public void Test3() throws IOException {
  6.  
    // 加載配置類
  7.  
    Configuration conf = new Configuration();
  8.  
    FileSystem fs =FileSystem.newInstance(conf);
  9.  
    Path path = new Path("/gyb/student.txt");
  10.  
    FileStatus[] fileStatus = fs.listStatus(path);
  11.  
    for (FileStatus fileStatus2 : fileStatus) {
  12.  
    if(fileStatus2 != null && fileStatus2.isFile()) {
  13.  
    //open方法只能傳文件
  14.  
    FSDataInputStream fsi = fs.open(path);
  15.  
    // 包裝IO流
  16.  
    BufferedReader br = new BufferedReader(new InputStreamReader(fsi));
  17.  
    while(br.ready()) {
  18.  
    System.out.println(br.readLine());
  19.  
    }
  20.  
    }
  21.  
    }
  22.  
    System.out.println( "--------over--------");
  23.  
    }
相關文章
相關標籤/搜索