HDFS深度歷險 之 從客戶端邏輯看HDFS寫入機制

来源:https://www.cnblogs.com/monkeyteng/archive/2019/01/04/10220395.html
-Advertisement-
Play Games

通過查網上資料和鑽研HDFS源碼,理清HDFS的寫入機制和流程 ...


說明

除了標註之外,本文純屬原創,轉載請註明出處:https://www.jianshu.com/p/ea6ef5f5b868https://www.cnblogs.com/monkeyteng/p/10220395.html

HDFS架構簡介

Hadoop的框架最核心的設計就是:HDFS和MapReduce。HDFS為海量的數據提供了存儲,則MapReduce為海量的數據提供了計算。本文基於Hadoop 2.7.3源碼,分析本地文件推送(新建/追加)到的HDFS客戶端邏輯。

HDFS架構圖

  1. HDFS架構主要包含兩種類型的節點:NameNode和DataNode。
  2. NameNode,其實就是名位元組點,其功能類似於我們常用的磁碟文件系統中的inode。對於HDFS而言,NameNode相當於“目錄管理器”和“inode表”。
  3. NameNode保存兩類關鍵的映射表:
  • 名字空間表:從文件名到數據塊(DataBlock)的映射,這部分數據保存在NameNode伺服器的磁碟。
  • inode表:從數據塊(DataBlock)到機器的映射,包括每一個數據塊保存在哪一個或者哪幾個機器上。這部分數據在每次重啟NameNode的時候都會和DataNode通訊並重建。
  1. 對於Hadoop 2.7.3而言,一個DataBlock預設是128MB,所以一個文件可能需要N個DataBlock來存儲,那麼名字空間表很可能是一個文件名映射到一個DataBlock的數組。
  2. 關於這兩張表如何協作定位文件:
  • 當使用文件名訪問文件時,NameNode會查詢名字空間表,根據這個文件名獲取它所有內容對應的DataBlock列表(是不是很類似於單機磁碟的數據訪問)。此時inode表會查詢每一個DataBlock的信息,包括它所在的位置(DataNode的IP+埠)、DataBlock的ID和時間戳以及裡面數據的長度(<=128MB)等。
  • 這個DataBlock列表返回到客戶端,客戶端根據每個DataBlock上的信息(線索),分別連接到每個DataNode上,獲取上面存儲的數據。
  1. 客戶端與NameNode、NameNode與DataNode的連接,全部都是通過ProtoBuf的RPC調用來實現的。關於ProtoBuf可以參考這裡。例如,下麵就是追加文件的append請求的RPC協議:
//摘自hadoop-hdfs-project/hadoop-hdfs/src/main/proto/ClientNamenodeProtocol.proto

//RPC請求
rpc append(AppendRequestProto) returns(AppendResponseProto);

//請求報文
message AppendRequestProto {
  required string src = 1;
  required string clientName = 2;
  optional uint32 flag = 3; // bits set using CreateFlag
}

//應答報文
message AppendResponseProto {
  optional LocatedBlockProto block = 1;
  optional HdfsFileStatusProto stat = 2;
}

HDFS寫文件Pipeline機制

HDFS在對文件的寫入方面,只允許數據追加到文件末尾,而不允許在文件中間修改文件。因為在文件中間修改文件,需要涉及文件鎖、數據塊之類的比較複雜的邏輯。

Hadoop的文件按照DataBlock分塊,並以DataBlock為單位做冗餘(負載均衡)。HDFS可以指定一個複製因數(replication),預設是保存3份,根據dfs.replication配置項配置。

下麵分析HDFS寫文件的Pipeline流程(藍色線表示用於通訊,紅色線表示數據的傳輸路線):

hadoop pipeline流程圖

  • ①客戶端發送請求到NameNode,請求寫文件/新建數據塊。
  • NameNode收到請求後,會給客戶端分配一個數據塊,其ID是blk_123456,並指明DataBlock各個拷貝所在的各個DataNode的IP和埠(圖中是分別存在於三個DataNode中)。
  • 這一系列的DataNode稱為Pipeline,也就是數據傳輸的管道,也就是【DataNode_1:50010, DataNode_2:50010, DataNode_3:50010】。
  • ②客戶端收到數據塊的信息,開始對DataNode發起寫的請求,請求報文包括要寫的數據塊,要寫的數據大小等等。請求成功後,發送數據到第一個DataNode,也就是圖中的DataNode_1,在該請求中包含DataBlock各個拷貝的地址(包含DataNode2和DataNode3的地址):【DataNode_1:50010, DataNode_2:50010, DataNode_3:50010】,發送完成之後等待DataNode_1返回的ACK報文。
  • ③DataNode_1收到數據後,保存數據,並把數據發送到DataNode_2,Pipeline修改為【DataNode_2:50010, DataNode_3:50010】,發送完成之後等待DataNode_2返回的ACK報文。
  • ④DataNode_2收到數據後,把數據發送到DataNode_3,Pipeline修改為【DataNode_3:50010】,發送完成之後等待DataNode_2返回的ACK報文。
  • ⑤DataNode_3發現Pipeline中只有自己,不再有下游的DataNode節點,於是處理完成之後只需要返回ACK到Pipeline的上游節點,即DataNode_2。
  • ⑥DataNode_2收到DataNode_3的ACK,於是把ACK發送到Pipeline的上游節點,即DataNode_1。
  • ⑦DataNode_1收到DataNode_2的ACK,把ACK發送到Pipeline的上游節點,即客戶端。

數據發送至此完成。

HDFS文件推送客戶端

要把本地文件推送到HDFS,可以通過以下兩個命令實現:

hadoop fs -appendToFile <localsrc> ... <dst>
hadoop fs -put [-f] [-p] [-l] <localsrc> ... <dst>

跟蹤調用堆棧發現,這兩個命令最終是調用DFSOutputStream.java中的代碼實現文件的拷貝。

輔助發送的相關類和數據結構

這份代碼裡面包含了一些用於輔助發送的類:

  • DFSOutputStream:實現了發送數據的主流程,最主要是繼承自FSOutputSummer這個虛擬類的介面方法writeChunk
  • DataStreamer:繼承自Daemon的後臺線程,主要實現數據的流式發送。
  • ResponseProcessor:同樣繼承自Daemon的後臺線程,主要實現對已發送數據包的ACK報文的接收。

還有一些保存發送數據相關信息的數據結構:

  • DFSPacket:表示發送出去的一個數據包,包含相應的請求頭部以及相關標誌位。
  • LinkedList<DFSPacket> dataQueue:用於保存待發送的數據包。它是主線程*DFSOutputStream和發送線程DataStreamer之間生產者-消費者關係的共用數據結構。
  • LinkedList<DFSPacket> ackQueue:用於保存已經發送的數據包。發出去的數據包還要等待DataNode返回ACK才可以被認為是發送成功。它是發送線程DataStreamer與ACK接收線程ResponseProcessor之間生產者-消費者關係的共用數據結構。
  • BlockConstructionStage stage:這是一個狀態變數,整個發送流程就相當於一個狀態機。

看完上面的數據結構,整個數據發送流程就很明顯了:
DFSOutputStream把數據組裝成DFSPacket對象,放入dataQueue;然後等待發送線程DataStreamer發送到DataNode;DataStreamer發送之後,把DFSPacket對象移動到ackQueue,等待ACK線程ResponseProcessor在收到對應的ACK之後把該DFSPacket從隊列移除。

下麵主要分析DFSOutputStream.java這個客戶端代碼的執行流程。

#### 數據發送的主要流程

  • newStreamForCreate/newStreamForAppend這兩個靜態函數用於創建DFSOutputStream對象。一個是用於新建文件,一個用於追加到現有的文件。兩個函數主要差別在於,前者需要新建一個文件(發送create的RPC請求到NameNode),後者直接通過發送append的RPC請求到NameNode,在返回報文中獲取文件最後的一個數據塊並開始寫入。
  • newStreamForCreate/newStreamForAppend這兩個函數返回一個DFSOutputStream的對象,然後被org.apache.hadoop.io.IOUtils.copyBytes()調用DFSOutputStreamwriteChunk介面函數,把本地的數據塊發送出去。下麵主要看writeChunk函數。這個函數的參數主要包括數據的緩衝區、要發送的數據在DataBlock中的offset、還有數據的校驗等。

HDFS客戶端數據發送流程.png


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 最近在瀏覽亞馬遜, 京東的時候, 發現會自動彈出很多廣告到瀏覽器, 其實是中了病毒MacOSDefender. 這個病毒非常煩人, 會在你瀏覽電商網頁的時候拼命的打開廣告頁面, 而且還會彈出一些提示, 騙你授權safari和chrome給MacOSDefender. 清除的方法也比較簡單, 不需要裝 ...
  • 在命令狀態下對當前行用== (連按=兩次), 或對多行用n==(n是自然數)表示自動縮進從當前行起的下麵n行。你可以試試把代碼縮進任意打亂再用n==排版,相當於一般IDE里的code format。使用gg=G可對整篇代碼進行排版。 vim 選擇文本,刪除,複製,粘貼 文本的選擇,對於編輯器來說,是 ...
  • VMware與CentOS系統安裝 1, 下載CentOS系統ISO鏡像: 國內鏡像源 2, 安裝VMware虛擬機 虛擬機能讓用戶在一臺機器上模擬出多個操作系統的軟體,一般的機器配置能夠勝任虛擬機的任務. 虛擬機不但可以虛擬出硬體資源,把實驗環境與真機文件分離保證數據安全,還能在刪掉系統核心配置時 ...
  • 1 進入安裝界面 2 選擇語言 3 選擇鍵盤 4 選擇存儲類型 5 是否格式化硬碟 6 設置主機名 7 配置網卡 (1)選擇網卡並編輯 (2)配置IPv4 (3)查看虛擬網路編輯器 NAT設置 DHCP設置 (4) 修改IPv4設置 8 選擇時區 9 設置密碼 (自己設定) 可能提示密碼簡單 10 ...
  • 下麵就來看看怎麼安裝centos7,首先就是要準備一個虛擬機了 簡稱VM,當然虛擬機的安裝步驟,我也不再多說,我用的Workstation 15 Pro的版本,我們直接打開虛擬機,打開界面如下: 在安裝過程中,沒必要非和我做的完全一樣,要根據自己的需求,設置適合你自己的參數設置 我們點擊,創建新的虛 ...
  • 本文詳細介紹nvidia-smi命令系列詳解;nvidia-smi簡稱NVSMI,提供監控GPU使用情況和更改GPU狀態的功能,是一個跨平臺工具,它支持所有標準的NVIDIA驅動程式 ...
  • 查看網卡信息: ifconfig 出現不正常的顯示原因主要有兩方面: >>>具體操作<<< 【修改虛擬機網卡信息】 【虛擬機網卡信息概要】 【虛擬機網卡信息說明】 【補充】 【網卡配置】 【網卡重啟】 【主機名配置】 【主機名配置文件內容】 ...
  • 關於kafka的性能方面的一些總結,內容大部分來自網上,加上一些自己的經驗(加粗),主要是為了方便自己查閱 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...