本文主要基于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. js物理弹性窗口

    js物理弹性窗口 点击下载代码

  2. TinyFrame续篇:整合Spring IOC实现依赖注入

    上一篇主要讲解了如何搭建基于CodeFirst的ORM,并且在章节末我们获取了上下文对象的实例:BookContext.这节主要承接上一篇,来讲解如何整合Spring IOC容器实现控制反转,依赖注入 ...

  3. java之yield(),sleep(),wait()区别详解

    1.sleep() 使当前线程(即调用该方法的线程)暂停执行一段时间,让其他线程有机会继续执行,但它并不释放对象锁.也就是说如果有synchronized同步快,其他线程仍然不能访问共享数据.注意该方 ...

  4. 一个C++宏定义与枚举定义重复的编译错误

    C++的开发效率低是众所周知的,原因比如有: 语言复杂度高 编译效率低 工具链不够完整高效(尤其是linux下) 另外一个恐怕是不少编译错误让人摸不着头脑,今天碰到一个,举个例子: #include ...

  5. 奇怪的Js时间计算方法,跨多个月后出现1天的误差

    在项目中要求用计算两个时间相差的天数,通俗的说就是两个时间 相减, 我的方法 先把两个时间转成相应的毫秒,相减后,再除以(1000 * 60 * 60 * 24) 就可以得到对应天数,但天数会比实际少 ...

  6. VMWare虚拟机提供的桥接、nat和主机模式的区别

    虚拟机网络模式 无论是vmware,virtual box,virtual pc等虚拟机软件,一般来说,虚拟机有三种网络模式: 1.桥接 2.NAT 3.Host-Only 哪一种网络是适合自己的虚拟 ...

  7. MySQL多实例

    http://www.kancloud.cn/digest/mysqlsummary/132842http://crazy123.blog.51cto.com/1029610/1611887/ htt ...

  8. Web.config自定义节点configSections

    1.为什么需要自定义节点 为了增加应用程序的可移植性,通常网站需要配置一些自定义的节点,例如:文件上传的路径等,再深入的应用,可以定义工厂方法需要创建的类. 2.configSections使用方法 ...

  9. Shell命令_for

    chmod 755 demo.sh ./demo.sh 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 ...

  10. 【URAL 1486】Equal Squares

    题意:求给定字符矩阵中相同正方形矩阵的最大边长和这两个相同正方形的位置 第一次写字符串哈希,选两个不同的模数进行二维字符串哈希. 本来应该取模判断相等后再暴力扫矩阵来判断,但是我看到<Hash在 ...