1. 程式人生 > >剖析HDFS的檔案寫入

剖析HDFS的檔案寫入

 

客戶端通過對DistributedFileSystem 物件呼叫create()來新建檔案(步驟1)。DistributedFileSystem對namenode 建立一個RPC呼叫,在檔案系統的名稱空間中新建一個檔案,此時該檔案中還沒有相應的資料塊(步驟2)。namenode執行各種不同的檢查以確保這個檔案不存在以及客戶端有新建該檔案的許可權。如果這些檢查均通過,namenode就會為建立新檔案記錄一條記錄,如果檢查未通過,會導致檔案建立失敗並向客戶端丟擲一個IOException。DistributedFileSystem向客戶端返回一個FSDataOutputStream物件,由此客戶端可以開始寫入資料。就像讀取事件一樣,FSDataOutputStream封裝一個DFSOutputStream物件,該物件負責處理datanode和namenode之間的通訊。

   


      圖-客戶端將資料寫入HDFS

在客戶端寫入資料時(步驟3), DFSOutputStream將它分成一個個的資料包,並寫入內部佇列,稱為“資料佇列”(data queue)。 DataStreamer處理資料佇列,它的責任是挑選出適合儲存資料複本的一組datanode,並據此來要求namenode分配新的資料塊。這一組 datanode 構成一個管線——我們假設複本數為3,所以管線中有3個節點。DataStreamer將資料包流式傳輸到管線中第1個datanode, 該datanode儲存資料包並將它傳送到管線中的第2個datanode。同樣,第2個datanode儲存該資料包並且傳送給管線中的第3個(也是最後一個)datanode (步驟4
)。
DFSOutputStream也維護著一個內部資料包佇列來等待datanode的收到確認回執,稱為“確認佇列”(ack queue)。收到管道中所有datanode 確認資訊後,該資料包才會從確認佇列刪除(步驟5)。

     如果任何datanode 在資料寫人期間發生故障,則執行以下操作(對寫人資料的客戶端是透明的)。首先關閉管線,確認把佇列中的所有資料包都添加回資料佇列的最前端,以確保故障節點下游的datanode 不會漏掉任何一個數據包。為儲存在另一正常datanode的當前資料塊指定一- 個新的標識,並將該標識傳送給namenode, 以便故障datanode在恢復後可以刪除儲存的部分資料塊。從管線中刪除故障datanode,基於兩個正常datanode 構建一條新管線。餘下的資料塊寫入管線中正常的datanode。namenode 注意到塊複本量不足時,會在另一個節點上建立一個新的複本。後續的資料塊繼續正常接受處理。

     在一個塊被寫入期間可能會有多個datanode同時發生故障,但非常少見。只要寫入了dfs.namenode.replication.min的複本數(預設為1),寫操作就會成功,並且這個塊可以在叢集中非同步複製,直到達到其目標複本數(dfs.replication的預設值為3)。

      客戶端完成資料的寫入後,對資料流呼叫close()方法(步驟6
)。該操作將剩氽的所有資料包寫人datanode 管線,並在聯絡到namenode告知其檔案寫人完成之前,等待確認(步驟7)。namenode已經知道檔案由哪些塊組成(因為Datastreamer請求分配資料塊),所以它在返回成功前只需要等待資料塊進行最小量的複製。