分佈式文件系統:HDFS 核心原理

目錄node

基礎架構算法

HDFS Client緩存

NameNode和DataNode安全

fsimage和editsbash

SecondaryNameNode服務器

高可用架構網絡

JournalNode架構

聯邦機制分佈式

副本機制工具

機架感知

安全模式

平衡策略

讀寫原理

讀原理

寫原理

刪除恢復機制


HDFS相關內容:

  1. HDFS超有用的知識點
  2. Hadoop3新特性之HDFS糾刪碼
  3. HDFS經常使用管理命令
  4. HDFS的副本數量配置
  5. HDFS查看namenode狀態
  6. 統計HDFS目錄下文件行數及文件大小

基礎架構

HDFS(Hadoop Distributed File System)是 Apache Hadoop 項目的一個子項目,Hadoop 很是適於存儲大型數據, 其就是使用 HDFS 做爲存儲系統,而HDFS 使用多臺計算機存儲文件,而且提供統一的訪問接口,像是訪問一個普通文件系統同樣使用分佈式文件系統。做爲大數據生態最重要的組件之一,HDFS充當着大數據時代的數據管理者的角色,爲各類分佈式計算組件提供用於處理的數據存儲的能力。

HDFS 基礎架構由四個角色組成:HDFS Client、NameNode、DataNode 和 SecondaryNameNode

HDFS Client

HDFS客戶端提交讀寫命令到HDFS,它負責:

  • 文件切分文件上傳 HDFS的時候,Client 將文件切分紅一個個Block(數據塊),而後進行存儲。
  • 與 NameNode 交互獲取文件真實的位置信息。
  • 與 DataNode 交互讀取或寫入數據。
  • Client 提供一些命令來管理 和訪問HDFS,好比啓動或者關閉HDFS。

NameNode和DataNode

NameNode 是HDFS的Master節點,它負責:

  • 管理 HDFS 的名稱空間;
  • 管理數據塊(Block)映射信息;
  • 配置副本策略;
  • 處理客戶端讀寫請求;
  • 週期性的接收心跳和塊的狀態信息報告;

 DataNode 是HDFS的Slave節點,它負責:

  • 存儲實際的數據塊;
  • 執行數據塊的讀/寫操做; 
  • 週期性向NameNode彙報心跳信息;
  • 週期性向NameNode彙報數據塊信息;
  • 週期性向NameNode彙報緩存數據塊信息;

fsimage和edits

在Hadoop集羣當中,NameNode的全部元數據信息都保存在fsimage 與 edits 文件中, 這兩個文件記錄了全部的數據的元數據信息,當集羣重啓時NameNode首先會從fsimage和edits文件中將元數據信息加載到內存中,所以NameNode機器對內存的要求相對會比DataNode高不少,元數據信息的保存目錄配置在了 hdfs-site.xml 中的這兩個參數:dfs.namenode.name.dir,dfs.namenode.edits.dir。

edits

  • 存放了客戶端最近一段時間的操做日誌;
  • 客戶端對 HDFS 進行寫文件時的操做會先被記錄在 edits 文件中;
  • edits 修改時元數據也會更新;

fsimage

  • NameNode 中關於元數據的鏡像,通常稱爲檢查點,fsimage 存放了一份比較完整的元數據信息;
  • 由於 fsimage 是 NameNode 的完整的鏡像, 若是每次都加載到內存生成樹狀拓撲結構,這是很是耗內存和CPU, 因此通常開始時對NameNode 的操做都放在 edits 中;
  • fsimage 內包含了 NameNode 管理下的全部 DataNode 文件和文件 block 以及 block所在的 DataNode 的元數據信息;
  • 隨着 edits 內容增大,就須要在必定策略下和 fsimage 合併;

因爲集羣重啓時NameNode會從新加載fsimage和edits文件,fsimage文件加載起來很快,但edits文件內記錄的都是操做日誌,所以edits文件不能無限增加,不然重放日誌很慢,會影響到集羣啓動的速度,所以edits文件和fsimage會按期進行合併。

SecondaryNameNode

SecondaryNameNode不是NameNode 的熱備。當NameNode 掛掉的時候,它並不能立刻替換 NameNode 並提供服務,而是做爲一個輔助者分擔NameNode的工做量。在後面的內容中介紹的HDFS的高可用中會介紹真正的NameNode熱備機制。

  • 按期合併 fsimage和edits,並推送給NameNode,把 edits 控制在一個範圍內。
  • 在緊急狀況下,可輔助恢復 NameNode。

上面提到edits文件會根據必定策略和fsimage合併,主要由core-site.xml文件中的兩個參數來管理:

<!-- 多久記錄一次 HDFS 鏡像, 默認 1小時 -->
<property>
  <name>fs.checkpoint.period</name>
  <value>3600</value>
</property>
<!-- 一次記錄多大, 默認 64M -->
<property>
  <name>fs.checkpoint.size</name>
  <value>67108864</value>
</property>

當edits和fsimage文件合併策略觸發時,合併流程以下:

  1. SNN(SecondaryNameNode)通知NN(NameNode)暫時切換將日誌寫到edits.new內;
  2. SNN經過GET請求將NN中的edits和fsimage文件加載到內存中;
  3. SNN將內存中的edits和fsimage合併生成新的fsimage.ckpt文件;
  4. SNN經過POST請求將生成的fsimage.ckpt文件傳給NN;
  5. NN將收到的fsimage.ckpt替換舊的fsimage文件;
  6. NN將edits.new替換舊的edits文件;

高可用架構

JournalNode

上面咱們介紹的都是HDFS的基礎架構,從上面的內容中咱們也能夠看出,NameNode對於HDFS很重要,整個HDFS文件系統的元數據信息都由NameNode來管理,NameNode的可用性直接決定了Hadoop 的可用性,一旦NameNode進程不能工做了,就會影響整個集羣的正常使用。所以在Hadoop2.x版本中加入了HDFS HA的特性,在典型的HA集羣中,兩臺獨立的機器被配置爲NameNode。在工做集羣中,NameNode機器中的一個處於Active狀態,另外一個處於Standby狀態。Active NameNode負責羣集中的全部客戶端 操做,而Standby充當從服務器,Standby機器保持足夠的狀態以提供快速故障切換。

兩個NameNode爲了數據同步,會經過一組稱做JournalNodes的獨立進程進行相互通訊。當Active 狀態的NameNode的命名空間有任何修改時,會告知大部分的JournalNodes進程。Standby 狀態的NameNode有能力讀取JNs中的變動信息,而且一直監控edit log的變化,把變化應用於本身的命名空間。Standby 能夠確保在集羣出錯時,命名空間狀態已經徹底同步了 ,以此達到快速故障切換。

HA架構下,SecondaryNameNode被JournalNode替代,實現兩個NameNode之間的信息同步,由Zookeeper實現兩個NameNode之間的高可用,相關的組件以下:

  • ZKFailoverController是基於Zookeeper的故障轉移控制器,它負責控制NameNode的主備切換,ZKFailoverController會監測NameNode的健康狀態,當發現Active NameNode出現異常時會經過Zookeeper進行一次新的選舉,完成Active和Standby狀態的切換;
  • HealthMonitor週期性調用NameNode的HAServiceProtocol RPC接口(monitorHealth 和 getServiceStatus),監控NameNode的健康狀態並向ZKFailoverController反饋;
  • ActiveStandbyElector接收ZKFC的選舉請求,經過Zookeeper自動完成主備選舉,選舉完成後回調ZKFailoverController的主備切換方法對NameNode進行Active和Standby狀態的切換;
  • DataNodeNameNode包含了HDFS的元數據信息和數據塊信息(blockmap),爲了確保快速切換,Standby 狀態的NameNode有必要知道集羣中全部數據塊的位置。爲了作到這點,全部的DataNode必須配置兩個NameNode的地址,同時發送數據塊位置信息和心跳給他們兩個。 
  • 共享存儲系統(JournalNode)共享存儲系統負責存儲HDFS的元數據(EditsLog),Active NameNode(寫入)和 Standby NameNode(讀取)經過共享存儲系統實現元數據同步,在主備切換過程當中,新的Active NameNode必須確保元數據同步完成才能對外提供服務;對於HA集羣而言,確保同一時刻只有一個NameNode處於active狀態是相當重要的。不然,兩個NameNode的數據狀態就會產生分歧,可能丟失數據,或者產生錯誤的結果。爲了保證這點,JNs必須確保同一時刻只有一個NameNode能夠向本身寫數據。

Hadoop3.x版本中的新特性容許2個以上的NameNode節點,該功能可以經過運行更多Standby NameNode來提供更高的容錯性,知足一些部署的需求。好比,經過配置3個NameNode和5個JournalNode,集羣可以知足容許兩個節點故障的容錯。

聯邦機制

雖然HA模式保證了NameNode的高可用,但HDFS中其實最嚴重的問題就是小文件過多致使的NameNode維護的元數據信息過多,由此引發的性能降低的問題,所以不管在MapReduce仍是Spark程序中都應當儘可能避免產生過多小文件。同時HDFS也推出了NameNode的水平擴展方案:聯邦機制(Federation)

HDFS聯邦機制表示有多個NameNode,但和HA模式下的多個NameNode的意思不一樣,在HA模式下的NameNode是主備的概念,而聯邦機制中的多NameNode相似分管,表示某個NameNode管理某塊命名空間(namespace)內的元數據信息,將原本大量的元數據信息分散在多個NameNode上進行管理,它們之間相互獨立不須要互相協助,各自分工,管理本身的區域。

 

同一個namespace下的block集合被稱爲Block Pool(存儲池),所以在聯邦機制下,每一個NameNode對應一個Block Pool,對應到DataNode中就是一個個的Block Pool,分別有對應的ID,這時候在DataNode上就不只僅存儲一個Block Pool下的數據了,而是多個,且存儲在DataNode的datadir路徑裏的名爲BP-xx.xx的目錄。

聯邦機制的好處是,多個NameNode共有一個集羣裏的存儲資源,且每一個NameNode均可以單獨對外提供服務,解決了單個Active NameNode的內存瓶頸問題。但聯邦仍是沒有解決單點故障的問題,假如維護namespace爲BP-003的NameNode宕機,則客戶端也沒法讀取DataNode中的/BP-003的數據,所以當集羣規模較大的時候,應採用HA+Federation的部署方案,即上圖中每一個Active NameNode都對應了一個Standby NameNode提高可用性。

副本機制

HDFS中的文件以Block塊的形式存儲在HDFS文件系統中,目的爲:

  • 一個文件有可能大於集羣中任意一個磁盤,引入塊機制,能夠很好的解決這個問題;
  • 使用塊做爲文件存儲的邏輯單位能夠簡化存儲子系統;
  • 塊很是適合用於數據備份,提供數據容錯能力;

在 Hadoop1.x 當中, 文件的 block 塊默認大小是 64M,在Hadoop2.x中, 文件的 block 塊大小默認是128M, block 塊的大小和副本數量能夠經過 hdfs-site.xml 當中的配置文件進行指定:

<!-- 塊大小,單位爲字節 -->
<property>
    <name>dfs.block.size</name>
    <value>134217728</value>
</property>

<!-- 副本數量,默認3個副本 -->
<property>
    <name>dfs.replication</name>
    <value>3</value>
</property>

注意

  • 當文件大於配置的塊大小時會被拆分,如130M的文件會被拆分爲兩個塊,一個128M另外一個2M。
  • 當文件小於配置的塊大小時不會拆分,如100M的文件不會拆分,只有一個100M的塊。 

機架感知

分佈式的集羣一般包含很是多的機器,因爲受到機架槽位和交換機網口的限制,一般大型的分佈式集羣都會跨好幾個機架,由多個機架上的機器共同組成一個分佈式集羣。機架內的機器之間的網絡速度一般都會高於跨機架機器之間的網絡速度,而且機架之間機器的網絡通訊一般受到上層交換機間網絡帶寬的限制。

Hadoop在設計時考慮到數據的安全與高效,數據文件默認在HDFS上存放三份,存儲策略爲:

  1. 第一個block副本放在客戶端所在的數據節點裏(若是客戶端不在集羣範圍內,則從整個集羣中隨機選擇一個合適的數據節點來存放);
  2. 第二個副本放置在與第一個副本所在節點不一樣的機架內的數據節點上(隨機選擇);
  3. 第三個副本放置在不一樣機架的節點上;
  4. 若是還有其餘副本,則隨機放在其餘節點上;

這樣設計的好處是:

  • 當本地數據損壞時,節點能夠從同一機架內的相鄰節點拿到數據,速度確定比從跨機架節點上拿數據要快;
  • 當整個機架的網絡出現異常,也能保證在其它機架的節點上找到數據;

爲了下降總體的帶寬消耗和讀取延時,HDFS會盡可能讓程序讀取離它最近的節點上的副本,以節約帶寬和提高性能。HDFS經過機架感知這一特性實現此功能。

在默認狀況下,機架感知沒有被啓用,全部的機器hadoop都默認在同一個默認的機架下,名爲 「/default-rack」,這種狀況下,任何一臺datanode機器,無論物理上是否屬於同一個機架,都會被認爲是在同一個機架下,此時,就很容易出現增添機架間網絡負載的狀況。由於此時hadoop集羣的HDFS在選機器的時候,是隨機選擇的,也就是說,頗有可能因爲副本的隨機分配致使大量的網絡傳輸從而影響性能和集羣的服務。

經過修改配置文件core-site.xml 中的參數 topology.script.file.name 開啓機架感知,value指定爲一個可執行程序,一般爲一個腳本(根據入參IP返回該IP地址對應的datanode所在的rack)。

:網絡拓撲以下圖:

開啓機架感知後,NameNode就能夠畫出上圖所示的datanode網絡拓撲圖。D1,R1都是交換機,最底層是datanode。則H1的rackid=/D1/R1/H1,H1的parent是R1,R1的parent是D1。有了這些rackid信息就能夠計算出任意兩臺datanode之間的距離。

distance(/D1/R1/H1,/D1/R1/H1)=0  相同的datanode
distance(/D1/R1/H1,/D1/R1/H2)=2  同一rack下的不一樣datanode
distance(/D1/R1/H1,/D1/R1/H4)=4  同一IDC下的不一樣datanode
distance(/D1/R1/H1,/D2/R3/H7)=6  不一樣IDC下的datanode

安全模式

安全模式是hadoop的一種保護機制,用於保證集羣中的數據塊的安全性。當集羣啓動的時候,會首先進入安全模式,當系統處於安全模式時會檢查數據塊的完整性。

假設咱們設置的副本數(即參數dfs.replication)是5,那麼在datanode上就應該有5個副本存在,假設只存在3個副本,那麼比例就是3/5=0.6。在配置文件hdfs-default.xml中定義了一個最小的副本的副本率0.999,咱們的副本率0.6明顯小於0.99,所以系統會自動的複製副本到其餘的dataNode,使得副本率不小於0.999.若是系統中有8個副本,超過咱們設定的5個副本,那麼系統也會刪除多餘的3個副本。

在安全模式下,系統會處於只讀狀態,NameNode不會處理任何數據塊的複製和刪除命令。DataNode會向NameNode上傳他們數據塊的列表,讓NameNode獲得數據塊的位置信息,並對每一個文件對應的數據塊副本進行統計:

  • 當最小副本條件知足時,即:必定比例的數據塊都到達最小副本數,系統會在30s後退出安全模式。
  • 當最小的副本條件未達到要求時,就會對副本數不足的數據塊安排DataNode進行復制,直到達到最小的副本數。

注意:在啓動一個剛剛格式化的HDFS時因爲沒有數據塊,因此係統不會進入安全模式。

HDFS安全模式操做命令:

hdfs dfsadmin  -safemode  get #查看安全模式狀態
hdfs dfsadmin  -safemode enter #進入安全模式
hdfs dfsadmin  -safemode leave #離開安全模式

安全模式相關參數在hdfs-site.xml 文件中配置:

<!-- 指定退出條件,須要達到最小副本數的數據塊比例,默認是 0.999 -->
<property>
    <name>dfs.namenode.safemode.threshold-pct</name>
    <value>0.999f</value>
</property>

<!-- 指定系統退出安全模式時須要的延遲時間,單位爲毫秒,默認爲 30s -->
<property>
    <name>dfs.namenode.safemode.extension</name>
    <value>30000</value>
</property>

若是 NameNode 長時間處於安全模式,多是由於 hdfs 的數據損壞過多。使用命令hadoop fsck / 檢查 hdfs 文件分佈的狀況。

平衡策略

在HDFS的DN節點間的數據不平衡狀況下,尤爲在新增和下架節點、或者人爲干預副本數量的時候,會大大的影響數據讀取的性能,下降任務的執行速度甚至崩潰,所以HDFS有一個組件叫作Balancer,使用該組件能夠保證每一個節點的數據均衡分佈

#開始數據平衡:
#用默認的10%的閾值啓動balancer
start-balancer.sh    
#或指定3%的閾值啓動balancer
hdfs dfs balancer -threshold 3
start-balancer.sh -threshold 3    

#中止數據平衡:
stop-balancer.sh

hdfs balancer
      [-threshold <threshold>]
      [-policy <policy>]
      [-exclude [-f <hosts-file> | <comma-separated list of hosts>]]
      [-include [-f <hosts-file> | <comma-separated list of hosts>]]
      [-idleiterations <idleiterations>]

-threshold  10      #集羣平衡的條件,datanode間磁盤使用率相差閾值,區間選擇:0~100。Threshold參數爲集羣是否處於均衡狀態設置了一個目標
-policy datanode    #默認爲datanode,datanode級別的平衡策略
-exclude  -f  /tmp/ip1.txt  #默認爲空,指定該部分ip不參與balance, -f:指定輸入爲文件
-include  -f  /tmp/ip2.txt  #默認爲空,只容許該部分ip參與balance,-f:指定輸入爲文件
-idleiterations  5          #最大迭代次數,默認爲 5

可選的配置參數以下:

#並行移動的block數量,默認5
dfs.datanode.balance.max.concurrent.moves

#Balance工具所佔用的帶寬,默認1048576(1MB)
dfs.datanode.balance.bandwidthPerSec

#用於執行block移動的線程池大小,默認1000
dfs.balancer.moverThreads

#每次balance進行迭代的過程最大移動數據量,默認10737418240(10GB)
dfs.balancer.max-size-to-move

#獲取block的數量,默認2147483648(2GB)
dfs.balancer.getBlocks.size

#用來平衡的最小block大小,默認10485760(10MB)
dfs.balancer.getBlocks.minblock-size

平衡算法根據各Datanode的使用狀況,將集羣中的節點分爲四類:過分閒置、平均值如下、平均值以上、過分使用

而後根據劃分的角色進行配對:

  • 過分使用--> 過分閒置
  • 過分使用-->平均值下
  • 平均值上-->過分閒置

爲了保證HDFS數據安全性,數據塊移動策略以下:

  1. 源DataNode的存儲類型和目的DataNode的存儲類型一致;
  2. 該block的副本未被安排;
  3. 目的DataNode不包含一樣的副本;
  4. 移動以後該機架上的block不會減小;

根據角色配對以及移動策略,Balancer數據均衡流程爲:

  1. 與NameNode交互,獲取DataNode磁盤使用狀況;
  2. 根據數據分佈狀況對DataNode進行角色劃分並配對;
  3. 根據移動策略從源DataNode移動block到目標DataNode,並刪除源DataNode上的block;
  4. 獲取移動結果,並繼續移動其餘數據塊,直到沒有數據能夠移動或者HDFS集羣以及達到了平衡的標準爲止,而後向NameNode提交更新後的DataNode信息;

當觸發下面的條件時,Balancer會自動退出:

  1. 集羣已達到均衡狀態;
  2. 沒有block能被移動;
  3. 連續5次(參數:idleiterations) 迭代移動沒有任何一個block被移動;
  4. 當與NameNode交互時出現了IOException;
  5. 另外一個Balancer進程在運行中。

讀寫原理

讀原理

客戶端向HDFS發送讀取文件的請求完整流程以下:

  1. 客戶端向NN提交讀請求;
  2. NN進行權限檢查、獲取文件塊列表:{blk_a_1: dn1,dn2,dn4 ;blk_a_2: dn2,dn3,dn4}
  3. NN根據機架感知將距離客戶端最近的文件塊所在的DN列表返回給客戶端:{blk_a_1:dn1, blk_a_2:dn2}
  4. 客戶端和每一個block所在的DN創建管道;
  5. 客戶端讀取數據,以數據包packet(64k)進行傳輸;
  6. 客戶端將接收到的block合併爲一個完整的文件;

NameNode會視狀況返回文件的部分或者所有block列表,對於每一個block,NameNode 都會返回含有該 block 副本的 DataNode 地址; 這些返回的 DN 地址,會按照集羣拓撲結構得出 DataNode 與客戶端的距離,而後進行排序,排序兩個規則:網絡拓撲結構內距離Client 近的排靠前;心跳機制中超時彙報的 DN 狀態爲 STALE,這樣的排靠後;以此來提高網絡傳輸的效率。

客戶端選取排序靠前的 DataNode 來讀取 block,若是客戶端自己就是DataNode,那麼將從本地直接獲取數據(短路讀取)。

每讀取完一個 block 都會進行 checksum 驗證,若是讀取 DataNode 時出現錯誤,客戶端會通知 NameNode,而後再從下一個擁有該block 副本的DataNode 繼續讀。

寫原理

客戶端向HDFS發送上傳文件的請求完整流程以下:

  1. 客戶端向NameNode提交寫請求;
  2. NN進行權限檢查、判斷是否知足寫條件;
  3. NN返回信息:能夠上傳;
  4. 客戶端根據HDFS的塊策略將文件切分爲n個block文件塊;
  5. 請求上傳第一個文件塊blk_a_1;
  6. 根據DN上的block信息和機架感知,選出能夠上傳的DN列表:(dn1,dn2,dn4);
  7. NN返回可上傳的DN列表(dn1,dn2,dn4);
  8. 客戶端和DN創建數據傳輸管道,上傳的DN之間也創建管道;
  9. 客戶端向DN以數據包packet(64k)傳遞數據,dn1收到一個packet會傳給dn2,dn2收到會傳給dn4,每傳一個packet會放入一個應答隊列等待應答;
  10. DN將收到的packet數據包進行緩存;
  11. 在管道的反方向上, DN逐個發送 ack(命令正確應答), 最終由管道中第一個DN節點dn1將ack發送給客戶端;
  12. 當文件塊block的packet傳輸完成則將緩存的臨時文件放置在指定的HDFS上傳路徑;
  13. 繼續上傳其他的block文件塊;

刪除恢復機制

當從HDFS中刪除某個文件時,這個文件並不會馬上從HDFS中刪除,而是將這個文件重命名並轉移到回收站 /trash目錄,只要這個文件還在/trash目錄下,該文件就能夠迅速被恢復。回收站的位置在HDFS上的/user/$USER/.Trash/Current/ 

文件在/trash目錄中存放的時間默認爲6個小時,當超過這個時間時,NN就會將文件從名稱空間中刪除;

刪除文件會使得該文件相關的數據塊被釋放;注意:從用戶刪除文件到HDFS空閒空間的增長之間會有必定時間的延遲;

經過修改hdfs-site.xml文件中下面的配置能夠修改回收站過時的時間:

#時間單位是秒
<property>
    <name>fs.trash.interval</name>
    <value>1440</value>
</property>

但願本文對你有幫助,請點個贊鼓勵一下做者吧~ 謝謝!

相關文章
相關標籤/搜索