1. 程式人生 > >HDFS讀寫檔案的過程

HDFS讀寫檔案的過程

HDFS寫入流程

客戶端將資料寫入HDFS流程圖
1、 使用HDFS提供的客戶端Client, 向遠端的Namenode發起RPC請求
2、 Namenode會檢查要建立的檔案是否已經存在, 建立者是否有許可權進行操作, 成功則會為檔案建立一個記錄, 否則會讓客戶端丟擲異常;
3、 當客戶端開始寫入檔案的時候, 客戶端會將檔案切分成多個packets, 並在內部以資料佇列“data queue( 資料佇列) ”的形式管理這些packets, 並向Namenode申請blocks, 獲取用來儲存replicas的合適的datanode列表, 列表的大小根據Namenode中replication的設定而定;
4、 開始以pipeline( 管道) 的形式將packet寫入所有的replicas中。 開發庫把packet以流的方式寫入第一個datanode, 該datanode把該packet儲存之後, 再將其傳遞給在此pipeline中的下一個datanode, 直到最後一個datanode, 這種寫資料的方式呈流水線的形式。
5、 最後一個datanode成功儲存之後會返回一個ack packet( 確認佇列) , 在pipeline裡傳遞至客戶端, 在客戶端的開發庫內部維護著”ack queue”, 成功收到datanode返回的ack packet後會從”ack queue”移除相應的packet。
6、 如果傳輸過程中, 有某個datanode出現了故障, 那麼當前的pipeline會被關閉, 出現故障的datanode會從當前的pipeline中移除, 剩餘的block會繼續剩下的datanode中繼續以pipeline的形式傳輸, 同時Namenode會分配一個新的datanode, 保持replicas設定的數量。
7、 客戶端完成資料的寫入後, 會對資料流呼叫close()方法, 關閉資料流;
8、 只要寫入了dfs.replication.min的複本數( 預設為1) , 寫操作就會成功, 並且這個塊可以在叢集中非同步複製, 直到達到其目標複本數( dfs. replication的預設值為3) , 因為namenode已經知道檔案由哪些塊組成, 所以它在返回成功前只需要等待資料塊進行最小量的複製。

客戶端寫入HDFS的動作
從上面的圖中,我們可以清楚的看出NameNode對應於使用者的三個動作分別
以create、 addBlock、 complete來進行相關的處理。現在,我就來詳細的分析NameNode的這三個動作是如何實現的。
1. NameNode的create動作主要是為客戶端傳過來的檔名在HDFS的Namesystem中申請一個名字空間,併為之建立一個響應的iNode,當然,這個iNode的狀態是underConstruction,然後為這個客戶建立一個該檔案的租約,就是檔案的獨佔鎖,以防止其它的客戶端對這個檔案同時寫。
2. NameNode的addBlock動作主要是為檔案建立一個新的Block,併為這個Block的副本分配儲存DataNode節點,最後給客戶端返回一個LocatedBlock物件,該物件包含Block的副本應該存放的位置。在這裡我想說得是,NameNode節點此時並不儲存該Block的副本位置,而是等到成功接收該Block的資料節點自動報告時它才正式記錄該Block的一個副本的位置,這樣做是由於HDFS不能保證Block一開始分配的資料節點都能成功結束Block。
3. NameNode的complete動作就是更改與當前檔案節點相關的狀態,同時釋放檔案的租約。另外,NameNode還要判斷檔案的所有Blocks的副本是否已滿足,對於還不滿足的Blocks, NameNode將其放入neededReplications佇列中,讓其它的後臺執行緒來負責這些Block的副本情況。

HDFS讀取流程

客戶端從HDFS中讀取資料

1、 使用HDFSᨀ供的客戶端Client, 向遠端的Namenode發起RPC請求;
2、 Namenode會視情況返回檔案的部分或者全部block列表, 對於每個block, Namenode都會返回有該block拷貝的DataNode地址;
3、 客戶端Client會選取離客戶端最近的DataNode來讀取block; 如果客戶端本身就是DataNode, 那麼將從本地直接獲取資料;
4、 讀取完當前block的資料後, 關閉當前的DataNode連結, 併為讀取下一個block尋找最佳的DataNode;
5、 當讀完列表block後, 且檔案讀取還沒有結束, 客戶端會繼續向Namenode獲取下一批的block列表;
6、 讀取完一個block都會進行checksum驗證, 如果讀取datanode時出現錯誤, 客戶端會通知Namenode, 然後再從下一個擁有該block拷貝的datanode繼續讀。