前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >hdfs——nn的启动优化

hdfs——nn的启动优化

作者头像
陈猿解码
发布2023-02-28 14:27:23
2760
发布2023-02-28 14:27:23
举报
文章被收录于专栏:陈猿解码

【概述】


上一篇文章讲解了,在一定DN节点规模,一定block数据量下的并发写文件的优化问题。

在这种节点、数据量规模的集群中,当HDFS全部重启(nn+dn全部重启),或者两个NN都重启后,需要经过较长时间,才能真正对外提供服务。

那么nn启动过程中都干了些啥,主要耗时点在哪,以及应当如何优化,本文就来聊聊这些问题——启动优化。

【启动流程与耗时分析】


NN的启动可以粗略的分为以下几个步骤:

  • 启动http服务
  • 加载文件系统
  • 启动rpc服务
  • 按需启动插件服务
  • 处理dn的注册以及dn的全量块汇报

其中启动HTTP服务、RPC服务,都是在对应配置的IP端口上进行监听,然后创建对应的reader线程、handler线程,然后等待客户端的连接并处理客户端的请求。

而加载文件系统则是启动过程中的关键步骤,又可以细分为:

  • 加载fsimage文件
  • 加载fsimage的MD5文件并进行比对校验
  • 加载editlog文件
  • checkpoint的保存(可选)
  • 进入安全模式

加载fsimage就是读取fsimage文件中的内容,并以此在内存中构建相关的元数据信息;加载editlog则是读取本地editlog文件或到JournalNode上读取editlog文件;checkpoint本质上还是对元数据信息持久化保存,对于HA模式而言,不需要进行checkpoint的保存处理;最后按需进入安全模式,等待dn的注册与块上报,当上报的块信息达到指定比例后(默认为99.9%),延迟一段时间后解除安全模式。

需要注意的是:这几个步骤是串行进行的,一个步骤完成后才进行下一个处理动作。

整个启动过程中,耗时的点在于加载文件系统dn注册后的块汇报。加载文件系统的耗时在整个启动过程中占50%左右,剩下的50%为dn注册的块汇报处理。http服务和rpc服务的启动几乎不耗时。

【fsimage的格式】


既然加载文件系统占整个启动过程中一半的耗时,有必要先来了解了fsimage文件格式是怎样的,具体的加载过程又是怎样的。

整个fsimage文件由几个部分组成,最前面的是Header头信息,然后是多个section段,section之后是一个Summary概要信息,以及Summary的长度。

header的内容在2.4版本之后均固定为"HDFSIMG1",长度为8字节,同时指明后面的section的编码方式(采用protobuf的方式编码存储)。

summary则记录各个section的名字、在文件中的起始偏移位置以及长度。section则保存Hdfs元数据的相关信息,其中最重要的当属INODEINODE_DIR两个section了,通常来说,这两个section占据fsimage的绝大部分空间。

INODE记录了hdfs中包含的所有文件/目录的信息,包括名称及可能的各个属性,每个INODE对应一条记录信息;而INDOE_DIR则记录了INODE的父子关系,也就是文件、目录的层级关系,同样也是一条记录对应一条关系信息。有了两个section,就可以构造出完整的文件系统目录树。

读取fsimage文件时,先读文件末尾4字节,得到Summary的起始位置,然后读取Summary的内容,这样就知道每个section的起始位置,长度,因此就可以按需加载各个section的内容了。

另外,section的加载顺序是串行的,即加载INODE_DIR时,必须先完成INODE的加载,否则可能出现找不到对应的inode条目。

【如何优化】


从上面fsimage的文件格式可以看出,每个文件的inode在INodeSection中都是一个独立的条目,读fsimage文件时单线程遍历每个条目,并在内存中构造对应的数据结构进行存储。因此,当有海量文件信息存储在fsiamge中时,单线程遍历必然是非常耗时的。这也就是启动耗时长的主要原因。

既然单线程加载很慢,那是否可以调整成多线程加载,每个线程读取其中的一部分,从而加速完成整个INodeSection的加载呢?

实际上,社区版本中的优化就是这么做的,将INodeSeciont拆分成多个带sub后缀的新分区名,同时保留原始的分区信息,同时在summary中增加各个子section的信息

真正读取文件时,使用多线程进行加载,每个线程完成一部分子section的读取,实现读取的加速,同样INODE_DIR也通过多线程并行进行读取。

其中,拆分后的子分区个数由配置项("dfs.image.parallel.target.sections")决定,并行加载的线程数由配置项("dfs.image.parallel.threads")决定。

这样一来,就可以通过多线程并行进行加载INODE和INODE_DIR两个section,每个线程读取一个子section,有效提升加载速度。

除此之外,社区还有两个优化:

一个优化是:fsimage文件md5校验计算和fsimage的加载并行处理,在此之前是串行处理的,详见官方JIRA(HDFS-13694)。

另一个优化是:在加载INodeDirectorySection后,需要更新blocksMap、更新nameCache,然后将inode添加到inode directory的child列表中,优化的逻辑是将这三个操作步骤并行进行处理。

【优化效果】


从官方给出的优化效果来看,数据量在几个亿的级别时,三个优化整体能达到40%-60%的提升(有兴趣的可以去看看社区给出的测试数据)。

而实际测试发现,整体效果差不多是在这个范围内,但具体还会NN所在节点的CPU核数有一定的关系,并行加载时,CPU几乎处于满负荷状态,如果核数不够,那么效果会一般,核数稍微大一些,优化的效果会明显了。

【总结】


好了,小结一下,本文主要讲述了nn的启动流程,分析了主要的耗时点,然后结合fsimage的文件结构,讲述社区的实际优化处理,以及优化后的效果。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-01-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 陈猿解码 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档