客戶端與HDFS文件讀取
建立HDFS文件系統實例
FileSystem fs = FileSystem.get(new URI("hdfs://ns1"), new Configuration(),"root");
客戶端經過調用FileSystem對象fs的Open()方法打開要讀取的文件,DistributedFileSystem經過使用RPC來調用NameNode,以肯定文件起始塊的位置。
對於文件的每個塊,NameNode返回存有該塊副本的DataNode地址。這些DataNode根據它們與客戶端的距離來排序(根據集羣中的網絡拓撲)。如
果該客戶端自己就是一個DataNode(例如在一個MapReduce任務中)並保存有相應數據塊的一個副本時,該節點就會從本地DataNode讀取數據。而後
DistributedFileSystem返回一個FSDataInputStream對象(支持文件定位的輸入流)給客戶端讀取數據。FSDataInputStream類轉而封裝DFSInputStream
對象,該對象管理着DataNode和NameNode的I/O。
FSDataInputStream in = fs.open(new Path(dfsPath));
接着客戶端對這個輸入流調用read()方法讀取,存儲着文件起始位置的幾個塊的DataNode地址的DFSInputStream隨機連接距離最近的DataNode。經過
對數據流反覆調用read()方法,將數據從DataNode傳輸到客戶端,到達快的末端時,DFSInputStream關閉與該DataNode的鏈接,而後尋找下一個塊的
最佳DataNode,客戶端只須要讀取連續的流。客戶端從流中讀取數據時,塊是按照打開DFSInputStream與DataNode新建鏈接順序的讀取的,它也會根
據須要詢問NameNode來檢索下一批數據塊的DataNode的位置,一旦客戶端讀取完成就對DFSInputStream調用close()方法釋放。在讀取數據時,若是
DFSInputStream在與DataNode通訊時遇到錯誤,會嘗試從這個塊的另一個最鄰近的DataNode讀取數據。它也會記住那個故障的DataNode,以保證
之後不會從那個故障DataNode節點反覆讀取後續的塊數據。DFSInputStream也會經過校驗和確認從DataNode發來的數據是否完整。若是發現有損壞的
塊,就在DFSInputStream試圖從其餘DataNode讀取其副本以前通知NameNode。這個設計的一個重點是:NameNode告知客戶端每一個塊中最佳的
DataNode,並讓客戶端直接鏈接到該最佳DataNode上檢索數據。因爲數據流分散在集羣中的全部DataNode上,因此這種設計能使HDFS可擴展到大量
的併發客戶端。同時,NameNode只須要響應塊位置的請求(這些塊位置信息存儲在內存中,於是很是高效),無需響應數據請求,不然隨着客戶端數量
的增加,NameNode會很快成爲瓶頸。
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(new File(localPath)));
IOUtils.copyBytes(in, out, 4096, true);
Hadoop的網絡拓撲解釋
在本地網絡中,兩個節點被稱爲「彼此近鄰」是指:在海里數據處理中,其主要限制因素是節點之間數據的傳輸速率-帶寬很稀缺。這裏的想法是將兩個
節點間的帶寬做爲軍力的衡量標準。若是不用衡量節點間的帶寬則很難實現(須要一個穩定的集羣,而且在集羣中兩兩節點對數量是節點數量的平方)。
Hadoop爲此採用了一種簡單的方法:把網絡當作一棵樹,兩個節點間的距離是它們到最近共同祖先的距離綜合。該書中的層次是沒有預先設定的,可是相對
於數據中心、機架和正在運行的節點,一般能夠設定等級。具體是針對如下每一個場景,可用帶寬一次遞減,以下:
同一節點上的進程
同一機架上的不一樣節點
同一數據中心的不一樣機架上的節點
不一樣數據中心的節點
跨數據中心運行 目前到Hadoop-2.7仍然不適合跨數據中心運行。