1. 程式人生 > >剖析HDFS檔案的讀取

剖析HDFS檔案的讀取

 客戶端通過呼叫FileSystem物件的open()方法來開啟希望讀取的檔案,對於HDFS來說,這個物件是DistributedFileSystem的一個例項(圖中的步驟1)。DistributedFileSystem通過使用遠端過程呼叫(RPC)來呼叫namenode,以確定檔案起始塊的位置(步驟2)。 對於每一個塊,namenode 返回存有該塊副本的datanode地址。此外,這些datanode根據它們與客戶端的距離來排序(根據叢集的網路拓撲;)。如果該客戶端本身就是一個datanode (比如,在一個MapReduce任務中),那麼該客戶端將會從儲存有相應資料塊複本的本地datanode讀取資料。

DistributedFileSystem類返回一個FSDataInputStream物件(一個支援檔案定位的輸入流)給客戶端以便讀取資料。FSDataInputStream類轉而封裝DFSInputStream物件,該物件管理著datanode和namenode的I/O。

接著,客戶端對這個輸入流呼叫read()方法(步驟3)。 儲存著檔案起始幾個塊的datanode地址的DFSInputStream隨即連線距離最近的檔案中第一個塊所在的datanode。通過對資料流反覆呼叫read()方法,可以將資料從datanode 傳輸到客戶端(步驟4

)。到達塊的末端時,DFSInputStream關閉與該datanode的連線,然後尋找下一個塊的最佳datanode(步驟5)。 所有這些對於客戶端都是透明的,在客戶看來它一直在讀取一個連續的流。

客戶端從流中讀取資料時,塊是按照開啟DFSInputStream與datanode 新建連線的順序讀取的。它也會根據需要詢問namenode來檢索下一批資料塊的datanode的位置。一旦客戶端完成讀取,就對FSDataInputStream呼叫close()方法(步驟6)。在讀取資料的時候,如果DFSInputStream在與datanode 通訊時遇到錯誤,會嘗試從這個塊的另外一個最鄰近datanode讀取資料。它也記住那個故障datanode,以保證以後不會反覆讀取該節點上後續的塊。DFSInputStream也會通過校驗和確認從datanode發來的資料是否完整。如果發現有損壞的塊,DFSInputStream會試圖從其他datanode讀取其複本,也會將被損壞的塊通知給namenode。

這個設計的一個重點是, 客戶端可以直接連線到datanode檢索資料,且namenode告知客戶端每個塊所在的最佳datanode。 由於資料流分散在叢集中的所有datanode,所以這種設計能使HDFS擴充套件到大量的併發客戶端。同時,namenode只需要響應塊位置的請求(這些資訊儲存在記憶體中,因而非常高效),無需響應資料請求,否則隨著客戶端數量的增長,namenode會很快成為瓶頸。