NameNode升级源码小析

NameNode 升级源码探析
1. 查找NameNode源码类入口
(1)获取start-dfs.sh -upgrade的最终调用
Hadoop执行升级是通过start-dfs.sh -upgrade命令来执行升级的。通过查看start-dfs.sh脚本,其中的调用如下所示:
   
其中的$nameStartOpt为start-dfs.sh的参数 -upgrade。发现最终调用hdfs start namenode -upgrade的命令完成NameNode的升级
(2)查看hdfs脚本的实现
  查看hdfs脚本,发现最终的执行命令是:
  
其中的$CLASS根据hdfs命令的第二个参数获取:
  
发现最终是调用了'org.apache.hadoop.hdfs.server.namenode.NameNode'这个类。
2.NameNode类探析
(1)NameNode main入口
找到NameNode类后,找到了该类的Main函数

从上图可以发现,Main函数会首先创建一个NameNode对象,创建成功后,进入join状态,开始提供服务。重点跟踪createNameNode这个方法
(2)createNameNode()
createNameNode中,首先对传入的参数进行了处理,并获取参数start0pt="-upgrade",然后会根据startOpt进行分支选择

      
如图所示,发现-upgrade的参数,最终会走入default分支。默认情况下,主要执行两个操作,初始化参数和返回一个NameNode对象。初始化参数不是我们关注的重点,因此,跟踪NameNode构造函数。
(3)NameNode构造函数
  查找到NameNode(conf)的构造函数,发现其会调用NameNode(Configuration conf, NamenodeRole role) 构造函数,如下图所示:
  
其中,NNameNode(conf,role)构造函数,首先获取了配置文件中的nsID等信息,并判定是否为HA模式,之后。会根据conf进行初始化操作initialize(conf)。如上图所示:(这个初始化过程会执行fsimage加载,目录保存等操作)。因此,跟踪initialize(conf)函数
(4)initialize(conf)函数

这个初始化函数首先会初始化NameNode的用户,启动httpServer服务等,关键一步是loadNamesystem(conf)。这个函数会根据conf,加载一个NameSystem。在完成后,会生成一个rpcServer
(5)LoadNamesystem(conf)

根据loadNamesystem的源码可以看到,FSNamesystem会从本地磁盘加载名字文件系统
(6)loadFromDisk(conf)
这个函数的功能是根据配置文件中的配置信息,实例化生成一个名字文件系统(FSNamesystem)。

如上图所示,在1中,会实例化一个fsImage,这个fsImage对象会指定默认的checkpoint目录,并建立一个storage和实例化editlog
在2中,通过fsImage构造了一个NameSystem对象,这里指定了要加载的FsImage和editlog文件,需要注意的是,这里仅是指定,但是并没有实际开始从磁盘加载。
3中,才是真正开始根据startOpt(这里是-upgrade)加载FsImage到内存中。
(7)namesystem.loadFSImage(startOpt)

如上图所示,loadFSImage这个函数主要有如下内容:
1)获取一个fsImage对象
2)判定startOpt参数是不是format,如果是的话,则执行fromat操作,并将startOpt=“-regular”
3)判定是否是老版本的Image,注意,如果start=“-upgrade”,即为升级操作的话,会在这个判断过程中,进行upgrade操作。
4)判定是否需要保持NameSpace
5)打开editlog的写,同时将信息写入seen_txid文件中
6)更新加载状态为complete,完成Image加载
这里主要跟踪第三步中的fsImage.recoverTransitionRead(startOpt,this,recovery)这个函数
(8)fsImage.recoverTransitionRead(startOpt,this,recovery)
该函数主要进行如下操作:
1)对目录进行分析,并判定是否格式化过。验证版本信息等
2)对未格式化的目录进行格式化
3)根据startOpt做转换操作

如果是upgrade或者upgradeonly 则执行doUpgrade(target)的操作,执行升级操作
如果是import,则执行doImportCheckpoint(target);操作
如果是rollback,则跑出异常
默认情况下,什么也不做,执行第4步
4)加载Image,并返回返回值
这其中,doUpgrade是我们关心的操作,他会在完成作升级后,返回直接返回,并且返回值为false。
(9)doUpgrade(target)
该函数中的升级主要有如下内容:
1)首先检查是否正在执行升级操作
判定的方法很简单,是通过previous目录是否存在来判定的,若存在说明升级已经执行

2)加载最新的image
1>首先对目录进行检查,更新xxx
2> 获取最接近txid的fsimage
 
其实现,比较明了,如下所示:

 3>初始化editlogs

 4>加载FsImage到内存

 5>加载editLog

加载到内存中的editlog,会将更改操作对内存中加载的命名空间生效。同时在加载完成后,生成最新的txid

3)对每个目录执行更新操作
NNUpgradeUtil.doPreUpgrade(conf, sd);
doPreUpgrade是upgrade的执行预演,如果其中有任何错误,upgrade就不会被调用。执行uptgrade的过程是:
1> 将current目录更改为previous.tmp并创建一个新的current空目录

2> 将previouse.tmp中的edit开头的文件以硬链接的方式链接到current

3>saveFSImageInAllDirs(target, editLog.getLastWrittenTxId());
 将fsimage写入current目录中
4> doUpgrade
  实际执行的更新操作。
首先,saveFSImage操作只是将FSImage写入了current,除此之外目录是空的。因此首先将版本信息写入current
其次,将previouse.tmp目录更改为previous目录
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值