Hadoop之HDFS讀寫原理

1、HDFS基本概念java

HDFS全稱是Hadoop Distributed System。HDFS是爲以流的方式存取大文件而設計的。適用於幾百MB,GB以及TB,並寫一次讀屢次的場合。而對於低延時數據訪問、大量小文件、同時寫和任意的文件修改,則並非十分適合。node

目前HDFS支持的使用接口除了Java的還有,Thrift、C、FUSE、WebDAV、HTTP等。HDFS是以block-sized chunk組織其文件內容的,默認的block大小爲64MB,對於不足64MB的文件,其會佔用一個block,但實際上不用佔用實際硬盤上的64MB,這能夠說是HDFS是在文件系統之上架設的一箇中間層。之因此將默認的block大小設置爲64MB這麼大,是由於block-sized對於文件定位頗有幫助,同時大文件更使傳輸的時間遠大於文件尋找的時間,這樣能夠最大化地減小文件定位的時間在整個文件獲取總時間中的比例。數據庫

 

2、HDFS設計原則緩存

HDFS是Google的GFS(Google File System)的開源實現。具備如下五個基本目標:安全

一、硬件錯誤是常態而不是錯誤。HDFS通常運行在普通的硬件上,因此硬件錯誤是一種很正常的狀況。因此在HDFS中,錯誤的檢測並快速自動恢復是HDFS的最核心的設計目標。網絡

二、流式數據訪問。運行在HDFS上的應用主要是以批量處理爲主,而不是用戶交互式事務,以流式數據讀取爲多。數據結構

三、大規模數據集。HDFS中典型的文件大小要達到GB或者是TB級。架構

四、簡單一致性原則。HDFS的應用程序通常對文件的操做時一次寫入、屢次讀出的模式。文件一經建立、寫入、關閉後,通常文件內容再發生改變。這種簡單的一致性原則,使高吞吐量的數據訪問成爲可能。函數

五、數據就近原則。HDFS提供接口,以便應用程序將自身的執行代碼移動到數據節點上來執行。採用這種方式的緣由主要是:移動計算比移動數據更加划算。相比與HDFS中的大數據/大文件,移動計算的代碼相比與移動數據更加划算,採用這種方式能夠提供寬帶的利用率,增長系統吞吐量,減小網絡的堵塞程度。oop

 

3、HDFS的體系結構

構成HDFS主要是Namenode(master)和一系列的Datanode(workers)。

Namenode是管理HDFS的目錄樹和相關的文件元數據,這些信息是以"namespaceimage"和"edit log"兩個文件形式存放在本地磁盤,可是這些文件是在HDFS每次重啓的時候從新構造出來的。

Datanode則是存取文件實際內容的節點,Datanodes會定時地將block的列表彙報給Namenode。

因爲Namenode是元數據存放的節點,若是Namenode掛了那麼HDFS就無法正常運行,所以通常使用將元數據持久存儲在本地或遠程的機器上,或者使用secondary namenode來按期同步Namenode的元數據信息,secondary namenode有點相似於MySQL的Master/Salves中的Slave,"edit log"就相似"bin log"。若是Namenode出現了故障,通常會將原Namenode中持久化的元數據拷貝到secondary namenode中,使secondary namenode做爲新的Namenode運行起來。

HDFS是一個主從結構(master/slave)。如圖所示:

 技術分享

 

4、HDFS可靠性保障措施

HDFS的主要設計目標之一是在故障狀況下,要保障數據存儲的可靠性。

HDFS具有了完善的冗餘備份和故障恢復機制。通常經過dfs.replication設置備份份數,默認3。

一、冗餘備份。將數據寫入到多個DataNode節點上,當其中某些節點宕機後,還能夠從其餘節點獲取數據並複製到其餘節點,使備份數達到設置值。dfs.replication設置備份數。

二、副本存放。HDFS採用機架感知(Rack-aware)的策略來改進數據的可靠性、可用性和網絡寬帶的利用率。當複製因子爲3時,HDFS的副本存放策略是:第一個副本放到同一機架的另外一個節點(執行在集羣中)/隨機一個節點(執行在集羣外)。第二個副本放到本地機架的其餘任意節點。第三個副本放在其餘機架的任意節點。這種策略能夠防止整個機架失效時的數據丟失,也能夠充分利用到機架內的高寬帶特效。

三、心跳檢測。NameNode會週期性的從集羣中的每個DataNode上接收心跳包和塊報告,NameNode根據這些報告驗證映射和其餘文件系統元數據。當NameNode無法接收到DataNode節點的心跳報告後,NameNode會將該DataNode標記爲宕機,NameNode不會再給該DataNode節點發送任何IO操做。同時DataNode的宕機也可能致使數據的複製。通常引起從新複製副本有多重緣由:DataNode不可用、數據副本損壞、DataNode上的磁盤錯誤或者複製因子增大。

四、安全模式。在HDFS系統的時候,會先通過一個徹底模式,在這個模式中,是不容許數據塊的寫操做。NameNode會檢測DataNode上的數據塊副本數沒有達到最小副本數,那麼就會進入徹底模式,並開始副本的複製,只有當副本數大於最小副本數的時候,那麼會自動的離開安全模式。DataNode節點有效比例:dfs.safemode.threshold.pct(默認0.999f),因此說當DataNode節點丟失達到1-0.999f後,會進入安全模式。

五、數據完整性檢測。HDFS實現了對HDFS文件內容的校驗和檢測(CRC循環校驗碼),在寫入數據文件的時候,也會將數據塊的校驗和寫入到一個隱藏文件中()。當客戶端獲取文件後,它會檢查從DataNode節點獲取的數據庫對應的校驗和是否和隱藏文件中的校驗和一致,若是不一致,那麼客戶端就會認爲該數據庫有損壞,將從其餘DataNode節點上獲取數據塊,並報告NameNode節點該DataNode節點的數據塊信息。

六、回收站。HDFS中刪除的文件先會保存到一個文件夾中(/trash),方便數據的恢復。當刪除的時間超過設置的時間閥後(默認6小時),HDFS會將數據塊完全刪除。

七、映像文件和事務日誌。這兩種數據是HDFS中的核心數據結構。

八、快照。

 

5、數據存儲操做

1、數據存儲: block

默認數據塊大小爲128MB,可配置。若文件大小不到128MB,則單獨存成一個block。

爲什麼數據塊如此之大?    數據傳輸時間超過尋道時間(高吞吐率)

一個文件存儲方式?      按大小被切分紅若干個block,存儲到不一樣節點上,默認狀況下每一個block有三個副本。

2、數據存儲: staging

HDFSclient上傳數據到HDFS時,首先,在本地緩存數據,當數據達到一個block大小時,請求NameNode分配一個block。 NameNode會把block所在的DataNode的地址告訴HDFS client。 HDFS client會直接和DataNode通訊,把數據寫到DataNode節點一個block文件中。

 

6、寫入數據

1.初始化FileSystem,客戶端調用create()來建立文件。

2.FileSystem用RPC調用元數據節點,在文件系統的命名空間中建立一個新的文件,元數據節點首先肯定文件原來不存在,而且客戶端有建立文件的權限,而後建立新文件。

3.FileSystem返回DFSOutputStream,客戶端用於寫數據,客戶端開始寫入數據。

4.DFSOutputStream將數據分紅塊,寫入data queue。data queue由Data Streamer讀取,並通知元數據節點分配數據節點,用來存儲數據塊(每塊默認複製3塊)。分配的數據節點放在一個pipeline裏。Data Streamer將數據塊寫入pipeline中的第一個數據節點。第一個數據節點將數據塊發送給第二個數據節點。第二個數據節點將數據發送給第三個數據節點。

5.DFSOutputStream爲發出去的數據塊保存了ack queue,等待pipeline中的數據節點告知數據已經寫入成功。

6.當客戶端結束寫入數據,則調用stream的close函數。此操做將全部的數據塊寫入pipeline中的數據節點,並等待ack queue返回成功。最後通知元數據節點寫入完畢。

7.若是數據節點在寫入的過程當中失敗,關閉pipeline,將ack queue中的數據塊放入data queue的開始,當前的數據塊在已經寫入的數據節點中被元數據節點賦予新的標示,則錯誤節點重啓後可以察覺其數據塊是過期的,會被刪除。失敗的數據節點從pipeline中移除,另外的數據塊則寫入pipeline中的另外兩個數據節點。元數據節點則被通知此數據塊是複製塊數不足,未來會再建立第三份備份。

8.若是在寫的過程當中某個datanode發生錯誤,會採起如下幾步:

1)pipeline被關閉掉;

2)爲了防止防止丟包ack quene裏的packet會同步到data quene裏;

3)把產生錯誤的datanode上當前在寫但未完成的block刪掉;

4)block剩下的部分被寫到剩下的兩個正常的datanode中;

5)namenode找到另外的datanode去建立這個塊的複製。固然,這些操做對客戶端來講是無感知的。

 

Java代碼

Configuration conf = new Configuration();
FileSystem fs = FileSystem.get(conf);
Path file = new Path("demo.txt");
FSDataOutputStream outStream =fs.create(file);
outStream.writeUTF("Welcome to HDFSJava API!!!");
outStream.close();

 

寫入過程圖片:

技術分享

 

7、讀取過程

  1.初始化FileSystem,而後客戶端(client)用FileSystem的open()函數打開文件。

2.FileSystem用RPC調用元數據節點,獲得文件的數據塊信息,對於每個數據塊,元數據節點返回保存數據塊的數據節點的地址。

3.FileSystem返回FSDataInputStream給客戶端,用來讀取數據,客戶端調用stream的read()函數開始讀取數據。

4.DFSInputStream鏈接保存此文件第一個數據塊的最近的數據節點,data從數據節點讀到客戶端(client)

5.當此數據塊讀取完畢時,DFSInputStream關閉和此數據節點的鏈接,而後鏈接此文件下一個數據塊的最近的數據節點。

6.當客戶端讀取完畢數據的時候,調用FSDataInputStream的close函數。

7.在讀取數據的過程當中,若是客戶端在與數據節點通訊出現錯誤,則嘗試鏈接包含此數據塊的下一個數據節點。

8. 失敗的數據節點將被記錄,之後再也不鏈接。

 

Java代碼

Configurationconf = new Configuration(); 
FileSystemfs = FileSystem.get(conf); 
Pathfile = new Path("demo.txt"); 
FSDataInputStreaminStream = fs.open(file); 
Stringdata = inStream.readUTF(); 
System.out.println(data); 
inStream.close();

 

讀取文件過程圖片:

技術分享

 

原文地址:http://jaydenwang.blog.51cto.com/6033165/1842812

相關文章
相關標籤/搜索