元數據管理概述
HDFS元數據,按類型分,主要包括以下幾個部分:
1、文件、目錄自身的屬性信息,例如文件名,目錄名,修改信息等。
2、文件記錄的信息的存儲相關的信息,例如存儲塊信息,分塊情況,副本個數等。
3、記錄 HDFS 的 Datanode 的信息,用於 DataNode 的管理。
按形式分為內存元數據和元數據文件兩種,分別存在內存和磁盤上。
HDFS 磁盤上元數據文件分為兩類,用於持久化存儲:
fsimage 鏡像文件:是元數據的一個持久化的檢查點,包含 Hadoop 文件系統中的所有目錄和文件元數據信息,但不包含文件塊位置的信息。文件塊位置信息只存儲在內存中,是在 datanode 加入集群的時候,namenode 詢問 datanode 得到的,並且間斷的更新。
Edits 編輯日志:存放的是 Hadoop 文件系統的所有更改操作(文件創建,刪除或修改)的日志,文件系統客戶端執行的更改操作首先會被記錄到 edits 文件中。
fsimage 和 edits 文件都是經過序列化的,在 NameNode 啟動的時候,它會將 fsimage文件中的內容加載到內存中,之后再執行 edits 文件中的各項操作,使得內存中的元數據和實際的同步,存在內存中的元數據支持客戶端的讀操作,也是最完整的元數據。
當客戶端對 HDFS 中的文件進行新增或者修改操作,操作記錄首先被記入 edits 日志文件中,當客戶端操作成功后,相應的元數據會更新到內存元數據中。因為 fsimage 文件一般都很大(GB 級別的很常見),如果所有的更新操作都往 fsimage 文件中添加,這樣會導致系統運行的十分緩慢。
HDFS 這種設計實現着手於:一是內存中數據更新、查詢快,極大縮短了操作響應時間;二是內存中元數據丟失風險頗高(斷電等),因此輔佐元數據鏡像文件(fsimage)+編輯日志文件(edits)的備份機制進行確保元數據的安全。
NameNode 維護整個文件系統元數據。因此,元數據的准確管理,影響着 HDFS 提供文件存儲服務的能力。
元數據目錄相關文件
在 Hadoop 的 HDFS 首次部署好配置文件之后,並不能馬上啟動使用,而是先要對文件系統進行格式化。需要在 NameNode(NN)節點上進行如下的操作:
$HADOOP_HOME/bin/hdfs namenode –format
在這里要注意兩個概念,一個是文件系統,此時的文件系統在物理上還不存在;二就是此處的格式化並不是指傳統意義上的本地磁盤格式化,而是一些清除與准備工作。
格式化完成之后,將會在$dfs.namenode.name.dir/current 目錄下創建如下的文件結構,這個目錄也正是 namenode 元數據相關的文件目錄:
其中的 dfs.namenode.name.dir 是在 hdfs-site.xml 文件中配置的,默認值如下:
dfs.namenode.name.dir 屬性可以配置多個目錄,各個目錄存儲的文件結構和內容都完全一樣,相當於備份,這樣做的好處是當其中一個目錄損壞了,也不會影響到 Hadoop 的元數據,特別是當其中一個目錄是 NFS(網絡文件系統 Network File System,NFS)之上,即使你這台機器損壞了,元數據也得到保存。
下面對$dfs.namenode.name.dir/current/目錄下的文件進行解釋。
VERSION
namespaceID=934548976
clusterID=CID-cdff7d73-93cd-4783-9399-0a22e6dce196
cTime=0
storageType=NAME_NODE
blockpoolID=BP-893790215-192.168.24.72-1383809616115
layoutVersion=-47
namespaceID/clusterID/blockpoolID 這些都是 HDFS 集群的唯一標識符。標識符被用來防止 DataNodes 意外注冊到另一個集群中的 namenode 上。這些標識在聯邦(federation)部署中特別重要。聯邦模式下,會有多個 NameNode 獨立工作。每個的 NameNode 提供唯一的命名空間(namespaceID),並管理一組唯一的文件塊池(blockpoolID)。clusterID 將整個集群結合在一起作為單個邏輯單元,在集群中的所有節點上都是一樣的。
storageType 說明這個文件存儲的是什么進程的數據結構信息(如果是 DataNode,storageType=DATA_NODE);
cTime NameNode 存儲系統創建時間,首次格式化文件系統這個屬性是 0,當文件系統升級之后,該值會更新到升級之后的時間戳;
layoutVersion 表示 HDFS 永久性數據結構的版本信息,是一個負整數。
補充說明:
格式化集群的時候,可以指定集群的 cluster_id,但是不能與環境中其他集群有沖突。
如果沒有提供 cluster_id,則會自動生成一個唯一的 ClusterID。
$HADOOP_HOME/bin/hdfs namenode -format -clusterId <cluster_id>
seen_txid
$dfs.namenode.name.dir/current/seen_txid 非常重要,是存放 transactionId 的文件,format 之后是 0,它代表的是 namenode 里面的 edits_*文件的尾數,namenode 重啟的時候,會按照 seen_txid 的數字,循序從頭跑 edits_0000001~到 seen_txid 的數字。所以當你的 hdfs 發生異常重啟的時候,一定要比對 seen_txid 內的數字是不是你 edits 最后的尾數。
Fsimage & edits
$dfs.namenode.name.dir/current 目錄下在 format 的同時也會生成 fsimage 和 edits文件,及其對應的 md5 校驗文件。
secondary namenode
NameNode 職責是管理元數據信息,DataNode 的職責是負責數據具體存儲,那么SecondaryNameNode 的作用是什么?對很多初學者來說是非常迷惑的。它為什么會出現在HDFS 中。從它的名字上看,它給人的感覺就像是 NameNode 的備份。但它實際上卻不是。
大家猜想一下,當 HDFS 集群運行一段事件后,就會出現下面一些問題:
edit logs 文件會變的很大,怎么去管理這個文件是一個挑戰。
NameNode 重啟會花費很長時間,因為有很多改動要合並到 fsimage 文件上。
如果 NameNode 掛掉了,那就丟失了一些改動。因為此時的 fsimage 文件非常舊。
因此為了克服這個問題,我們需要一個易於管理的機制來幫助我們 減小 s edit logs 文件的大小和得到一個最新的fsimage 文件,這樣也會減小在 NameNode 上的壓力。這跟Windows 的恢復點是非常像的,Windows 的恢復點機制允許我們對 OS 進行快照,這樣當系統發生問題時,我們能夠回滾到最新的一次恢復點上。
SecondaryNameNode 就是來幫助解決上述問題的,它的職責是合並 NameNode 的 editlogs 到 fsimage 文件中。
Checkpoint
每達到觸發條件,會由 secondary namenode 將 namenode 上積累的所有 edits 和一個最新的 fsimage 下載到本地,並加載到內存進行 merge(這個過程稱為 checkpoint),如下圖所示:
Checkpoint 詳細步驟
- NameNode 管理着元數據信息,其中有兩類持久化元數據文件:edits 操作日志文件和fsimage 元數據鏡像文件。新的操作日志不會立即與 fsimage 進行合並,也不會刷到NameNode 的內存中,而是會先寫到 edits 中(因為合並需要消耗大量的資源),操作成功之后更新至內存。
- 有 dfs.namenode.checkpoint.period 和 dfs.namenode.checkpoint.txns 兩個配置,只要達到這兩個條件任何一個,secondarynamenode 就會執行 checkpoint 的操作。
- 當觸發 checkpoint 操作時,NameNode 會生成一個新的 edits 即上圖中的 edits.new 文件,同時 SecondaryNameNode 會將 edits 文件和 fsimage 復制到本地(HTTP GET 方式)。
- secondarynamenode 將下載下來的 fsimage 載入到內存,然后一條一條地執行 edits 文件中的各項更新操作,使得內存中的 fsimage 保存最新,這個過程就是edits 和fsimage文件合並,生成一個新的 fsimage 文件即上圖中的 Fsimage.ckpt 文件。
- secondarynamenode 將新生成的 Fsimage.ckpt 文件復制到 NameNode 節點。
- 在 NameNode 節點的 edits.new 文件和 Fsimage.ckpt 文件會替換掉原來的 edits 文件和 fsimage 文件,至此剛好是一個輪回,即在 NameNode 中又是 edits 和 fsimage 文件。
- 等待下一次 checkpoint 觸發 SecondaryNameNode 進行工作,一直這樣循環操作。
Checkpoint 觸發條件
Checkpoint 操作受兩個參數控制,可以通過 core-site.xml 進行配置:
<property> <name> dfs.namenode.checkpoint.period</name> <value>3600</value> <description> 兩次連續的 checkpoint 之間的時間間隔。默認 1 小時 </description> </property> <property> <name>dfs.namenode.checkpoint.txns</name> <value>1000000</value> <description> 最大的沒有執行 checkpoint 事務的數量,滿足將強制執行緊急 checkpoint,即使 尚未達到檢查點周期。默認設置為 100 萬。 </description> </property>
從上面的描述我們可以看出,SecondaryNamenode 根本就不是 Namenode 的一個熱備,其只是將 fsimage 和 edits 合並。其擁有的 fsimage 不是最新的,因為在他從 NameNode 下載 fsimage 和 edits 文件時候,新的更新操作已經寫到 edit.new 文件中去了。而這些更新在 SecondaryNamenode 是沒有同步到的!當然, 如果 NameNode 中的 fsimage 真的出問題了,還是可以用SecondaryNamenode 中的 fsimage 替換一下NameNode 上的 fsimage ,雖然已經不是最新的 fsimage ,但是我們可以將損失減小到最少!