本文知識 由 hadoop權威指南第四版得到,圖片也來自與此node
client經過調用 FileSystem對象的open()方法來打開文件。在HDFS中,FileSystem是DistributedFileSystem的一個實例。DistributedFileSystem是經過RPC調用namenode,獲取文件起始block的位置。對於每個block,namenode會返回存有該block副本的datanode地址,並且datanode 根據與client的距離來排序。若是該client自己就是一個datanode,並保存有相應數據塊的一個副本時,該節點會從本地datanode讀取數據。併發
DistributedFileSystem 會返回給client FSDataInputStream對象 用於讀取數據。FSDataInputStream包裝了 DFSInputStream對象,該對象管理着datanode和namenode的I/O。client調用read()方法時,FSDataInputStream會鏈接距離最近的datanode。經過反覆調用read()方法,將數據從datanode傳輸到客戶端。當讀取完一個block時,DFSInputStream 會關閉與datanode的鏈接。而後尋找下一個block的最佳datanode。這寫操做對客戶端是透明的。異步
在讀取數據期間,若是 DFSInputStream 在與datanode 通訊時遇到錯誤,會嘗試從這個block的另外一個最近的datanode讀取數據。而且會記住這個故障的datanode,確保不會反覆讀取該節點上後續的block。DFSInputStream 也會經過校驗從datanode讀取的數據是否完整。若是發現有block的損壞,DFSInputStream 會嘗試從其餘datanode讀取備份,並將該損壞的blocak報告給namenode。oop
這個設計有個很是重要的一面,namenode 告訴client每一個block 最佳的datanode,client能夠直接鏈接該datanode 並檢索數據。由於數據流分散到 集羣中的datanode中,這種設計可使HDFS 可以處理大量的併發鏈接。同時,namenode只相應塊位置的請求(這些信息存儲在內存中,因此很是高效)。namenode不響應數據的請求,不然隨着client併發量的增加,namenode的性能將稱爲瓶頸。佈局
client經過調用 create()方法在DistributedFileSystem建立文件。DistributedFileSystem 會經過RPC調用namenode在 文件系統命名空間中新建一文件,可是該文件並未有block。namenode會執行嚴格的檢查確保文件不存在而且client有新建該文件的權限。若是經過這些檢查,namenode就會爲這個新文件建立一個記錄(the namenode makes a record of the new file).不然,文件建立失敗,client會拋出一個IOException。性能
DistributedFileSystem向 client返回一個FSDataOutputStream對象,client拿到該對象就能夠開始寫入數據。就像數據讀取同樣,FSDataOutputStream 包裝了 DFSOutputStream,該對象處理datanode和namenode通訊。ui
client在寫入數據時,DFSOutputStream將它分紅一個個的數據包,並寫入內部數據隊列(data queue)。data queue由 DataStreamer處理,DataStreamer責任是,根據datanode列表請求namenode分配blocks用以存儲 數據副本。(The data queue is consumed by the DataStreamer , which is responsible for asking the namenode to allocate new blocks by picking a list of suitable datanodes to store the replicas.) 這一組datanode造成一個管道流,如上圖(假設有3個副本)。DataStreamer 將數據包發給pipeline的第一個datanode,該datanode存儲數據包並將它發送到第二個datanode,以此類推。設計
DFSOutputStream 也維護一個內部數據包隊列等待接受datanode的確認回執(ack queue)。在收到管道中全部的datanode確認信息後,該數據包纔會從 ack queue 中刪除。
若是數據在寫入期間datanode fail,則會執行如下操做(對客戶端是透明的)。對象
當client完成數據的寫入後,會調用close()方法關閉流。該操做會將 剩餘的全部的數據包寫入datanode pipeline,等待確認文件寫入完成,並聯系namenode發送完成信號。namenode已經知曉文件是由那些塊構成的,因此在它返回成功錢只須要等待block進行最小量的複製。blog
Hadoop默認block存放佈局策略是,運行在客戶端節點上存放第一個replica(若是客戶端運行在集羣節點以外,就隨機選擇一個節點,不過系統不會選擇存儲太滿或者太忙的節點)。第二個replica放在與第一個不一樣且隨機選擇的機架中節點上。第三個replica與第二個replica放在同一個機架上,隨機選擇一個節點存放。其餘replica放在集羣中隨機選擇的節點上,不一樣系統會盡可能避免在同一個機架上放太多的replica。