FSNameSystem
FSNameSystem是HDFS文件系統實際執行的核心,提供各種增刪改查文件操作接口。其內部維護多個數據結構之間的關係:
- fsname->block列表的映射
- 所有有效blocks集合
- block與其所屬的datanodes之間的映射(該映射是通過block reports動態構建的,維護在namenode的內存中。每個datanode在啓動時向namenode報告其自身node上的block)
- 每個datanode與其上的blocklist的映射
- 採用心跳檢測根據LRU算法更新的機器(datanode)列表
FSDirectory
FSDirectory用於維護當前系統中的文件樹。
其內部主要組成結構包括一個INodeDirectoryWithQuota作爲根目錄(rootDir)和一個FSImage來持久化文件樹的修改操作。
INode
HDFS中文件樹用類似VFS中INode的方式構建,整個HDFS中文件被表示爲INodeFile,目錄被表示爲INodeDirectory。INodeDiretoryWithQuota是INodeDirectory的擴展類,即帶配額的文件目錄
INodeFile表示INode書中的一個文件,擴展自INode,除了名字(name),父節點(parent)等之外,一個主要元素是blocks,一個BlockInfo數組,表示該文件對應的block信息。
BlocksMap
BlocksMap用於維護Block -> { INode, datanodes, self ref } 的映射 BlocksMap結構比較簡單,實際上就是一個Block到BlockInfo的映射。
Block
Block是HDFS中的基本讀寫單元,主要包括:
- blockId: 一個long類型的塊id
- numBytes: 塊大小
- generationStamp: 塊更新的時間戳
BlockInfo
BlockInfo擴展自Block,除基本信息外還包括一個inode引用,表示該block所屬的文件;以及一個神奇的三元組數組Object[] triplets,用來表示保存該block的datanode信息,假設系統中的備份數量爲3。那麼這個數組結構如下:
- DN1,DN2,DN3分別表示存有改block的三個datanode的引用(DataNodeDescriptor)
- DN1-prev-blk表示在DN1上block列表中當前block的前置block引用
- DN1-next-blk表示在DN1上block列表中當前block的後置block引用
DN2,DN3的prev-blk和next-blk類似。 HDFS採用這種結構存放block->datanode list的信息主要是爲了節省內存空間,block->datanodelist之間的映射關係需要佔用大量內存,如果同樣還要將datanode->blockslist的信息保存在內存中,同樣要佔用大量內存。採用三元組這種方式能夠從其中一個block獲得到改block所屬的datanode上的所有block列表。
FSImage
FSImage用於持久化文件樹的變更以及系統啓動時加載持久化數據。 HDFS啓動時通過FSImage來加載磁盤中原有的文件樹,系統Standby之後,通過FSEditlog來保存在文件樹上的修改,FSEditLog定期將保存的修改信息刷到FSImage中進行持久化存儲。 FSImage中文件元信息的存儲結構如下(參見FImage.saveFSImage()方法)
FSImage頭部信息
- layoutVersion(int):image layout版本號,0.19版本的hdfs中爲-18
- namespaceId(int): 命名空間ID,系統初始化時生成,在一個namenode生命週期內保持不變,datanode想namenode註冊是返回改id作爲registerId,以後每次datanode與namenode通信時都攜帶該id,不認識的id的請求將被拒絕。
- numberItemOfTree(long): 系統中的文件總數
- generationTimeStamp: 生成image的時間戳
INode信息
FSImage頭之後是numberItemOfTree個INode信息,INode信息分爲文件(INodeFile)和文件目錄(INodeDirectory)兩類,兩者大體一致,分爲INode頭,Blocks區(目錄沒有blocks)和文件權限。
INode頭
- nameLen(short): 文件名長度
- filename(String): 文件名
- replication(short): 備份數量
- modificationTime(long): 最近修改時間
- accessTime(long): 最近訪問時間
- preferedBlockSize(long): 塊大小(目錄爲0)
- block num(int): 塊數量(目錄爲-1)
Blocks區
- blockId(long)
- numBytes(long,block大小)
- generationTimeStamp(long, 更新時間戳)
文件權限
- username(String): 文件用戶名
- group(String): 所屬組
- fileperm(short): 文件權限
underconstructionFile區
layoutverion<-18版本的fsimage還包括正在構建的文件區。與普通Inode信息類似,均有inode頭和blocks區以及文件權限,除此之外,underConstructionFile還包括:
client信息
- clientName:client明
- clientMachine: client機器名
已分配的datanode信息
- ipcport: 服務端口
- capacity: 容量
- dfsuse: 已使用的空間
- remaining: 剩餘空間
- lastupdate: 最新更新時間
- xceiverCount
- location: datanode位置
- hostName:主機名
- state: admin管理狀態
其他結構
CorruptReplicasMap
CorruptReplicasMap通過一個TreeMap維護corrupt狀態block的blocks-->datanodedescriptor(s)映射。一個block備份在多個datanode中,當其中的一個或多個datanode上的block損壞時,會將該datanode加到treeMap中該block對應的datanodeDescriptor集合中。FSNameSystem通過該Map來維護所有損壞的block與其對應datanode的關係。
Map<String, LightWeightHashSet> recentInvalidateSets
維護最近失效的block集合,map中爲storageId->ArrayList,當某個block的一個datanode上副本失效時會將改block和對應的datanode的storeageId添加到recentInvalidateSet中,當datanode想namenode進行heartbeat時,namenode會檢查該datanode中是否有損壞的block,如有,則通知datanode刪除改block。
NavigableMap<String, DatanodeDescriptor> datanodeMap
datanodeMap用於維護datanode->block的映射
ArrayList heartbeats
維護多有當前活着的節點
UnderReplicatedBlocks neededReplications
通過一個優先級隊列來維護當前需要備份的block集合,副本數越少的block優先級越高,0爲最高級,表示當前只有一個副本。
PendingReplicationBlocks pendingReplications;
維護當前正在備份的block集合,並且進行備份請求的時間統計,並通過一個後臺線程(PendingReplicationMonitor)來週期性(默認爲5分鐘)的統計超時的備份請求,當發生超時時,會將這個block重新添加到neededReplications列表中。
LightWeightLinkedSet overReplicatedBlocks
當前需要檢查是否備份過多的block集合
Map<String, Collection> excessReplicateMap
維護系統中datanode與其上的超額備份block的集合,這些超額的備份將被刪除。
轉http://jiangbo.me/blog/2012/10/18/hdfs-namenode-datastructure/