Hadoop檔案寫入(詳細剖析)
步驟詳情:
檔案是如何寫入 HDFS 的。儘管比較詳細,但對於理解資料流還是很有用的,因為它清楚地說明了 HDFS 的一致模型。要考慮的情況是如何建立一個新檔案,並把資料寫入該檔案,最後關閉該檔案。參見上圖客戶端通過對 DistributedFileSystem 物件呼叫 create()函式來建立檔案(圖步驟1)。 DistributedFileSystem 對 namenode 建立一個 RPC 呼叫,在檔案系統的名稱空間中建立一個新檔案,此時該檔案中還沒有相應的資料塊(步驟 2)。 namenode 執行各種不同的檢查以確保這個檔案不存在,並且客戶端有建立該檔案的許可權。如果這些檢查翊通過, namenode就會為建立新檔案記錄一條記錄;否則,檔案建立失敗並向客戶端丟擲一個 IOException 異常 DistributedFileSystem 想客戶端返回一個 FSDataOutputStream 物件,由此客戶端可以開始寫入資料。就像讀取事件一樣, FSDataOutputStream 封裝一個 DFSoutPutstream 物件,該物件負責處理 datanode 和 namenode 之間的通訊。在客戶端寫入資料時(步驟 3), DFSOutputStream 將它分成一個個的資料包,並寫入內部佇列,稱為“資料佇列” (data queue)。 DataStreamer 處理資料佇列,它的責任是根據datanode 列表來要求 namenode 分配適合的新塊來儲存資料備份。這一組 datanode 構成一個管線一一假設複本數為 3,所以管線中有 3 個節點。 DataStreamer 將資料包流式傳輸到管線中第 1 個datanode,該 datanode 儲存資料包並將它傳送到管線中的第 2 個 datanode。同樣地,第 2 個 datanode 儲存該資料包並且傳送給管線中的第3 DFSOutputStream 也維護著一個內部資料包佇列來等待 datanode 的收到確認回執,稱為“確認佇列” (ack queue)。當收到管道中所有 datanode 確認資訊後,該資料包才會從確認佇列刪除(步驟 5)。如果在資料寫入期間, datanode 發生故障,則執行以下操作,這對與寫入資料的客戶端是透明的。首先關閉管線,確認把佇列中的任何資料包都添加回資料佇列的最前端,以確保故障節點下游的 datanode 不會漏掉任何一個數據包。為儲存在另一正常 datanode 的當前資料塊指定一個新的標識,並將該標識傳送給 namenode,以便故障 datanode 在恢復後可以刪除儲存的部分資料塊。從管線中刪除故障資料節點並且把餘下的資料塊寫入管線中的兩個正常的的 datanode。 namenode 注意到塊複本量不足時,會在另一個節點上建立一個新的複本。後續的資料塊繼續正常接受處理。在一個塊被寫入期間可能會有多個 datanode 同時發生故障,但非常少見。只要寫入了dfs. replication. min 的複本數(預設為 1),寫操作就會成功,並且這個塊可以在叢集中非同步複製,直到達到其目標複本數( dfs. replication 的預設值為 3)。客戶端完成資料的寫入後,會對資料流呼叫 close()方法(步驟 6)。該操作將剩餘的所有資料包寫入 datanode 管線中,並在聯絡 namenode 且傳送檔案寫入完成訊號之前,等待確認(步驟 7)
步驟總結:
由上圖可知;寫入檔案分為三個角色,分別是clientnode namenode 和datanode
cliennode本質為java虛擬機器.namenode 和datanode則是Hadoop資料叢集儲存塊
第一步:create實際是客戶端建立DistributedFileSystem例項化物件
第二步 create通過例項化物件錄取呼叫物件中create()方法,此方法訪問namenode,那麼弄得收到命令,首先判斷datanode中所寫的檔案是否有重複,然後在檢查namenode是否有可寫入空餘的空間.當二者同時滿足是,namenode寫將datanode路徑資訊,檔案數等記錄,並確認資訊返回DistributedFileSystem,否則返回異常,DistributedFileSystem收到確認資訊後向客戶端返回一個FSDataOutputStream FSDataOutputStream物件
第三步:例項化例項化FSDataOutputStreamFSDataOutputStream物件(該物件負責處理 datanode 和 namenode 之間的通訊 ),呼叫該物件的write()方法, 即是圖中write實現過程該物件負責處理 datanode 和 namenode 之間的通訊
第四步:方法將資料分成多個數據包,並寫入內部佇列. DFDataOutStream 將寫入的資料分成多個數據包,並寫入內部佇列中,同時開啟datanode中DataStreamer處理資料佇列,它負責根據datanode列來要求namenode分配合適的新塊儲存資料備份開啟管道機制依次執行步驟4,同時即是write packet完整過程
第五步:每執行一次4就有一次步驟5返回確認資訊.
4和5屬於分別在DataQueue佇列和ACKQueue佇列,當每執行一次4就將此步確認資訊放到ACKQueue佇列中
如圖:
第七步:DistributeFileStream 返回給namenode確認資訊.
註釋:第4-5部分實現在後臺完成步不一定在第七步之前,
當執行第四步就就收第5步確認資訊,告訴namenode 資料寫入成功,即是第七步.
如有不明之處私信與我,相互交流經驗.,懇請多多指正.謝謝!