接前文 分布式存储-HDFS 架构解析,我们总体分析了 HDFS 架构的主要构成组件包括:NameNode、DataNode 和 Client。本文首先进一步解析 HDFS NameNode 的设计和实现要点。

元数据持久化

NameNode 将所有元信息以特定的数据结构组织存放在内存中,对于 namespace 和 replication factor 的信息会进行持久化,而映射关系则不会持久化。因为映射关系是通过 DataNode 启动后定时汇报上来,即使 NameNode 重启后内存信息丢失也可以通过 DataNode 重新汇报获得,而其他元信息则必须通过读取持久化存储来重建内存数据结构。出于性能原因,所有元信息的读取直接从内存中获得,而增删改操作则借鉴来数据库的事务日志技术。每次只变更内存数据结构并记录操作日志,将随机写变为顺序写来提高吞吐能力。

NameNode 使用一个事务日志文件 EditLog 来持久化记录针对文件系统元数据的每一次操作变更。而整个 file system namesapce 文件、文件块和数据节点的映射关系被存储在另一个 FsImage 文件中。当 NameNode 启动时,它读取 FsImage 文件构建元数据的内存数据结构,接着读取 EditLog 文件应用所有的操作事务到内存数据结构中。接着基于最新的内存数据结构重新写一个新的 FsImage 文件到磁盘上,然后清除 EditLog 的内容,因为它上面记录的所有操作日志都已经反应到 FsImage 上了。这个过程称为建立了一个检查点(checkpoint),当然检查点技术也是数据库里最常用的了。启动过程中 NameNode 会进入一种特殊状态,称为安全模式(Safemode state),它等待 DataNode 报告文件块及其副本的数量并确定哪些文件的副本数量是不足的。

所有上述启动过程完成后,NameNode 才能对外提供服务。

数据分布策略

除了文件系统元数据管理外,NameNode 另一个重要作用是对写入的文件块选择合适 DataNode 来存放,称为 block placement policy。在通常情况下,replication factor(副本数)默认为 3, HDFS 的数据分布策略是将两份副本放在本地机架的两个不同 DataNode 上,最后一个副本放在另外一个机架的一个 DataNode 上。

NameNode 基于机架感知的数据分布策略并未考虑 DataNode 的磁盘空间利用率。这有效避免了将新的文件数据集中放置在一组拥有大量剩余空间的 DataNodes 上,比如新扩容的 DataNodes。这又带来另外一个问题,就是扩容新 DataNode 时导致数据分布的严重不平衡。

为了应对此类情况,HDFS 引入了一个平衡器工具(Balancer),在整个集群平衡磁盘空间利用率。这个工具通过引入设置一个在 0 和 1 之间的阈值来判断整个集群是否达到平衡。

HDFS 对于磁盘均衡的定义如下:

对于每一个 DataNode 其磁盘利用率与整个集群的平均利用率相比不超过设置的阈值偏差。

平衡器工作过程中确保不会减少副本总数,及其分布的机架数。也就是原来三个副本分布在两个机架,被平衡后也还是三个副本分布在两个机架,但可能移动到不同的 DataNode 上了。为了减少网络带宽占用,会尽可能避免机架间拷贝数据。例如:副本 A1 和 A2 在 Rack1,A3 在 Rack2,若平衡器认为 A1 所在 DataNode 磁盘利用率过高,需要移动 A1。在 Rack1 内找不到磁盘利用率低的其他 DataNode,则需要将 A1 移动到 Rack2。实际做法是直接从 Rack2 的 A3 复制一份得到 A4,并删除 Rack1 上的 A1,这样就避免了机架间复制。

复制管理

NameNode 努力确保每一个副本符合配置的 replication factor。假如 DataNode 宕机发生导致一些文件的 block 副本数变少,Namdenode 会发出复制命令给 DataNode,复制出新的副本以保持与配置的副本数一致。当宕机的 DataNode 恢复后重新加入集群后会导致一些文件的副本数超出配置数,NameNode 会检测到并删除多余的副本以节省存储空间。NameNode 维护一个复制优先级队列,对于副本不足的文件 block 按优先级排序,仅剩下一个副本的文件 block 享有最高的复制优先级。

性能设计

除了 NameNode 的单点和重启过程影响可用性外,另一个担忧因素是性能。
读操作基于内存访问还好,写操作中磁盘是一个瓶颈点。而 NameNode 支持大量 Client 的并发读写,对于大量的并发写操作 NameNode 进行了优化。多线程情况下,当一个线程为保存操作事务日志发起一个 flush-and-sync 到磁盘文件的操作,其他线程只能等待。为了优化此类情况,NameNode 将随机写转换为批量写操作。当一个 NameNode 的线程初始化了一个 flush-and-sync 操作,所有当时的事务操作日志被批量写入文件。其余的线程只需要检查它们的事务是否被保存到了文件而不再需要再发起 flush-and-sync 操作。

总结

上面描述了 NameNode 提供的功能及其设计实现要点,最后我们简单点评下它在架构设计上的权衡考量。首先 NameNode 作为中心节点简化了整体设计,但很显然它也是个单点,会影响可用性。其次 NameNode 将所有元数据存储在内存中,内存的容量决定了整个分布式文件系统能支持文件数量,如果是大量的小文件场景也是个问题。而且 HDFS 基于 java 实现,java 针对大堆内存的 GC 优化也是个麻烦事。再次上面描述的 NameNode 的启动过程看起来就很耗时,特别是在 FsImage 和 EditLog 都很大的情况下。而且在 NameNode 的启动完成前整个 HDFS 是不可用的,所以 NameNode 即使是重启也对整体的可用性有很大影响。

参考

[1] Hadoop Documentation. HDFS Architecture.
[2] Robert Chansler, Hairong Kuang, Sanjay Radia, Konstantin Shvachko, and Suresh Srinivas. The Hadoop Distributed File System


下面是我自己开的一个微信公众号 [瞬息之间],除了写技术的文章、还有产品的、行业和人生的思考,希望能和更多走在这条路上同行者交流,有兴趣可关注一下,谢谢。

版权声明:本文为博主原创文章,未经博主允许不得转载。

HDFS NameNode 设计实现解析的更多相关文章

  1. 后端分布式系列:分布式存储-HDFS NameNode 设计实现解析

    接前文 分布式存储-HDFS 架构解析,我们总体分析了 HDFS 架构的主要构成组件包括:NameNode.DataNode 和 Client.本文首先进一步解析 HDFS NameNode 的设计和 ...

  2. HDFS Client 设计实现解析

    前面对 HDFS NameNode 和 DataNode 的架构设计实现要点做了介绍,本文对 HDFS 最后一个主要构成组件 Client 做进一步解析. 流式读取 HDFS Client 为客户端应 ...

  3. HDFS DataNode 设计实现解析

    前文分析了 NameNode,本文进一步解析 DataNode 的设计和实现要点. 文件存储 DataNode 正如其名是负责存储文件数据的节点.HDFS 中文件的存储方式是将文件按块(block)切 ...

  4. 后端分布式系列:分布式存储-HDFS Client 设计实现解析

    前面对 HDFS NameNode 和 DataNode 的架构设计实现要点做了介绍,本文对 HDFS 最后一个主要构成组件 Client 做进一步解析. 流式读取 HDFS Client 为客户端应 ...

  5. 后端分布式系列:分布式存储-HDFS DataNode 设计实现解析

    前文分析了 NameNode,本文进一步解析 DataNode 的设计和实现要点. 文件存储 DataNode 正如其名是负责存储文件数据的节点.HDFS 中文件的存储方式是将文件按块(block)切 ...

  6. 2本Hadoop技术内幕电子书百度网盘下载:深入理解MapReduce架构设计与实现原理、深入解析Hadoop Common和HDFS架构设计与实现原理

    这是我收集的两本关于Hadoop的书,高清PDF版,在此和大家分享: 1.<Hadoop技术内幕:深入理解MapReduce架构设计与实现原理>董西成 著  机械工业出版社2013年5月出 ...

  7. 大数据技术 - 分布式文件系统 HDFS 的设计

    本章内容介绍下 Hadoop 自带的分布式文件系统,HDFS 即 Hadoop Distributed Filesystem.HDFS 能够存储超大文件,可以部署在廉价的服务器上,适合一次写入多次读取 ...

  8. Hadoop:HDFS NameNode内存全景

    原文转自:https://tech.meituan.com/namenode.html 感谢原作者 一.概述 从整个HDFS系统架构上看,NameNode是其中最重要.最复杂也是最容易出现问题的地方, ...

  9. HDFS核心设计

    一.HDFS核心设计 数据块(block) 数据块是HDFS上最基本的存储单位 HDFS块默认大小为128M         对块进行抽象会带来的好处 一个小文件的大小可以大于网络中任意一个磁盘的容量 ...

随机推荐

  1. 动态创建DAL层类的实例

    为了可扩展性,方便以后对于代码的修改维护,使用动态创建DAL层对象. 1.首先在webconfig中的configuration下添加配置项 <appSettings> <add k ...

  2. 如何快速找到排好序的数组中最先不连续的数字N

    现在有一大堆自然数组成的小到大数组arr,其中会有123456910  这样就要找到6(最先不连续的数字) 举例:[12356789] 找到3 [012345678] 找到8 第一种:遍历数组判断是否 ...

  3. DNG格式解析

    Author:Maddock Date:2015.04.22 转载请注明出处:http://www.cnblogs.com/adong7639/p/4446828.html DNG格式基本概念 DNG ...

  4. HashMap源码阅读笔记(基于jdk1.8)

    1.HashMap概述: HashMap是基于Map接口的一个非同步实现,此实现提供key-value形式的数据映射,支持null值. HashMap的常量和重要变量如下: DEFAULT_INITI ...

  5. git学习(四):撤销修改和撤销删除

    修改有两种情况 在工作区修改但没有add到暂存区 git checkout -- <file> 在工作区修改了也add到暂存区 git reset HEAD <file> 先撤 ...

  6. Addthis

    WordPress外贸主题模版可以非常方便地整合国外流行的分享收藏社会化网络功能,比如Addthis是国外一个网络书签按钮聚合网站,是稳步提升网站流量和搜索引擎排名的WEB2.0工具!通过AddThi ...

  7. java.lang.NoSuchMethodException: org.apache.ibatis.executor.statement.StatementHandler.prepare(java.sql.Connection)

    此错误是由于版本造成的,如果使用mybatis3.4版本以上,配置拦截器规则应增加Intger @Intercepts({ @Signature( type= StatementHandler.cla ...

  8. 通过sql server 连接mysql

    图文:通过sql server 连接mysql   1.在SQL SERVER服务器上安装MYSQL ODBC驱动; 驱动下载地址:http://dev.mysql.com/downloads/con ...

  9. iOS how to stop a scrolling scrollView

    - (void)killScroll { CGPoint offset = scrollView.contentOffset; offset.y -= 1.0; [scrollView setCont ...

  10. System.getProperty()方法大全

    System.out.println("当前程序所在目录:" + System.getProperty("user.dir")); // 当前程序所在目录 Sy ...