hadoop架構組成java
hadoop有兩部分組成:分佈式文件系統HDFS,統一的資源管理器YARNnode
hdfs架構web
Client:切分文件;訪問或經過命令行管理HDFS;與NameNode交互,獲取文件位置信息;與DataNode交互,讀取和寫入數據。
NameNode:Master節點,只有一個,管理HDFS的名稱空間和數據塊映射信息;配置副本策略;處理客戶端請求。
DataNode:Slave節點,存儲實際的數據;執行數據塊的讀寫;彙報存儲信息給NameNode。
Secondary NameNode:輔助NameNode,分擔其工做量;按期合併fsimage和fsedits,推送給NameNode;緊急狀況下,可輔助恢復NameNode,但Secondary NameNode並不是NameNode的熱備。apache
fsimage和fsedits安全
NameNode中兩個很重要的文件,
fsimage是元數據鏡像文件(保存文件系統的目錄樹)。
edits是元數據操做日誌(記錄每次保存fsimage以後到下次保存之間的全部hdfs操做)。網絡
fsimage文件實際上是Hadoop文件系統元數據的一個永久性的檢查點,其中包含Hadoop文件系統中的全部目錄和文件idnode的序列化信息;
edits文件存放的是Hadoop文件系統的全部更新操做的路徑,文件系統客戶端執行的因此寫操做首先會被記錄到edits文件中。架構
內存中保存了最新的元數據信息(fsimage和edits)。併發
edits過大會致使NameNode重啓速度慢,Secondary NameNode負責按期合併它們。框架
合併流程圖分佈式
數據塊的映射關係
1)包括兩種:文件與數據塊映射關係,DataNode與數據塊映射關係;
2)NameNode啓動的時候,可經過心跳信息重構映射信息,DataNode運行過程當中定時彙報當前block信息;映射關係保存在NameNode內存中。
3)NameNode重啓速度慢(須要加載經過合併fsimage與edits文件生成的最新目錄樹以及DataNode的塊信息)
數據塊(block)
1)在HDFS中,文件被切分紅固定大小的數據塊,默認大小爲64MB,也可本身配置。
2)爲什麼數據塊如此大,由於數據傳輸時間超過尋道時間(高吞吐率)。
3)文件的存儲方式:按大小被切分紅若干個block,存儲到不一樣節點上,默認狀況下每一個block有三個副本。
HDFS的默認副本存放策略
Hadoop 0.17 以後:副本1-同Client的節點上;副本2-不一樣機架中的節點上;副本3-同第二個副本的機架中的另外一個節點上;其餘副本:隨機挑選。以下圖示例:
HDFS可靠性機制
常見錯誤狀況:文件損壞;網絡或者機器失效;NameNode掛掉;
文件的完整性:經過CRC32校驗,若是有損壞,用其餘副本替代損壞文件;
Heartbeat:DataNode按期向NameNode發送eartbeat;
元數據信息:FsImage、Editlog進行多份備份,當NameNode宕機後,可手動還原。
HDFS 數據備份
HDFS被設計成一個能夠在大集羣中、跨機器、可靠的存儲海量數據的框架。它將全部文件存儲成block塊組成的序列,除了最後一個block塊,全部的block塊大小都是同樣的。文件的全部block塊都會由於容錯而被複制。每一個文件的block塊大小和容錯複製份數都是可配置的。容錯複製份數能夠在文件建立時配置,後期也能夠修改。HDFS中的文件默認規則是write one(一次寫、屢次讀)的,而且嚴格要求在任什麼時候候只有一個writer。NameNode負責管理block塊的複製,它週期性地接收集羣中全部DataNode的心跳數據包和Blockreport。心跳包表示DataNode正常工做,Blockreport描述了該DataNode上全部的block組成的列表。
備份數據的存放:
備份數據的存放是HDFS可靠性和性能的關鍵。HDFS採用一種稱爲rack-aware的策略來決定備份數據的存放。經過一個稱爲Rack Awareness的過程,NameNode決定每一個DataNode所屬rack id。缺省狀況下,一個block塊會有三個備份,一個在NameNode指定的DataNode上,一個在指定DataNode非同一rack的DataNode上,一個在指定DataNode同一rack的DataNode上。這種策略綜合考慮了同一rack失效、以及不一樣rack之間數據複製性能問題。
副本的選擇:
爲了下降總體的帶寬消耗和讀取延時,HDFS會盡可能讀取最近的副本。若是在同一個rack上有一個副本,那麼就讀該副本。若是一個HDFS集羣跨越多個數據中心,那麼將首先嚐試讀本地數據中心的副本。
安全模式:
系統啓動後先進入安全模式,此時系統中的內容不容許修改和刪除,直到安全模式結束。安全模式主要是爲了啓動檢查各個DataNode上數據塊的安全性。
HDFS的讀寫流程
HDFS文件讀取:
首先調用FileSystem對象的open方法,實際上是一個DistributedFileSystem的實例
DistributedFileSystem經過rpc得到文件的第一批個block的locations,同一block按照重複數會返回多個locations,這些locations按照hadoop拓撲結構排序,距離客戶端近的排在前面.
前兩步會返回一個FSDataInputStream對象,該對象會被封裝成DFSInputStream對象,DFSInputStream能夠方便的管理datanode和namenode數據流。客戶端調用read方法,DFSInputStream最會找出離客戶端最近的datanode並鏈接。
數據從datanode源源不斷的流向客戶端。
若是第一塊的數據讀完了,就會關閉指向第一塊的datanode鏈接,接着讀取下一塊。這些操做對客戶端來講是透明的,客戶端的角度看來只是讀一個持續不斷的流。
若是第一批block都讀完了,DFSInputStream就會去namenode拿下一批blocks的location,而後繼續讀,若是全部的塊都讀完,這時就會關閉掉全部的流。
package test; import java.io.IOException; import java.net.URI; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.fs.Path; import org.apache.hadoop.fs.FSDataInputStream; import org.apache.hadoop.fs.FSDataOutputStream;; public class Test { public void WriteFile(String hdfs) throws IOException { Configuration conf = new Configuration(); FileSystem fs = FileSystem.get(URI.create(hdfs),conf); FSDataOutputStream hdfsOutStream = fs.create(new Path(hdfs)); hdfsOutStream.writeChars("hello"); hdfsOutStream.close(); fs.close(); } public void ReadFile(String hdfs) throws IOException { Configuration conf = new Configuration(); FileSystem fs = FileSystem.get(URI.create(hdfs),conf); FSDataInputStream hdfsInStream = fs.open(new Path(hdfs)); byte[] ioBuffer = new byte[1024]; int readLen = hdfsInStream.read(ioBuffer); while(readLen!=-1) { System.out.write(ioBuffer, 0, readLen); readLen = hdfsInStream.read(ioBuffer); } hdfsInStream.close(); fs.close(); } public static void main(String[] args) throws IOException { String hdfs = "hdfs://192.168.56.112:9000/test/hello.txt"; Test t = new Test(); t.WriteFile(hdfs); t.ReadFile(hdfs); } }
HDFS讀取發生異常處理
若是在讀數據的時候,DFSInputStream和datanode的通信發生異常,就會嘗試正在讀的block的排第二近的datanode,而且會記錄哪一個datanode發生錯誤,剩餘的blocks讀的時候就會直接跳過該datanode。DFSInputStream也會檢查block數據校驗和,若是發現一個壞的block,就會先報告到namenode節點,而後DFSInputStream在其餘的datanode上讀該block的鏡像
HDFS讀操做設計思考
客戶端直接鏈接datanode來檢索數據而且namenode來負責爲每個block提供最優的datanode,namenode僅僅處理block location的請求,這些信息都加載在namenode的內存中,hdfs經過datanode集羣能夠承受大量客戶端的併發訪問。
HDFS文件寫入
客戶端經過調用DistributedFileSystem的create方法建立新文件
DistributedFileSystem經過RPC調用namenode去建立一個沒有blocks關聯的新文件,建立前,namenode會作各類校驗,好比文件是否存在,客戶端有無權限去建立等。若是校驗經過,namenode就會記錄下新文件,不然就會拋出IO異常.
前兩步結束後會返回FSDataOutputStream的對象,和讀文件的時候類似,FSDataOutputStream被封裝成DFSOutputStream,DFSOutputStream能夠協調namenode和datanode。客戶端開始寫數據到DFSOutputStream,DFSOutputStream會把數據切成一個個小packet,而後排成隊列data quene。
DataStreamer會去處理接受data quene,他先問詢namenode這個新的block最適合存儲的在哪幾個datanode裏,好比重複數是3,那麼就找到3個最適合的datanode,把他們排成一個pipeline.DataStreamer把packet按隊列輸出到管道的第一個datanode中,第一個datanode又把packet輸出到第二個datanode中,以此類推。
DFSOutputStream還有一個對列叫ack quene,也是有packet組成,等待datanode的收到響應,當pipeline中的全部datanode都表示已經收到的時候,這時akc quene纔會把對應的packet包移除掉。
客戶端完成寫數據後調用close方法關閉寫入流
DataStreamer把剩餘得包都刷到pipeline裏而後等待ack信息,收到最後一個ack後,通知datanode把文件標示爲已完成。
HDFS文件寫入失敗 若是在寫的過程當中某個datanode發生錯誤,會採起如下幾步: 1.pipeline被關閉 2.爲了防止防止丟包ack quene裏的packet會同步到data quene 3.把產生錯誤的datanode上當前在寫但未完成的block刪 4.block剩下的部分被寫到剩下的兩個正常的datanode 5.namenode找到另外的datanode去建立這個塊的復 這些操做對客戶端來講是無感知的。 (客戶端執行write操做後,寫完得block纔是可見的,正在寫的block對客戶端是不可見的,只有調用sync方法,客戶端才確保該文件被寫操做已經所有完成,當客戶端調用close方法時會默認調用sync方法。是否須要手動調用取決你根據程序須要在數據健壯性和吞吐率之間的權衡。)