NameNode管理文件系統(tǒng)的命名空間。它維護(hù)著文件系統(tǒng)樹及整棵樹內(nèi)所有的文件和目錄。這些信息以兩個文件形式永久保存在本地磁盤上:命名空間鏡像文件和編輯日志文件。NameNode也記錄著每個文件中各個塊所在的數(shù)據(jù)節(jié)點(diǎn)信息,但它并不永久保存塊的位置信息,因?yàn)檫@些信息在系統(tǒng)啟動時由數(shù)據(jù)節(jié)點(diǎn)重建。
節(jié)點(diǎn)介紹
hdfs集群有兩類節(jié)點(diǎn),并以管理者-工作者模式運(yùn)行,即一個NameNode(管理者)和多個DataNode(工作者)。一個HDFS cluster包含一個NameNode和若干的DataNode,NameNode(以下簡稱nn)是master,主要負(fù)責(zé)管理hdfs文件系統(tǒng),具體地包括namespace管理(其實(shí)就是目錄結(jié)構(gòu)),block管理(其中包括 filename->block,block->datanode list的對應(yīng)關(guān)系)。nn提供的是始終被動接收服務(wù)的server,主要有四類協(xié)議接口:ClientDatanodeProtocol接口、ClientProtocol接口、DatanodeProtocol接口、NamenodeProtocol接口。DataNode(以下簡稱dn)主要是用來存儲數(shù)據(jù)文件,hdfs將一個文件分割成一個個的block,這些block可能存儲在一個DataNode上或者是多個DataNode上。dn負(fù)責(zé)實(shí)際的底層的文件的讀寫,如果客戶端client程序發(fā)起了讀hdfs上的文件的命令,那么首先將這些文件分成block,然后nn將告知client這些block數(shù)據(jù)是存儲在哪些dn上的,之后,client將直接和dn交互。
還有一個重要的節(jié)點(diǎn):Secondary NameNode,該部分主要是定時對NameNode進(jìn)行數(shù)據(jù)snapshots進(jìn)行備份,這樣盡量降低NameNode崩潰之后,導(dǎo)致數(shù)據(jù)的丟失,其實(shí)所作的工作就是從nn獲得fsimage和edits把二者重新合并然后發(fā)給nn,這樣,既能減輕nn的負(fù)擔(dān)又能保險(xiǎn)地備份。
數(shù)據(jù)結(jié)構(gòu)
FSdirectory
FSDirectory存儲整個文件系統(tǒng)的目錄狀態(tài),對整個目錄結(jié)構(gòu)的管理通過調(diào)用FSImage和FSEditLog的方法從namenode本地磁盤讀取元數(shù)據(jù)信息和向本地磁盤寫入元數(shù)據(jù)信息,并登記對目錄結(jié)構(gòu)所作的修改到日志文件。另外,F(xiàn)SDirectory保存了文件名和數(shù)據(jù)塊的映射關(guān)系。INode是對文件系統(tǒng)目錄結(jié)構(gòu)中一個節(jié)點(diǎn)的抽象
INodeFile和INodeDirectory均繼承自INode類,分別表示文件節(jié)點(diǎn)和目錄節(jié)點(diǎn)。
INodeFile類中最重要的數(shù)據(jù)結(jié)構(gòu)是BlockInfo blocks[],它記錄了一個文件所包含的所有Block,成員方法的操作大都與Block相關(guān)
INodefileUnderConstruction表示正在都建的文件
INodeDirectory的關(guān)鍵數(shù)據(jù)結(jié)構(gòu)是List
INodeDirectoryWithQuota表示有配額限制的目錄,根目錄就是這種類型。
FSimage
把文件和目錄的元數(shù)據(jù)信息持久化地存儲到fsimage文件中,每次啟動時從中將元數(shù)據(jù)加載到內(nèi)存中構(gòu)建目錄結(jié)構(gòu)樹,之后的操作記錄在edits log中
定期將edits與fsimage合并刷到fsimage中
loadFSImage(File curFile)用于從fsimage中讀入Namenode持久化的信息。fsimage中保存的元數(shù)據(jù)信息格式如下,hdfs加載和寫入時都按照該格式進(jìn)行
fsimage是一個二進(jìn)制文件,當(dāng)中記錄了HDFS中所有文件和目錄的元數(shù)據(jù)信息,這是網(wǎng)上流傳的一張經(jīng)典圖。
imageVersion(int)——image版本號
namespaceID(int)——命名空間ID,在namenode的生命期內(nèi)保持不變,datanode注冊時
返回作為其registrationID,每次和namenode通信時都要檢查,不認(rèn)識的namespaceID拒絕連接.
numFiles(16版以后long型)記錄文件系統(tǒng)中的文件數(shù)
genstamp(long)生成image時間戳
下面是numFiles個文件(目錄)信息:
path(String)文件或目錄路徑
replication(int)副本數(shù),會調(diào)用FSEditLog.adjustReplication(replication);調(diào)整,目錄的為0
mtime(long)修改時間
atime(long)訪問時間
blockSize(long)塊大小,目錄是0
NumBlocks(int)文件包含的塊數(shù)(imageVersion 9以后的版本numBlocks>=0時表示文件,之前的版本>0時表示文件),目錄的為-1,saveINode2Image方法中可以看到
如果是文件,下面是NumBlocks個block的相關(guān)信息:
blockId(long):該文件的block的blockid,
numBytes(long):該block的大小
generationStamp(long):該block的時間戳
如果是目錄,讀入quota信息:
nsQuota(long)命名空間大小配額,默認(rèn)-1
dsQuota(long)磁盤空間配額,默認(rèn)-1
下面是權(quán)限相關(guān)
username(String)文件或目錄的所屬用戶名
groupname(String)組名
permission(short)權(quán)限
如果前面的path.length==0,表示根目錄,設(shè)置根目錄的配額,修改時間,訪問時間和權(quán)限信息。
將這些信息讀入內(nèi)存之后,構(gòu)造一個文件目錄結(jié)構(gòu)樹,將表示文件或目錄的節(jié)點(diǎn)填入到結(jié)構(gòu)中。
然后是加載datanode信息(新版已取消該項(xiàng))
再之后是加載FilesUnderConstruction.
BlocksMap
block->datanode的信息沒有持久化存儲,而是namenode通過datanode的blockreport獲取block->datanode list
BlocksMap負(fù)責(zé)維護(hù)了三種信息:
block->datanode list
block->INodeFile
datanode->blocks
這要?dú)w功于一個很牛逼的結(jié)構(gòu):Object[] triplets
他是一個三元組,每個block有幾個副本,就有幾個三元組。三元組的第一個元素表示該block所屬的Datanode,類型是DatanodeDescriptor,通過它獲得
block->datanode list
第二/三個元素表示該block所在Datanode上的前/后一個block(前驅(qū)和后繼),類型是BlockInfo,通過它獲得datanode->blocks
借助這個三元組可以找到一個block所屬的所有datanode,也可以通過三元組的后兩個元素信息找到一個datanode上所有的block。
上面這兩個結(jié)構(gòu)介紹之后,nn需要的namespace信息和block信息基本就全了。在nn加載fsimage完成之后,BlocksMap中只有每個block到其所屬的datanodes list的對應(yīng)關(guān)系信息還沒建立。然后通過dn的blockReport來收集構(gòu)建。當(dāng)所有的dn匯報(bào)給nn的blockReport處理完畢后,BlocksMap整個結(jié)構(gòu)也就構(gòu)建完成了。
參考資料 >