前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >漫画大数据:如何解决 NameNode 内存持续增长的问题(一)

漫画大数据:如何解决 NameNode 内存持续增长的问题(一)

作者头像
DataChat
发布2023-02-06 10:49:15
6030
发布2023-02-06 10:49:15
举报
文章被收录于专栏:漫画大数据漫画大数据

漫画大数据:HDFS 中 NameNode 的内存为什么会一直涨?

以下内容参考自:https://tech.meituan.com/2016/08/26/namenode.html

NameNode 内存全景

NameNode 管理着整个 HDFS 文件系统的元数据。从架构设计上看,元数据大致分成两个层次:

  • Namespace 管理层,负责管理文件系统中的树状目录结构以及文件与数据块的映射关系;
  • 块管理层,负责管理文件系统中文件的物理块与实际存储位置的映射关系 BlocksMap,如图 1 所示。

图 1

除了对文件系统本身元数据的管理之外,NameNode 还需要维护整个集群的机架及 DataNode 的信息、Lease 管理以及集中式缓存引入的缓存管理等等。这几部分数据结构空间占用相对固定,且占用较小。

NameNode 整个内存结构大致可以分成四大部分:Namespace、BlocksMap、NetworkTopology 及其它,图 2 为各数据结构内存逻辑分布图示。

图 2

  • Namespace:维护整个文件系统的目录树结构及目录树上的状态变化;
  • BlockManager:维护整个文件系统中与数据块相关的信息及数据块的状态变化;
  • NetworkTopology:维护机架拓扑及 DataNode 信息,机架感知的基础;
  • 其它:
    • LeaseManager:读写的互斥同步就是靠 Lease 实现,支持 HDFS 的 Write-Once-Read-Many 的核心数据结构;
    • CacheManager:Hadoop 2.3.0 引入的集中式缓存新特性,支持集中式缓存的管理,实现 memory-locality 提升读性能;
    • SnapshotManager:Hadoop 2.1.0 引入的 Snapshot 新特性,用于数据备份、回滚,以防止因用户误操作导致集群出现数据问题;
    • DelegationTokenSecretManager:管理 HDFS 的安全访问;
    • 另外还有临时数据信息、统计信息 metrics 等等。

NameNode 常驻内存主要被 Namespace 和 BlockManager 使用,二者使用占比分别接近 50%。其它部分内存开销较小且相对固定,与 Namespace 和 BlockManager 相比基本可以忽略。

NetworkTopology 内存分析

NameNode 通过 NetworkTopology 维护整个集群的树状拓扑结构,当集群启动过程中,通过机架感知(通常都是外部脚本计算)逐渐建立起整个集群的机架拓扑结构,一般在 NameNode 的生命周期内不会发生大变化。拓扑结构的叶子节点 DatanodeDescriptor 是标识 DataNode 的关键结构,该类继承关系如下图所示:

DatanodeDescriptor 继承关系

在 64 位 JVM 中,DatanodeDescriptor 内存使用情况如下图所示(除特殊说明外,后续对其它数据结构的内存使用情况分析均基于 64 位 JVM):

DatanodeDescriptor 内存使用详解

由于 DataNode 节点一般会挂载多块不同类型存储单元,如 HDD、SSD 等,图 2 中 storageMap 描述的正是存储介质 DatanodeStorageInfo 集合,其详细数据结构如下图所示:

DatanodeStorageInfo 内存使用详解

除此之外,DatanodeDescriptor 还包括一部分动态内存对象,如 replicateBlocks、recoverBlocks 和 invalidateBlocks 等与数据块动态调整相关的数据结构,pendingCached、cached 和 pendingUncached 等与集中式缓存相关的数据结构。由于这些数据均属动态的形式临时存在,随时会发生变化,所以这里没有做进一步详细统计(结果存在少许误差)。

根据前面的分析,假设集群中包括 2000 个 DataNode 节点,NameNode 维护这部分信息需要占用的内存总量:

(64 + 114 + 56 + 109 ∗ 16)∗ 2000 = ~4MB

在树状机架拓扑结构中,除了叶子节点 DatanodeDescriptor 外,还包括内部节点 InnerNode 描述集群拓扑结构中机架信息。

NetworkTopology 拓扑结构内部节点内存使用详解

对于这部分描述机架信息等节点信息,假设集群包括 80 个机架和 2000 个 DataNode 节点,NameNode 维护拓扑结构中内部节点信息需要占用的内存总量:

(44 + 48) ∗ 80 + 8 ∗ 2000 = ~25KB

从上面的分析可以看到,为维护集群的拓扑结构 NetworkTopology,当集群规模为 2000 时,需要的内存空间不超过 5MB,按照接近线性增长趋势,即使集群规模接近 10000,这部分内存空间~25MB,相比整个 NameNode JVM 的内存开销微乎其微。

NameSpace 内存分析

与传统单机文件系统相似,HDFS 对文件系统的目录结构也是按照树状结构维护,NameSpace 保存的正是整个目录树及目录树上每个目录 / 文件节点的属性,包括:名称(name)编号(id)所属用户(user)所属组(group)权限(permission)修改时间(mtime)访问时间(atime)子目录/文件(children)等信息。

图 3 为 Namespace 中 INode 的类图结构,从类图可以看出,文件 INodeFile 和目录 INodeDirectory 的继承关系。其中目录在内存中由 INodeDirectory 对象来表示,并用 List children 成员列表来描述该目录下的子目录或文件;文件在内存中则由 INodeFile 来表示,并用 BlockInfo[] blocks 数组表示该文件由哪些 Blocks 组成。其它属性由继承关系的各个相应子类成员变量标识。

图 3

目录和文件结构在继承关系中各属性的内存占用情况如图 4 所示:

图 4

除图中提到的属性信息外,一些附加如 ACL 等非通用属性,没有在统计范围内。在默认场景下,INodeFileINodeDirectory.withQuotaFeature 是相对通用和广泛使用到的两个结构。

根据前面的分析,假设 HDFS 目录和文件数分别为 1 亿,Block 总量在 1 亿情况下,整个 Namespace 在 JVM 中内存使用情况:

Total(Directory) = (24 + 96 + 44 + 48) ∗ 100M + 8 ∗ num(total children)

Total(Files) = (24 + 96 + 48) ∗ 100M + 8 ∗ num(total blocks)

Total = (24 + 96 + 44 + 48) ∗ 100M + 8 ∗ num(total children) + (24 + 96 + 48) ∗ 100M + 8 ∗ num(total blocks) = ~38GB

关于预估方法的几点说明:

    1. 对目录树结构中所有的 Directory 均按照默认 INodeDirectory.withQuotaFeature 结构进行估算,如果集群开启 ACL/Snapshotd 等特性,需增加这部分内存开销。
    1. 对目录树结构中所有的 File 按照 INodeFile 进行估算。
    1. 从整个目录树的父子关系上看,num (total children) 就是目录节点数和文件节点数之和。
    1. 部分数据结构中包括了字符串,按照均值长度为 8 进行预估,实际情况可能会稍大。

Namespace 在 JVM 堆内存空间中常驻,在 NameNode 的整个生命周期一直在内存存在,同时为保证数据的可靠性,NameNode 会定期对其进行 Checkpoint,将 Namespace 物化到外部存储设备。随着数据规模的增加,文件数 / 目录树也会随之增加,整个 Namespace 所占用的 JVM 内存空间也会基本保持线性同步增加。

BlocksMap 内存分析

HDFS 将文件按照一定的大小切成多个 Block,为了保证数据可靠性,每个 Block 对应多个副本,存储在不同 DataNode 上。NameNode 除需要维护 Block 本身的信息外,还需要维护从 Block 到 DataNode 列表的对应关系,用于描述每一个 Block 副本实际存储的物理位置,BlockManager 中 BlocksMap 结构即用于 Block 到 DataNode 列表的映射关系。BlocksMap 内部数据结构如图 5 所示。

图 5

BlocksMap 经过多次优化形成当前结构,最初版本直接使用 HashMap 解决从 Block 到 BlockInfo 的映射。由于在内存使用、碰撞冲突解决和性能等方面存在问题,之后使用重新实现的 LightWeightGSet 代替 HashMap,该数据结构本质上也是利用链表解决碰撞冲突的 HashTable,但是在易用性、内存占用和性能等方面表现更好。关于引入 LightWeightGSet 细节可参考 HDFS-1114。

与 HashMap 相比,为了尽可能避免碰撞冲突,BlocksMap 在初始化时直接分配整个 JVM 堆空间的 2% 作为 LightWeightGSet 的索引空间,当然 2% 不是绝对值,如果 2% 内存空间可承载的索引项超出了 Integer.MAX_VALUE/8(注:Object.hashCode () 结果是 int,对于 64 位 JVM 的对象引用占用 8Bytes)会将其自动调整到阈值上限。限定 JVM 堆空间的 2% 基本上来自经验值,假定对于 64 位 JVM 环境,如果提供 64GB 内存大小,索引项可超过 1 亿,如果 Hash 函数适当,基本可以避免碰撞冲突。

BlocksMap 的核心功能是通过 BlockID 快速定位到具体的 BlockInfo,关于 BlockInfo 详细的数据结构如图 6 所示。BlockInfo 继承自 Block,除了 Block 对象中 BlockID,numbytes 和 timestamp 信息外,最重要的是该 Block 物理存储所在的对应 DataNode 列表信息 triplets。

图 6

其中 LightWeightGSet 对应的内存空间全局唯一。尽管经过 LightWeightGSet 优化内存占用,但是 BlocksMap 仍然占用了大量 JVM 内存空间,假设集群中共 1 亿 Block,NameNode 可用内存空间固定大小 128GB,则 BlocksMap 占用内存情况:

16 + 24 + 2% ∗ 128GB +( 40 + 128 )∗ 100M = ~20GB

BlocksMap 数据在 NameNode 整个生命周期内常驻内存,随着数据规模的增加,对应 Block 数会随之增多,BlocksMap 所占用的 JVM 堆内存空间也会基本保持线性同步增加。

总结

假设 HDFS 中,目录数量为 num_directory,文件数量为 num_files,所有文件对应的 block 总数为 num_blocks

NameSpace 中,目录信息所占用的内存总量可近似计算为:

代码语言:javascript
复制
Total(Directory) = 212 Byte ∗ num_directory + 8 Byte ∗ (num_directory + num_files) 
                 = 220 Byte * num_directory + 8 Byte * num_files

文件信息所占用的内存总量可近似计算为:

代码语言:javascript
复制
Total(Files) = 168 Byte ∗ num_files + 8 Byte ∗ num_blocks

BlockMap 所占用的内存总量可近似计算为:

代码语言:javascript
复制
Total(BlockMap) = 40 Byte + 2% ∗ NameNode堆内存 + 168 Byte ∗ num_blocks 

由于 NameSpace 和 BlockMap 几乎占满了 NameNode 的内存,所以一般估算 NameNode 所需内存时,还可以近似为:

代码语言:javascript
复制
Total = Total(Directory) + Total(Files) + Total(BlockMap)
     ~= 200 Byte * (num_directory + num_files + num_blocks) + 2% * NameNode堆内存

—————END—————

文中「澜妹、澜宝」使用了数澜的吉祥物,点击获取 业界首张《数据中台产品技术能力地图》

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

本文分享自 DataChat 微信公众号,前往查看

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • NameNode 内存全景
  • NetworkTopology 内存分析
  • NameSpace 内存分析
  • BlocksMap 内存分析
  • 总结
相关产品与服务
大数据
全栈大数据产品,面向海量数据场景,帮助您 “智理无数,心中有数”!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档