hadoop-NameNode篇(基于0.20版本)

 本篇文章中重点介绍hdfs中NameNode的实现原理,由于内容非常多,要在一条线上将所有的东西都说清楚很难,所以采用的是先从宏观角度说明整体流程,其中某个环节如果复杂,为了不影响把控大的流程,所以这种点上可能就稍稍带过,如果要更详细的了解该环节的具体情况,就需要跳到其他章节去看。所以文字组织上比较乱,个人文字功底薄弱,还望大家见谅。另外,hadoop是一个非常复杂的系统,后面的内容是结合先前看源代码加上最近时间的温习,业余时间整理出来的,有问题的地方,请大家指正,我积极修改,望不以误导人为目的。

 

本篇文章是第一篇,后面我会继续整理map/reduce,hive,hbase,storm以及本人之前做过的一些大数据量方面的计算框架的开发,希望不会误导赏脸的朋友。

 

整体流程:

首先从整体上理解一下NameNode的执行流程

首先通过NameNode.java的main触发启动流程,加载配置信息,根据命令参数判定当前的启动模式(常规/导入/升级/格式化等),触发相应的启动流程,这里我们先介绍常规模式:

  1. 初始化安全模块(hadoop.security.authorization控制是否启动,默认关闭,具体实现逻辑见文章后面章节)
  2. 初始化统计模块(通过该模块将统计数据上报到JMX和所配置的监控服务器)
  3. 启动InfoServer(就是http://hadoopMasterServer:50070这个服务,通过该服务,用户可以使用浏览器查看文件系统状态,SecondaryNameNode可以通过该接口下载快照和EditLog等,服务启动在dfs.http.address,内部使用jetty实现)
  4. 启动NameSystem模块,加载快照和EditLog到内存(该模块是NameNode最核心的模块,元数据的管理逻辑都封装在该模块中,本文章中大部分都是在解释他的逻辑)
  5. 启动RPC服务器(接收ClientDataNoderpc请求,端口在fs.default.name)(RPC实现原理见后面章节)

6.    启动Trash线程(定时清空回收站,是否启动使用fs.trash.interval配置,默认关闭)

7.    Main主线程循环等待RPC服务器stop,否则一直循环(要关闭nameNode,只能是kill进程,nameNode没有提供一个类似tomcatshutdown port。采用kill是否安全,后面章节也会分析)

启动完成之后,RPC服务器和Info服务器就开始接收请求,以及相关后台线程循环执行其对应逻辑:

  1. RPC服务器接收客户端的请求,如createdeleteaddBlock等元数据修改接口,这些请求会转到由FSNamesystem处理,RPC服务器也接收DataNode的请求,如register(注册DataNode),reportBlock(上报Block信息)等,这些命令内部的执行逻辑后面我们会说到。
  2. InfoServer接受用户用的管控请求(如/listPaths,/fsck等),也接受SecondaryNameNode的请求,如getimage下载快照和EditLog
  3. 后台一些Monitor线程处理如回收站内容删除,检查DFSClient异常关闭,检查Block备份数是否正确等

 

FSNamesystem

该模块维护HDFS文件系统的元数据,如系统中的有哪些文件,每个文件中有哪些Block,各个Block存放在哪些DataNode中,并且提供对这些元数据进行操作的接口。

首先,我们可以将元数据是否会持久化到磁盘分为两类:一类是需要持久化的,如文件目录树,文件的block列表,权限等数据,当改变这些数据时,会生成操作日志被记录到磁盘里面;另一类是不需要持久化的,如Block在哪些DataNode上存储,或者反过来DataNode上存储有哪些Block,这类数据当DataNode启动时,由DataNode主动上报到NameNode,有NameNode完成收集汇总。

接下来我们介绍需要持久化的元数据如何保存。首先这里面有两个术语:快照(Image,内存中的数据结构持久化到磁盘之后的文件)和操作日志(EditLog)。当对元数据进行修改时(如create/delete),除了修改元数据在内存中的结构而外,同时会生成这些操作的操作日志,也就是EditLog,这些日志会被即时的存储到硬盘中,元数据在内存中的结构会在某些时候生成快照被持久化到磁盘。当启动NameNode时,从磁盘中得到快照,和快照之后才产生的操作日志,根据操作日志在快照的基础上重新执行这些操作,就可以恢复内存中的数据结构。不需要持久化的Block存储的DataNode列表数据,被存储在BlockMap结构中,通过该结构,可以根据block信息得到其存储的DataNode。

 

元数据在内存中的对象模型:

说明:从图中我们可以看出针对是否需要持久化到硬盘的数据,NameNode分别使用BlockMap和FSDirectory维护。在FSDirectory对象中保存需要持久化的元数据信息,数据分为两种形式存储,一种是内存结构(INodeDirectoryWithQuota,该类继承于INodeDirectory,增加了限额的功能),一种是磁盘中的FSImage结构。

l  INodeDirectoryWithQuota继承至INodeDirectory,可以保存子节点,当HDFS中新增一个文件时,从FSDirectory的rootDir开始逐层找到父节点的INodeDirectory实例,在该实例下新增一个子节点(这里我们顺便提一下INodeFile和其子类INodeFileUnderConstruction的区别,当一个文件没有被create/append打开时,文件在内存中由INodeFile维护,一旦被这两个操作打开,说明要修改文件内容,为了防止多用户同时操作同一个文件,以及防止client异常退出,于是进入租约模型,此时该文件替换为使用INodeFileUnderConstruction来维护,该类相比INodeFile多了一个非常重要的一个属性clientName,用于记录该文件目前正在被哪个client操作,当完成文件写操作之后,撤销租约,再换回成INodeFile来维护,对租约模型感兴趣的朋友,可以参见下面的章节)。

l  FsImage维护快照和操作日志(EditLog),快照和操作日志可以在多个目录下同时存储多份,用以防止某个磁盘坏掉的情况(如果担心整个机子挂掉,可以存储一份到NFS磁盘上,多路径是在配置文件中用逗号隔开,分别使用dfs.name.dir,dfs.name.edits.dir维护快照和操作日志的存储路径),所以我们看到Storage(FSImage继承至Storage)中storageDirs(保存数据的跟目录)是一个数组,FSEditLog中editStreams也是一个数组,当对元数据进行修改时,会向editStream数组中保存的所有输出流都写入操作日志,当然同时也会在修改FSDirectory维护的内存数据。

 

了解了元数据的对象结构之后,我们再看看这些数据被持久化到磁盘之后是什么样的结构:

在参数dfs.name.dir配置的路径下,我们一般可以看到有如下的目录结构,我们先说明一个每个文件的作用,然后再讲解一下每个文件的格式。存储在磁盘中的元数据有多个状态,不同的状态存储在不同的文件夹下,如current,lastcheckpoint.tmp,previous.checkpoint等。

当从内存保存元数据到磁盘时:

1.      将current  rename为lastcheckpoint.tmp

2.      存储内存数据到current

3.      如果previous.checkpoint 存在,先删除,然后将lastcheckpoint.tmp rename为 previous.checkpoint

        current
                edits   存储操作日志

                fsimage  存储当前快照,使用fsimage+edits即是当

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值