1. 程式人生 > 其它 >hadoop入門(12):hdfs的讀寫流程

hadoop入門(12):hdfs的讀寫流程

hdfs的寫入流程


檔案具體上傳流程如下:

  • 建立檔案

    1. HDFS client向HDFS寫資料先呼叫DistributedFileSystem.create()
    2. RPC呼叫namenode的create()方法,會在HDFS目錄樹中指定路徑,新增新檔案;並將操作記錄在edits.log中。namenode的create()方法執行完後,返回一個FSDataOutPutStream,他是DFSOutPutStream的包裝類
  • 建立資料流管道pipeline

    1. client呼叫DFSOutPutStream.write()寫資料(先寫檔案的第一個塊,暫時稱為blk1)
    2. DFSOutputStream通過RPC呼叫namenode的addBlock,向namenode申請一個空的資料塊block
    3. addBlock返回一個LocatedBlock物件,此物件包含當前blk要儲存哪三個datanode資訊,比如dn1,dn2,dn3
    4. 客戶端根據位置資訊建立資料流管道
  • 向資料流管道寫入當前塊的資料

    1. 寫資料時,先將資料寫入一個檢驗塊chunk中,寫滿512位元組後,對此chunk計算校驗和chunksum值(4位元組)
    2. 然後將chunk和對應的校驗寫入packet中,一個packet是64kb
    3. 隨著源源不斷的帶校驗chunk寫入packet,當packet寫滿之後將其寫入dataqueue佇列中
    4. packet從佇列中取出,沿著pipeline傳送到dn1,再從dn1傳送到dn2,dn2傳送到dn3
    5. 同時,這個packet也會儲存一份到一個確認佇列ack queue中
    6. packet到達最後一個datanode即nd3之後會做檢驗,然後將檢驗沿結果逆著pipeline方向傳回客戶端,具體檢驗結果從dn3傳到dn2,dn2做檢驗,dn2傳到dn1,dn1做檢驗,結果再傳回客戶端。
    7. 客戶端根據校驗結果,如果“成功”,則將儲存在ack queue中的packet刪除,如果失敗則將packet取出重新放回到dataqueue末尾,等待沿pipeline再次傳輸。
    8. 如此將block中一個數據的一個個packet傳送出去。當block傳送完畢,即dn1,dn2,dn3都接收了blk1的副本,那麼三個datanode分別RPC呼叫namenode的blockReceivedAndDeleted(),namenode會更新記憶體中block與datanode的對應關係(比如dn1上多了個blk1)
  • 關閉三個datanode構建的pipeline,且檔案還有下一個塊的時候,再從4開始直到全部檔案寫完

    1. 最終,呼叫DFSOutputStream的close()。
    2. 客戶端呼叫namenode的complete(),告知namenode檔案傳輸完成。

HDFS寫資料-容錯

Q: 如果在傳輸過程中dn2掛了,則當前piprline中斷,hdfs會怎麼樣?
A: 客戶端RPC會呼叫namenode的updateBlockPipeline()為當前block(假設為blk1)生成新的版本比如ts1(本質上是時間戳),故障dn2會從pipeline中刪除。
DFSOutputStream再RPC呼叫namenode的getAdditionalDatanode()讓namenode重新分配datanode假設為dn4。讓dn1、dn3、dn4組成新的管道,他們上邊的blk1版本設定為新版本ts1.
由於dn4上沒有blk1的資料,客戶端告訴dn1、dn3將其上的blk1資料拷貝給dn4.
新的管道建立好之後,DFSOutputStream呼叫updatePipeline()更新namenode元資料。到此,pipeline恢復,客戶端繼續上傳檔案。
故障的datanode重啟後,namenode發現其上面的blk1的時間戳是老的,會讓datanode將blk1刪除掉。

hdfs的讀取流程


檔案的具體讀取流程如下:

  1. Client端讀取hdfs檔案,client呼叫檔案系統物件DistributedFileSystem的open方法
  2. 返回FSDataInputStream物件(對DFSInputStream的包裝)
  3. 構造DFSInputStream物件時,呼叫namenode的getBlockLocation方法,獲得file開始的若干個block的儲存datanode列表;針對每個block的dn列表,會根據網路拓撲排序,離client近的排在前面。
  4. 呼叫DFSInputStream的read方法讀取blk1的資料,與client最近的datanode建立連線,讀取資料。
  5. 讀取完後,關閉與dn建立的流。
  6. 重複4、5、6步驟,緊接著讀取下一個塊的資料,直到這一批塊的資料讀完。
  7. 讀取下一批塊,重複3、4、5、6、7
  8. 呼叫FSDataInputStream的close方法

HDFS讀資料-容錯

Q: 讀取block資料時,client與datanode連線中斷會怎麼辦?
A: client與第二個儲存此block的datanode建立連線,儲存資料。記錄出問題的datanode,不會再從其上讀取資料。

Q: client讀取資料時,發現block塊的資料有問題怎麼辦?
A: client讀取資料時,同時會讀取到block的校驗和,若client針對讀取的block計算校驗和發現與其讀取的校驗和不一致,說明block損壞。client會從其它存放此block的datanode讀取資料,同樣會計算校驗和,同時告訴namenode此情況。