HDFS原理介紹


  HDFS(Hadoop Distributed File System )Hadoop分布式文件系統。是根據google發表的論文翻版的。論文為GFS(Google File System)Google 文件系統(中文英文)。

1. 架構分析

  基礎名詞解釋:

  • Block: 在HDFS中,每個文件都是采用的分塊的方式存儲,每個block放在不同的datanode上,每個block的標識是一個三元組(block id, numBytes,generationStamp),其中block id是具有唯一性,具體分配是由namenode節點設置,然后再由datanode上建立block文件,同時建立對應block meta文件
  • Packet:在DFSclient與DataNode之間通信的過程中,發送和接受數據過程都是以一個packet為基礎的方式進行
  • Chunk:中文名字也可以稱為塊,但是為了與block區分,還是稱之為chunk。在DFSClient與DataNode之間通信的過程中,由於文件采用的是基於塊的方式來進行的,但是在發送數據的過程中是以packet的方式來進行的,每個packet包含了多個chunk,同時對於每個chunk進行checksum計算,生成checksum bytes
  • 小結:

    1. 一個文件被拆成多個block持續化存儲(block size 由配置文件參數決定)   思考: 修改 block size 對以前持續化的數據有何影響?

    2. 數據通訊過程中一個 block 被拆成 多個 packet

    3. 一個 packet 包含多個 chunk

  • Packet結構與定義: Packet分為兩類,一類是實際數據包,另一類是heatbeat包。一個Packet數據包的組成結構,如圖所示

  上圖中,一個Packet是由Header和Data兩部分組成,其中Header部分包含了一個Packet的概要屬性信息,如下表所示:

  Data部分是一個Packet的實際數據部分,主要包括一個4字節校驗和(Checksum)與一個Chunk部分,Chunk部分最大為512字節  

  在構建一個Packet的過程中,首先將字節流數據寫入一個buffer緩沖區中,也就是從偏移量為25的位置(checksumStart)開始寫Packet數據Chunk的Checksum部分,從偏移量為533的位置(dataStart)開始寫Packet數據的Chunk Data部分,直到一個Packet創建完成為止。

  當寫一個文件的最后一個Block的最后一個Packet時,如果一個Packet的大小未能達到最大長度,也就是上圖對應的緩沖區中,Checksum與Chunk Data之間還保留了一段未被寫過的緩沖區位置,在發送這個Packet之前,會檢查Chunksum與Chunk Data之間的緩沖區是否為空白緩沖區(gap),如果有則將Chunk Data部分向前移動,使得Chunk Data 1與Chunk Checksum N相鄰,然后才會被發送到DataNode節點

   hdfs架構

1、HDFS的組成:

  1. NameNode:Master節點(也稱元數據節點),是系統唯一的管理者。負責元數據的管理(名稱空間和數據塊映射信息);配置副本策略;處理客戶端請求
  2. DataNode:數據存儲節點(也稱Slave節點),存儲實際的數據;執行數據塊的讀寫;匯報存儲信息給NameNode
  3. Sencondary NameNode:分擔namenode的工作量;是NameNode的冷備份;合並fsimage和fsedits然后再發給namenode。注意:在hadoop 2.x 版本,當啟用 hdfs ha 時,將沒有這一角色
  4. client:系統使用者,調用HDFS API操作文件;與NameNode交互獲取文件元數據;與DataNode交互進行數據讀寫。注意:寫數據時文件切分由Client完成 

  熱備份b是a的熱備份,如果a壞掉。那么b立即運行代替a的工作

  冷備份b是a的冷備份,如果a壞掉。那么b不能立即代替a工作。但是b上存儲a的一些信息,減少a壞掉之后的損失

2、hdfs構架原則:

  1. 元數據與數據分離文件本身的屬性(即元數據)與文件所持有的數據分離
  2. 主/從架構一個HDFS集群是由一個NameNode和一定數目的DataNode組成
  3. 一次寫入多次讀取HDFS中的文件在任何時間只能有一個Writer。當文件被創建,接着寫入數據,最后,一旦文件被關閉,就不能再修改
  4. 移動計算比移動數據更划算數據運算,越靠近數據,執行運算的性能就越好,由於hdfs數據分布在不同機器上,要讓網絡的消耗最低,並提高系統的吞吐量,最佳方式是將運算的執行移到離它要處理的數據更近的地方,而不是移動數據

 

NameNode:

  • NameNode是整個文件系統的管理節點,也是HDFS中最復雜的一個實體,它維護着HDFS文件系統中最重要的兩個關系:
  1. HDFS文件系統中的文件目錄樹,以及文件的數據塊索引,即每個文件對應的數據塊列表
  2. 數據塊和數據節點的對應關系,即某一塊數據塊保存在哪些數據節點的信息
  • 第一個關系即目錄樹、元數據和數據塊的索引信息會持久化到物理存儲中,實現是保存在命名空間的鏡像fsimage和編輯日志edits中,注意:在fsimage中,並沒有記錄每一個block對應到哪幾個Datanodes的對應表信息
  • 第二個關系是在NameNode啟動后,每個Datanode對本地磁盤進行掃描,將本Datanode上保存的block信息匯報給Namenode,Namenode在接收到每個Datanode的塊信息匯報后,將接收到的塊信息,以及其所在的Datanode信息等保存在內存中。HDFS就是通過這種塊信息匯報的方式來完成 block -> Datanodes list的對應表構建
  • fsimage記錄了自最后一次檢查點之前HDFS文件系統中所有目錄和文件的序列化信息;
  • edits是元數據操作日志(記錄每次保存fsimage之后到下次保存之間的所有hdfs操作)
  • 在NameNode啟動時候,會先將fsimage中的文件系統元數據信息加載到內存,然后根據eidts中的記錄將內存中的元數據同步至最新狀態,將這個新版本的 FsImage 從內存中保存到本地磁盤上,然后刪除 舊的 Editlog,這個過程稱為一個檢查 點 (checkpoint)。 
  • 類似於數據庫中的檢查點,為了避免edits日志過大,在Hadoop1.X中,SecondaryNameNode會按照時間閾值(比如24小時)或者edits大小閾值(比如1G),周期性的將fsimage和edits的合並,然后將最新的fsimage推送給NameNode。而在Hadoop2.X中,這個動作是由Standby NameNode來完成.
  • 由此可看出,這兩個文件一旦損壞或丟失,將導致整個HDFS文件系統不可用。
  • 在hadoop1.X為了保證這兩種元數據文件的高可用性,一般的做法,將dfs.namenode.name.dir設置成以逗號分隔的多個目錄,這樣,多個目錄至少不要在一塊磁盤上,最好放在不同的機器上,比如:掛載一個共享文件系統
  • fsimage\edits 是序列化后的文件,想要查看或編輯里面的內容,可通過 hdfs 提供的 oiv\oev 命令,如下:
    • 命令: hdfs oiv (offline image viewer) 用於將fsimage文件的內容轉儲到指定文件中以便於閱讀,,如文本文件、XML文件,該命令需要以下參數:

        1. -i  (必填參數)  –inputFile <arg>  輸入FSImage文件

        2. -o (必填參數)  –outputFile <arg> 輸出轉換后的文件,如果存在,則會覆蓋

        3. -p (可選參數) –processor <arg>   將FSImage文件轉換成哪種格式: (Ls|XML|FileDistribution).默認為Ls

        示例:hdfs oiv -i /data1/hadoop/dfs/name/current/fsimage_0000000000019372521 -o /home/hadoop/fsimage.txt

  • 命令:hdfs oev (offline edits viewer 離線edits查看器)的縮寫, 該工具只操作文件因而並不需要hadoop集群處於運行狀態。

    示例:  hdfs oev -i edits_0000000000000042778-0000000000000042779 -o edits.xml

    支持的輸出格式有binary(hadoop使用的二進制格式)、xml(在不使用參數p時的默認輸出格式)和stats(輸出edits文件的統計信息)

  • 小結:
  1. NameNode管理着DataNode,接收DataNode的注冊、心跳、數據塊提交等信息的上報,並且在心跳中發送數據塊復制、刪除、恢復等指令;同時,NameNode還為客戶端對文件系統目錄樹的操作和對文件數據讀寫、對HDFS系統進行管理提供支持
  2. Namenode 啟動后會進入一個稱為安全模式的特殊狀態。處於安全模式的 Namenode 是不會進行數據塊的復制的。Namenode 從所有的 Datanode 接收心跳信號和塊狀態報告。塊狀態報告包括了某個 Datanode 所有的數據塊列表。每個數據塊都有一個指定的最小副本數。當Namenode檢測確認某 個數據塊的副本數目達到這個最小值,那么該數據塊就會被認為是副本安全 (safely replicated) 的;在一定百分比(這個參數可配置)的數據塊被 Namenode 檢測確認是安全之后(加上一個額外的 30 秒等待時間), Namenode 將退出安全模式狀態。接下來它會確定還有哪些數據塊的副本沒有達到指定數目,並將這些數據塊復制到其他 Datanode 上。

 

Secondary NameNode:在HA cluster中又稱為standby node

Secondary NameNode 定期合並 fsimage 和 edits 日志,將 edits 日志文件大小控制在一個限度下,其過程如下:

  • namenode 響應 Secondary namenode 請求,將 edit log 推送給 Secondary namenode , 開始重新寫一個新的 edit log
  • Secondary namenode 收到來自 namenode 的 fsimage 文件和 edit log
  • Secondary namenode 將 fsimage 加載到內存,應用 edit log , 並生成一 個新的 fsimage 文件
  • Secondary namenode 將新的 fsimage 推送給 Namenode
  • Namenode 用新的 fsimage 取代舊的 fsimage , 在 fstime 文件中記下檢查點發生的時

 

工作原理

 寫操作:

有一個文件FileA,100M大小。Client將FileA寫入到HDFS上。HDFS按默認配置(塊大小為64M)。HDFS分布在三個機架上Rack1,Rack2,Rack3。

a. Client將FileA按64M分塊。分成兩塊,block1和Block2;

b. Client向nameNode發送寫數據請求,如圖藍色虛線①------>。

c. NameNode節點,記錄block信息。並返回可用的DataNode,如粉色虛線②--------->。

    Block1: host2,host1,host3

    Block2: host7,host8,host4

  原理:

      NameNode具有RackAware機架感知功能(這個可以配置)。

      若client為DataNode節點,那存儲block時,規則為:副本1,同client的節點上;副本2,不同機架節點上;副本3,同第二個副本機架的另一個節點上;其他副本隨機挑選。

      若client不為DataNode節點,那存儲block時,規則為:副本1,隨機選擇一個節點上;副本2,不同副本1,機架上;副本3,同副本2相同的另一個節點上;其他副本隨機挑選。

  client向DataNode發送block1;發送過程是以流式寫入。流式寫入過程:

     將64M的block1按64k的package划分;

             然后將第一個package發送給host2;

             host2接收完后,將第一個package發送給host1,同時client向host2發送第二個package;

             host1接收完第一個package后,發送給host3,同時接收host2發來的第二個package。

             以此類推,如圖紅線實線所示,直到將block1發送完畢。

             host2,host1,host3向NameNode,host2向Client發送通知,說“消息發送完了”。如圖粉紅顏色實線所示。

             client收到host2發來的消息后,向namenode發送消息,說我寫完了。這樣就真完成了。如圖黃色粗實線

             發送完block1后,再向host7,host8,host4發送block2,如圖藍色實線所示。

             發送完block2后,host7,host8,host4向NameNode,host7向Client發送通知,如圖淺綠色實線所示。

             client向NameNode發送消息,說我寫完了,如圖黃色粗實線。。。這樣就完畢了。

   分析通過寫過程,我們可以了解到:

                寫1T文件,我們需要3T的存儲(有3個副本),3T的網絡流量貸款。

                在執行讀或寫的過程中,NameNode和DataNode通過HeartBeat進行保存通信,確定DataNode活着。如果發現DataNode死掉了,就將死掉的DataNode上的數據,放到其他節點去。讀取時,要讀其他節點去。

                掛掉一個節點,沒關系,還有其他節點可以備份;甚至,掛掉某一個機架,也沒關系;其他機架上,也有備份。

 

說明: 

  1. 當客戶端向 HDFS 文件寫入數據的時候,一開始是寫到本地臨時文件中。假設該文件的副本系數設置為 3 ,當本地臨時文件累積到一個數據塊的大小時,客戶端會從 Namenode 獲取一個 Datanode 列表用於存放副本。然后客戶端開始向第一個 Datanode 傳輸數據,第一個 Datanode 一小部分一小部分 (4 KB) 地接收數據,將每一部分寫入本地倉庫,並同時傳輸該部分到列表中 第二個 Datanode 節點。第二個 Datanode 也是這樣,一小部分一小部分地接收數據,寫入本地 倉庫,並同時傳給第三個 Datanode 。最后,第三個 Datanode 接收數據並存儲在本地。因此, Datanode 能流水線式地從前一個節點接收數據,並在同時轉發給下一個節點,數據以流水線的 方式從前一個 Datanode 復制到下一個
  2. 時序圖如下:

 

讀操作: 

  讀操作流程為

  • 客戶端通過調用FileSystem對象的open()方法來打開希望讀取的文件,對於HDFS來說,這個對象是分布文件系統的一個實例;
  • DistributedFileSystem通過使用RPC來調用NameNode以確定文件起始塊的位置,同一Block按照重復數會返回多個位置,這些位置按照Hadoop集群拓撲結構排序,距離客戶端近的排在前面 
  • 前兩步會返回一個FSDataInputStream對象,該對象會被封裝成DFSInputStream對象,DFSInputStream可以方便的管理datanode和namenode數據流,客戶端對這個輸入流調用read()方法
  • 存儲着文件起始塊的DataNode地址的DFSInputStream隨即連接距離最近的DataNode,通過對數據流反復調用read()方法,將數據從DataNode傳輸到客戶端
  • 到達塊的末端時,DFSInputStream會關閉與該DataNode的連接,然后尋找下一個塊的最佳DataNode,這些操作對客戶端來說是透明的,客戶端的角度看來只是讀一個持續不斷的流
  • 一旦客戶端完成讀取,就對FSDataInputStream調用close()方法關閉文件讀取

block持續化結構:

  DataNode節點上一個Block持久化到磁盤上的物理存儲結構,如下圖所示:

  每個Block文件(如上圖中blk_1084013198文件)都對應一個meta文件(如上圖中blk_1084013198_10273532.meta文件),Block文件是一個一個Chunk的二進制數據(每個Chunk的大小是512字節),而meta文件是與每一個Chunk對應的Checksum數據,是序列化形式存儲

 

 參考:

HDFS 原理、架構與特性介紹--轉載 -  

hadoop(一):深度剖析hdfs原理  

【Hadoop】HDFS的運行原理  

還不懂HDFS的工作原理?快來掃掃盲    

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM