HDFS 的架构设计及组件

HDFS 的特点

  1. 高容错: 由于 HDFS 采用数据的多副本方案,所以部分硬件的损坏不会导致全部数据的丢失。
  2. 高吞吐量: HDFS 设计的重点是支持高吞吐量的数据访问,而不是低延迟的数据访问。
  3. 大文件支持: HDFS 适合于大文件的存储,文档的大小应该是是 GB 到 TB 级别的。
  4. 简单一致性模型: HDFS 更适合于一次写入多次读取 (write-once-read-many) 的访问模型。支持将内容追加到文件末尾,但不支持数据的随机访问,不能从文件任意位置新增数据。
  5. 跨平台移植性: HDFS 具有良好的跨平台移植性,这使得其他大数据计算框架都将其作为数据持久化存储的首选方案。

HDFS 的架构设计

1. 架构的设计原理

HDFS 采用 master/slave 架构。一个 HDFS 集群是由一个 Namenode 和一定数目的 Datanodes 组成。Namenode 是一个中心服务器,负责管理文件系统的名字空间 (namespace) 以及客户端对文件的访问。集群中的 Datanode 一般是一个节点一个,负责管理它所在节点上的存储。HDFS暴露了文件系统的名字空间,用户能够以文件的形式在上面存储数据。从内部看,一个文件其实被分成一个或多个数据块,这些块存储在一组 Datanode 上。 Namenode 执行文件系统的名字空间操作,比如打开、关闭、重命名文件或目录。它也负责确定数据块到具体 Datanode 节点的映射。Datanode 负责处理文件系统客户端的读写请求。在 Namenode 的统一调度下进行数据块的创建、删除和复制。

HDFS_Architecture

2. 架构的稳定性

1. 心跳机制和重新复制

每个 DataNode 定期向 NameNode 发送心跳消息,如果超过指定时间没有收到心跳消息,则将 DataNode 标记为死亡。NameNode 不会将任何新的 IO 请求转发给标记为死亡的 DataNode,也不会再使用这些 DataNode 上的数据。 由于数据不再可用,可能会导致某些块的复制因子小于其指定值,NameNode 会跟踪这些块,并在必要的时候进行重新复制。

2. 数据的完整性

由于存储设备故障等原因,存储在 DataNode 上的数据块也会发生损坏。为了避免读取到已经损坏的数据而导致错误,HDFS 提供了数据完整性校验机制来保证数据的完整性,具体操作如下:

当客户端创建 HDFS 文件时,它会计算文件的每个块的 校验和,并将 校验和 存储在同一 HDFS 命名空间下的单独的隐藏文件中。当客户端检索文件内容时,它会验证从每个 DataNode 接收的数据是否与存储在关联校验和文件中的 校验和 匹配。如果匹配失败,则证明数据已经损坏,此时客户端会选择从其他 DataNode 获取该块的其他可用副本。

3.元数据的磁盘故障

FsImageEditLog 是 HDFS 的核心数据,这些数据的意外丢失可能会导致整个 HDFS 服务不可用。为了避免这个问题,可以配置 NameNode 使其支持 FsImageEditLog 多副本同步,这样 FsImageEditLog 的任何改变都会引起每个副本 FsImageEditLog 的同步更新。

4.支持快照

快照支持在特定时刻存储数据副本,在数据意外损坏时,可以通过回滚操作恢复到健康的数据状态。

HDFS 的组件

HDFS 包含 NameNode、DataNode、SecondaryNameNode 三个组件。

1. NameNode(名称节点)

用来管理文件系统的命名空间,负责记录文件是如何分割成数据块,以及这些数据块分别被存储到哪些数据节点上。

  1. 维护 HDFS 文件系统,是 HDFS 的主节点。
  2. 接受客户端(命令行、Java程序)的请求: 创建目录、上传数据、下载数据、删除数据等。
  3. 管理和维护HDFS的日志和元信息。
    • 第一次启动 NameNode 格式化后,创建 edits 和 fsimage 文件。如果不是第一次启动,直接加载 edits 日志和 fsimage 文件到内存。

    • 日志文件(edits文件):记录的是客户端的所有操作,存放HDFS文件系统的所有更新操作的路径,文件系统客户端执行的所有写操作首先会被记录到edits文件中,同时体现了HDFS的最新的状态。

      (*)而日志 edits文件 保存在我们配置的数据块目录中:由 hadoop.tmp.dir 参数指定。路径:$hadoop.tmp.dir/dfs/name/current

      edit-20200505

      (*)使用 hdfs oev -i 命令查看 edit日志输出为 XML 文件:

      # 举个栗子
      hdfs dfs -mkdir /edit_log
      hdfs oev -i edits_inprogress_0000000000000000070 -o /tmp/log.xml
      

      edit_log_20200505

    • 元信息文件(fsimage文件):记录的是数据块的位置信息、数据块的冗余信息。

      (*)保存目录: $hadoop.tmp.dir/dfs/name/current

      fsimges-20200505

      (*)使用 hdfs oiv -i 命令将 fsimges 日志输出为 XML

      # 举个栗子
      hdfs oiv -i fsimage_0000000000000000069 -o ~/tmp/fsimage.xml -p XML
      

      blog-size-20200505

    • 每次 NameNod 启动的时候都会将 fsimage 文件读入内存,加载 edits 里面的所有操作,保证内存中的元数据信息是最新的、同步的,可以看成 NameNode 启动的时候就将 fsimage 和 edits 文件进行了合并。

2. DataNode(数据节点)

文件系统的数据节点,根据需要存储和检索数据块,并定期向 NameNode 发送他们所存储的块列表。

  1. 以数据块为单位,保存数据。

    1. Hadoop 1.x 的数据块大小: 64M。
    2. Hadoop 2.x 的数据块大小:128M。
    3. Hadoop 3.x 的数据块大小:128M。
  2. 数据保存的目录:由 hadoop.tmp.dir 参数指定。如:

    /usr/software/hadoop-2.10.0/tmp/dfs/data/current/BP-1940172841-192.168.3.11-1588315718387/current/finalized/subdir0/subdir0
    

    已文件的文件的形式进行保存(blk_***)

    datanode-blok-20200505

  3. 在全分布模式下,至少两个 DataNode 节点。

3. SecondaryNameNode(第二名称节点)

与 NameNode 进行通讯,定期保存 HDFS 元数据的快照,用以备份和恢复数据等操作,其中一个主要作用是进行日志的合并。

  1. SecondaryNameNode 询问 NameNode 是否需要 checkpoint。直接带回 NameNode 是否检查结果。
  2. SecondaryNameNode 请求执行 checkpoint。
  3. NameNode 滚动正在写的 edits 日志。
  4. 将滚动前的编辑日志和镜像文件拷贝到 SecondaryNameNode。
  5. SecondaryNameNode 加载编辑日志和镜像文件到内存,并合并。
  6. 生成新的镜像文件 fsimage.chkpoint。
  7. 拷贝 fsimage.chkpoint 到 NameNode。
  8. NameNode 将 fsimage.chkpoint 重新命名成 fsimage。

4. Checkpoint 时间检查点设置

  1. 通常情况下,SecondaryNameNode每隔一小时执行一次。对应的配置文件:hdfs-default.xml
<property>
    <name>dfs.namenode.checkpoint.period</name>
    <value>3600</value>
</property>
  1. 一分钟检查一次操作次数,当操作次数达到1百万时,SecondaryNameNode执行一次。
<property>
    <name>dfs.namenode.checkpoint.txns</name>
    <value>1000000</value>
    <description>操作动作次数</description>
</property>

<property>
    <name>dfs.namenode.checkpoint.check.period</name>
    <value>60</value>
    <description> 1分钟检查一次操作次数</description>
</property>

5. 总结

在 NameNode节点上,fsimage 保存了元数据镜像文件,而 edits中完整记录了元数据的操作日志(针对文件系统做得修改操作记录)。NameNode 内存中存储的元数据可以用“fsimage+edits”来表达。而 SecondaryNameNode 负责定时(默认1小时 或 数据达到配置量时)从 NameNode 上获取 fsimage 和 edits进行合并,然后在发送给 NameNode,减少 NameNode 的工作量。

上次更新: 2020-5-10 1:34:13 PM