本文主要基于Hadoop1.1.2分析HDFS中的关键数据结构。

1 NameNode

首先从NameNode开始。NameNode的主要数据结构如下:

NameNode管理着两张很重要的表:

1)  filename->blocksequence (namespace)

2)  block->machinelist ("inodes")

第一张表保存在磁盘上,第二张表在每次NameNode启动的时候重建。这两张表的信息分别保存在FSDirectory和BlocksMap中。

实际上NameNode并没有亲自完成上述两张表的管理工作,而是由FSNamesystem完成绝大部分的文件系统管理工作。NameNode主要负责向外部提供IPC接口以及HTTP服务,外加上一些配置管理工作。Namenode自己主要实现了三个通信接口:

ClientProtocol:和客户端的通信

DatanodeProtocol:和DataNode的通信

NamenodeProtocol:主要和Second NameNode的通信

2 FSNamesystem

NameNode将绝大部分工作都交给了FSNamesystem处理,先来看看FSNamesystem的内部主要数据结构:

下面分别简单解释FSNamesystem内部封装的各个对象。

(1)BlocksMap blocksMap

负责block->block's metadata的映射。

具体有三种映射,如下:
block->datanode list
block->INodeFile
datanode->blocks

(2)NetworkTopology clusterMap

保存了DataNode集群的拓扑结构。

(3)CorruptReplicasMap corruptReplicas

字面意思:出错副本映射。用来记录datanode上所有出错的block。CorruptReplicasMap内部主要封装了一个Block到DataNode集合的映射表。Map<Block, Collection<DatanodeDescriptor>>。

(4)NavigableMap<String, DatanodeDescriptor> datanodeMap

暂时没弄懂

(5)

(6)

3 BlocksMap

现在来具体分析BlocksMap的内部结构:

BlocksMap内部最主要的结构就是一个GSet。GSet是一个存储key-value对的Set。可以将BlocksMap看成一个内部封装了一个没有重复存储Block的数组的数据结构。

BlocksMap负责block->block's metadata的映射。

具体有三种映射,如下:
block->datanode list
block->INodeFile
datanode->blocks

4 Block

Block表示文件的某个块。Block可以看做HDFS中的原始数据类型,它由一个Long类型的blockId标识。

5 BlocksMap.BlockInfo

BlockInfo这个类定义在BlocksMap内部,继承自Block,先看看它的主要内部结构:

BlockInfo保存了块的元数据信息。

  • block->dataNodeList(块所在的物理位置)
  • block->InodeFile(块在文件目录中的逻辑位置)

这里涉及到两个映射关系:

  1. 一方面,由于一个块具体是存储在某些个DataNode中的,所以需要保存Block与DataNode的映射关系。
  2. 另一方面,Block在逻辑上是属于某个文件的,所以得保存该Block与文件(InodeFile)的映射关系。

所以在具体实现上,BlockInfo封装了如下信息来分别保存上述映射关系:

private INodeFile inode;  //保存块所属的文件
private Object[] triplets; //三元组,数组长度是副本数*3,保存Block与DataNode的映射关系

正是由于采用了三元组这种数据结构,所以实际上三元组还隐藏了第三种映射关系:

  • datanode->blocks

通过一个block可以知道该block所在的DataNode,然后可以查找到该DataNode中存储的所有block。要想理解这句话,得先弄清楚三元组的具体结构。

详解三元组

文件副本的数目称为文件的副本系数。

一个三元组保存了一个Block的副本的相关信息。在HDFS的具体实现上,是用一个数组的三个连续单元(triplets[3i],triplets[3i+1],triplets[3i+2])来表示一个三元组。

为了容错,一个块会有多个副本,在大多数情况下,副本系统是3。HDFS将这些副本放在数组中连续存储起来,因为一个副本用一个三元组表示,所以每个副本占据3个连续的数组单元,所以如果某个块的副本系统为R,则该块的所有副本占据3*R个数组单元。

因为一个块的所有的副本都是采用数组连续存储的,所以可以实现高效的随机访问。比如需要查看某个块的第i(i>=1)个副本的信息,则直接访问triplets[3(i-1)]即可获得指向该副本所在的DatanodeDescriptor引用;直接访问triplets[3(i-1)+1]即可获得指向该副本所在的DataNode中Block列表中的上一个Block的引用;直接访问triplets[3(i-1)+2]即可获得指向该副本所在的DataNode中Block列表中的下一个Block的引用。这是因为对于每个副本的三元组:

  • triplets[3i]:指向该副本所在的DatanodeDescriptor的引用
  • triplets[3i+1]:指向该副本所在的DataNode中Block列表中的上一个Block的引用
  • triplets[3i+2]:指向该副本所在的DataNode中Block列表中的下一个Block的引用

6 INode相关的类

INode相关的类如下图所示:

INode: 是对文件系统目录结构中一个节点的抽象,也叫元数据。它用来存放文件及目录的基本信息:名称,父节点、修改时间,访问时间以及UGI信息等。

INodeFile: 表示文件节点,继承自INode,除INode信息外,还有组成这个文件的Blocks列表,重复因子,Block大小等。

INodeDirectory:表示目录节点,继承自INode,此外还有一个INode列表来组成文件或目录树结构。

INodeFileUnderConstruction:表示正在建的文件,继承自INodeFile。

INodeDirectoryWithQuota:表示有配额限制的目录,根目录就是这种类型,继承自INodeDirectory。

7 FSDirectory

FSDirectory存储整个文件系统的目录状态,对整个目录结构的管理。保存着 filename->blockset 的映射。FSDirectory通过调用fsimage和editLog的方法从NameNode本地磁盘读取元数据信息和向本地磁盘写入元数据信息,并登记对目录结构所作的修改到日志文件。

private final NameCache<ByteArray> nameCache;//缓存频繁使用的文件名,字节数组表示INode中的文件名。NameCache内部封装了Map。ByteArray内部封装了一个字节数组。这个字节数组在这里就表示文件的名称。

8 FSImage 相关的数据结构

9 DatanodeDescriptor相关数据结构

(1)Node

表示物理集群中一个节点,可以标识某个数据中心下面的某个机架中的某个节点。该接口提供了一些getter/setter方法,用于设置/获取节点的名称、网络位置等信息。

网络位置是这样的字符串“/dog/orange”,表示该节点位于dog数据中心下面的orange机架。节点名称可按如下表示:“hostname:port”。

(2)DatanodeID

name表示:"主机名:端口"。
storageID:每个集群唯一的storageID。

(3)DatanodeDescriptor

在继承DataNode本身的信息的基础上,还额外添加了与Block相关的信息。参考:http://sid1211.iteye.com/blog/1002488

总结:

几个关键映射表:

filename -> block[] ,谁负责?FSDirectory

block ->DataNode[] ,谁负责?BlocksMap

HDFS实际上具有两个功能:命名空间管理(Namespace management)和块/存储管理服务(block/storage management)。

参考资料

HDFS读写原理:

http://wenku.baidu.com/link?url=BmFDjL6AC1jAOtDt2RFlz8wyesPQIK3xujMX9hZzgCcKdn3AjGKLZr8MhN9csJp2HY4OjkgIMpPfz9h5mSLZBeuiy1whjp4EbgUwv1liT3e

HDFS文件系统结构解析 http://weilaiyxj.iteye.com/blog/933553

http://www.cnblogs.com/wangyonghui/archive/2011/09/01/2162489.html

http://www.cnblogs.com/wangyonghui/archive/2011/09/07/2169565.html

StorageDirectory

http://www.linuxidc.com/Linux/2012-01/50867.htm

http://zy19982004.iteye.com/blog/1876706

HDFS Federation(HDFS 联盟)介绍http://blog.csdn.net/strongerbit/article/details/7013221/

HDFS源码分析:NameNode相关的数据结构的更多相关文章

  1. HDFS源码分析心跳汇报之数据结构初始化

    在<HDFS源码分析心跳汇报之整体结构>一文中,我们详细了解了HDFS中关于心跳的整体结构,知道了BlockPoolManager.BPOfferService和BPServiceActo ...

  2. HDFS源码分析心跳汇报之BPServiceActor工作线程运行流程

    在<HDFS源码分析心跳汇报之数据结构初始化>一文中,我们了解到HDFS心跳相关的BlockPoolManager.BPOfferService.BPServiceActor三者之间的关系 ...

  3. HDFS源码分析心跳汇报之数据块增量汇报

    在<HDFS源码分析心跳汇报之BPServiceActor工作线程运行流程>一文中,我们详细了解了数据节点DataNode周期性发送心跳给名字节点NameNode的BPServiceAct ...

  4. HDFS源码分析之UnderReplicatedBlocks(一)

    http://blog.csdn.net/lipeng_bigdata/article/details/51160359 UnderReplicatedBlocks是HDFS中关于块复制的一个重要数据 ...

  5. HDFS源码分析数据块校验之DataBlockScanner

    DataBlockScanner是运行在数据节点DataNode上的一个后台线程.它为所有的块池管理块扫描.针对每个块池,一个BlockPoolSliceScanner对象将会被创建,其运行在一个单独 ...

  6. HDFS源码分析数据块复制监控线程ReplicationMonitor(一)

    ReplicationMonitor是HDFS中关于数据块复制的监控线程,它的主要作用就是计算DataNode工作,并将复制请求超时的块重新加入到待调度队列.其定义及作为线程核心的run()方法如下: ...

  7. HDFS源码分析之LightWeightGSet

    LightWeightGSet是名字节点NameNode在内存中存储全部数据块信息的类BlocksMap需要的一个重要数据结构,它是一个占用较低内存的集合的实现,它使用一个数组array存储元素,使用 ...

  8. HDFS源码分析数据块汇报之损坏数据块检测checkReplicaCorrupt()

    无论是第一次,还是之后的每次数据块汇报,名字名字节点都会对汇报上来的数据块进行检测,看看其是否为损坏的数据块.那么,损坏数据块是如何被检测的呢?本文,我们将研究下损坏数据块检测的checkReplic ...

  9. HDFS源码分析心跳汇报之数据块汇报

    在<HDFS源码分析心跳汇报之数据块增量汇报>一文中,我们详细介绍了数据块增量汇报的内容,了解到它是时间间隔更长的正常数据块汇报周期内一个smaller的数据块汇报,它负责将DataNod ...

  10. HDFS源码分析之UnderReplicatedBlocks(二)

    UnderReplicatedBlocks还提供了一个数据块迭代器BlockIterator,用于遍历其中的数据块.它是UnderReplicatedBlocks的内部类,有三个成员变量,如下: // ...

随机推荐

  1. ES6 数组解构赋值

    .数组解构 let [a, b, c,d] = ["aa", "bb", 77,88]; alert(a) //弹出aa 可以用babel 解析看ES5的转换结 ...

  2. Java 读取xlsx

    读取特别大的xlsx文件时, 需要使用StreamingReader, 可以控制JVM内存峰值在200M以内 InputStream is = new FileInputStream(new File ...

  3. .net AES加密解密

    using System;      using System.Collections.Generic;      using System.Text;      using System.Secur ...

  4. 根据Unicode编码用C#语言把它转换成汉字的代码

    rt 根据所具有的Unicode编码用C#语言把它转换成汉字的代码 var s = System.Web.HttpUtility.HtmlDecode(Utf8Str); var o = Newton ...

  5. 扩展 easyui-tabs 插件 关闭标签页方法

    $.extend($.fn.tabs.methods,{ allTabs:function(jq){ var tabs = $(jq).tabs('tabs'); var all = []; all ...

  6. 手把手教你使用markdown

    这是 [认真学编程] 系列的 第3篇 文章,欢迎点赞分享.写留言,这些都是对我最好的支持. 全文2300字,阅读预计5分钟] 在前面几篇文章中,多次提到装X神器markdown,本人也是markdow ...

  7. K-means算法及文本聚类实践

    K-Means是常用的聚类算法,与其他聚类算法相比,其时间复杂度低,聚类的效果也还不错,这里简单介绍一下k-means算法,下图是一个手写体数据集聚类的结果. 基本思想 k-means算法需要事先指定 ...

  8. versionCompare 版本号比较工具

    简介 需求非常简单,需要比较软件或app的版本号,判断大小,形如 0.10.2形式的版本号字符串.实现逻辑是按照点(.)分割字符串,然后逐级比较版本大小.不存在的按0处理,空字符串小于非空字符串. 测 ...

  9. 各地IT薪资待遇讨论

    作为一个搞.net开发的程序员,在北京混了三年半,最近准备辞职到上海找工作.由于对上海的IT行业还不是很了解,在这里想让上海的同行们说下你们的情况,以方便我对自己在上海的定位,当然,其余城市的的同行们 ...

  10. BASH 命令以及使用方法小结

    最近工作中需要写一个Linux脚本,用到了很多BASH命令,为了防止以后忘记,在这里把它们一一记下来.可能会比较乱,随便看看就好了.如果有说的不对的地方也欢迎大家指正. 1,export VAR=.. ...