HDFS 03 – 你能說說 HDFS 的寫入和讀取過程嗎?

1 – HDFS 文件的寫入

1.1 寫入過程

1、Client 發起文件上傳請求,通過 RPC 與 NameNode 建立連接,NameNode 檢查 Client 是否有相應許可權,以及目標文件是否已存在、父目錄是否存在,向 Client 返回是否可以上傳;

2、Client 從 NameNode 中獲取第一個 block 的傳輸目的地,也就是應該傳輸到哪些 DataNode 上;

3、NameNode 根據配置文件中指定的備份數量及機架感知原理進行文件分配,返回可用的 DataNode 的地址,假設分別是 A、B、C;

機架感知:Hadoop 在設計時考慮到數據存儲的安全與高效,數據文件在 HDFS 上默認存放三份副本。

副本的存儲策略為:客戶端所在 DataNode 一份,同機架內其它某一節點上一份,不同機架的某一節點上一份。

4、Client 先向 DataNode A 上傳數據(也是一個 RPC 調用,建立 pipeline ),A 收到請求會繼續調用 B,然後 B 調用 C,建立完成所有的 pipeline 之後,逐級返回 Client;

5、Client 開始向 DataNode A 上傳第一個 block,以 packet 為單位(默認是64K),A 收到一個 packet 就會傳給 B,B 傳給 C,A 每傳一個 packet 會放入一個 ack 隊列等待應答;

6、數據被分割成一個個的 packet 數據包在 pipeline 上依次傳輸,在 pipeline 反方向上逐個發送 ack(操作是否成功的應答),最終由 pipeline 中第一個 DataNode 節點 A 將 pipelineack 發送給 Client;

7、當一個 block 傳輸完成後,Client 再次請求 NameNode 上傳第二個 block ,繼續上述 (4) – (7) 步驟。

1.2 寫入異常時的處理

當數據寫入失敗時,HDFS 會作出以下反應:

首先管道會被關閉,任何在確認通知隊列中的文件包都會被添加到數據隊列的前端,以確保故障節點下游的 DataNode 不會漏掉任何一個數據包。

為存儲在另一個正常的 DataNode 的當前數據塊指定一個新的標識,並將標識傳送給 NameNode,以便 故障 DataNode 在恢復後可以刪除存儲的部分數據塊

刪除故障 DataNode 的 pipeline 連接,基於兩個正常的 DataNode 構建新的 pipeline,剩餘的數據塊寫入新的 pipeline 中。

NameNode 在注意到副本個數不足時,會在其他 DataNode 上創建一個新的副本。後續的數據塊就能正常的接受處理。

1.3 寫入的一致性

  • 新建一個文件後,HDFS 的命名空間中立即可見;
  • 寫入文件的內容不保證立即可見(即使數據流已經調用 flush() 方法刷新並存儲);
  • 當前正在寫入的塊對其他 Reader 不可見;
  • 調用 hflush() 方法後,數據被寫入 DataNode 的記憶體中,可保證對所有 Reader 可見;
  • 調用 hsync() 方法後,數據就會被寫到磁碟上;
  • 如果沒有調用 hflush()hsync(),客戶端在故障的情況下可能丟失正在寫入的數據塊。

2 – HDFS 文件的讀取

2.1 讀取過程

1、Client 向 NameNode 發起 RPC 請求,來確定請求文件 block 所在的位置;

2、NameNode 會視情況返迴文件的部分或者全部 block 列表:對每個 block,NameNode 都會返回含有該 block 副本的 DataNode 地址 —— 按照集群拓撲結構得出 DataNode 與客戶端的距離,然後進行排序,排序規則是:

網路拓撲結構中距離 Client 近的靠前 —— 網路拓撲需要根據數據中心、機架、數據節點等因素手動設置;

心跳機制中超時彙報的 DataNnode 狀態為 STALE 的排靠後。

3、Client 選取排序靠前的 DataNode 來讀取 block,如果客戶端本身就是 DataNode,就會從本地直接獲取數據(短路讀取特性);

4、底層本質是建立 Socket Stream(FSDataInputStream),重複調用父類 DataInputStream 的 read 方法,直到這個 block 上的數據讀取完畢;

5、當讀完列表的 block 後,若文件讀取還沒有結束,客戶端會繼續向 NameNode 獲取下一批的 block 列表;

DataInputStream#read() 方法是並行讀取 block 資訊,仍然是以 packet 為單位(默認是64K)在 pipeline 上依次傳輸;

6、讀取完所有的 block 後,客戶端會將它們合併成一個完整的文件。

【注意】NameNode 只是返回 Client 請求的 block 的 DataNode 地址,並不會返回 block 的具體數據。

2.2 讀取異常時的處理

1)如果客戶端和所連接的 DataNode 在讀取數據時出現故障,那客戶端就會去嘗試連接存儲這個 block 的下一個最近的 DataNode,同時它會 記錄這個發生故障的 DataNode,以免後面再次連接該節點。

2)客戶端每讀完一個 block 都會進行 checksum 驗證,如果從某個 DataNode 上讀取到的 block 是損壞的,客戶端會通知 NameNode 更新該 block 的相關資訊,然後從下一個擁有該 block 副本的 DataNode 繼續讀取文件。

版權聲明

作者:瘦風(//healchow.com)

出處:部落格園-瘦風的南牆(//www.cnblogs.com/shoufeng)

感謝閱讀,公眾號 「瘦風的南牆」 ,手機端閱讀更佳,還有其他福利和心得輸出,歡迎掃碼關注🤝

本文版權歸部落客所有,歡迎轉載,但 [必須在頁面明顯位置標明原文鏈接],否則部落客保留追究相關人士法律責任的權利。