之因此選擇 HDFS 存儲數據,由於 HDFS 具備如下優勢:node
一、高容錯性緩存
二、適合批處理服務器
三、適合大數據處理網絡
四、流式文件訪問架構
五、可構建在廉價機器上併發
固然 HDFS 也有它的劣勢,並不適合全部的場合:app
一、低延時數據訪問框架
二、小文件存儲分佈式
三、併發寫入、文件隨機修改oop
HDFS的架構圖
HDFS 採用Master/Slave的架構來存儲數據,這種架構主要由四個部分組成,分別爲HDFS Client、NameNode、DataNode和Secondary NameNode。下面咱們分別介紹這四個組成部分
一、Client:就是客戶端。
二、NameNode:就是 master,它是一個主管、管理者。
三、DataNode:就是Slave。NameNode 下達命令,DataNode 執行實際的操做。
四、Secondary NameNode:並不是 NameNode 的熱備。當NameNode 掛掉的時候,它並不能立刻替換 NameNode 並提供服務。
首先:HDFS是一個文件系統,用於存儲和管理文件,經過統一的命名空間(相似於本地文件系統的目錄樹)。是分佈式的,服務器集羣中各個節點都有本身的角色和職責。
其次:
1.HDFS中的文件在物理上是分塊存儲(block),塊的大小能夠經過配置參數( dfs.blocksize)來規定,默認大小在hadoop2.x版本中是128M,以前的版本中是64M。
2.HDFS文件系統會給客戶端提供一個統一的抽象目錄樹,客戶端經過路徑來訪問文件,形如:hdfs://namenode:port/dir-a/dir-b/dir-c/file.data
3.目錄結構及文件分塊位置信息(元數據)的管理由namenode節點承擔,namenode是HDFS集羣主節點,負責維護整個hdfs文件系統的目錄樹,以及每個路徑(文件)所對應的數據塊信息(blockid及所在的datanode服務器)
4.文件的各個block的存儲管理由datanode節點承擔,datanode是HDFS集羣從節點,每個block均可以在多個datanode上存儲多個副本(副本數量也能夠經過參數設置dfs.replication,默認是3)
5.Datanode會按期向Namenode彙報自身所保存的文件block信息,而namenode則會負責保持文件的副本數量,HDFS的內部工做機制對客戶端保持透明,客戶端請求訪問HDFS都是經過向namenode申請來進行。
6.HDFS是設計成適應一次寫入,屢次讀出的場景,且不支持文件的修改。須要頻繁的RPC交互,寫入性能很差。
NameNode 負責管理整個文件系統元數據;DataNode 負責管理具體文件數據塊存儲;Secondary NameNode 協助 NameNode 進行元數據的備份。
HDFS 的內部工做機制對客戶端保持透明,客戶端請求訪問 HDFS 都是經過向NameNode 申請來進行。
詳細步驟解析:
一、 client 發起文件上傳請求,經過 RPC 與 NameNode 創建通信,NameNode檢查目標文件是否已存在,父目錄是否存在,返回是否能夠上傳;
二、 client 請求第一個 block 該傳輸到哪些 DataNode 服務器上;
三、 NameNode 根據配置文件中指定的備份數量及副本放置策略進行文件分配,返回可用的 DataNode 的地址,如:A,B,C;注:默認存儲策略由 BlockPlacementPolicyDefault 類支持。也就是平常生活中提到最經典的 3副本策略 。
1st replica 若是寫請求方所在機器是其中一個 datanode,則直接存放在本地,不然隨機在集羣中選擇一個 datanode.
2nd replica 第二個副本存放於不一樣第一個副本的所在的機架.
3rd replica 第三個副本存放於第二個副本所在的機架,可是屬於不一樣的節點
如圖:
四、 client 請求 3 臺 DataNode 中的一臺 A 上傳數據(本質上是一個 RPC 調用,創建 pipeline),A 收到請求會繼續調用 B,而後 B 調用 C,將整個pipeline 創建完成,後逐級返回 client;
五、 client 開始往 A 上傳第一個 block(先從磁盤讀取數據放到一個本地內存緩存),以 packet 爲單位(默認 64K),A 收到一個 packet 就會傳給 B,B 傳給 C;A 每傳一個 packet 會放入一個應答隊列等待應答。
六、 數據被分割成一個個 packet 數據包在 pipeline 上依次傳輸,在pipeline 反方向上,逐個發送 ack(命令正確應答),最終由 pipeline中第一個 DataNode 節點 A 將 pipeline ack 發送給 client;
七、 當一個 block 傳輸完成以後,client 再次請求 NameNode 上傳第二個block 到服務器。
--------
詳細步驟解析:
一、 Client 向 NameNode 發起 RPC 請求,來肯定請求文件 block 所在的位置; 二、 NameNode會視狀況返回文件的部分或者所有block列表,對於每一個block,NameNode 都會返回含有該 block 副本的 DataNode 地址; 三、 這些返回的 DN 地址,會按照集羣拓撲結構得出 DataNode 與客戶端的距離,而後進行排序,排序兩個規則:網絡拓撲結構中距離 Client 近的排靠前;心跳機制中超時彙報的 DN 狀態爲 STALE,這樣的排靠後; 四、 Client 選取排序靠前的 DataNode 來讀取 block,若是客戶端自己就是DataNode,那麼將從本地直接獲取數據; 五、 底層上本質是創建 Socket Stream(FSDataInputStream),重複的調用父類 DataInputStream 的 read 方法,直到這個塊上的數據讀取完畢; 六、 當讀完列表的 block 後,若文件讀取尚未結束,客戶端會繼續向NameNode 獲取下一批的 block 列表; 七、 讀取完一個 block 都會進行 checksum 驗證,若是讀取 DataNode 時出現錯誤,客戶端會通知 NameNode,而後再從下一個擁有該 block 副本的DataNode 繼續讀。 八、 read 方法是並行的讀取 block 信息,不是一塊一塊的讀取;NameNode 只是返回Client請求包含塊的DataNode地址,並非返回請求塊的數據; 九、 最終讀取來全部的 block 會合併成一個完整的最終文件。