MHuiG

「看庭前花开花落,望天上云卷云舒」

HDFS 架构

# 大数据处理技术 - HDFS 的架构

## 基础架构

1、 `NameNode` 是一个中心服务器，单一节点（简化系统的设计和实现），负责管理文件系统的名字空间 `namespace` 以及客户端对文件的访问
2、 文件操作，`namenode` 是负责文件元数据的操作，`datanode` 负责处理文件内容的读写请求，跟文件内容相关的数据流不经过 `Namenode`，只询问它跟哪个 `dataNode` 联系，否则 `NameNode` 会成为系统的瓶颈
3、 副本存放在哪些 `Datanode` 上由 `NameNode` 来控制，根据全局情况作出块放置决定，读取文件时 `NameNode` 尽量让用户先读取最近的副本（网络拓扑图），降低读取网络开销和读取延时
4、 `NameNode` 全权管理数据库的复制（永远保证有三个副本），它周期性的从集群中的每个 `DataNode` 接收心跳信合和状态报告，接收到心跳信号意味着 `DataNode` 节点工作正常，块状态报告包含了一个该 `DataNode` 上所有的数据列表

NameNode 与 Datanode 的总结概述

NameNode | Datanode
--- | ---
存储元数据 | 存储文件内容
元数据存储在 内存中 | 文件内容存储在硬盘上
保存文件、block、DataNode 之间的映射关系 | 维护了 block id 到 DataNode 本地文件之间的映射关系

文件划了几个 block 块，存在那些个 DataNode 上

## 文件的文件副本机制以及 block 块存储

所有的文件都是以 `block` 块的方式存放在 `HDFS` 文件系统当中，在 hadoop1 当中，文件的 `block` 块默认大小是 `64M`，hadoop2 当中，文件的 `block` 块大小默认是 `128M`，`block` 块的大小可以通过 `hdfs-site.xml` 当中的配置文件进行指定

    <property>
      <name>dfs.block.size</name>
      <value>块大小 以字节为单位</value> <!-- 只写数值就可以 -->
    </property>

## 元数据信息 FSimage 以及 edits 和 secondaryNN 的作用

在 hadoop 当中，使用如下架构的时候

也就是 `namenode` 就一个的时候，所有的元数据信息都保存在了 `FsImage` 与 `Eidts` 文件当中，这两个文件就记录了所有的数据的元数据信息，元数据信息的保存目录配置在了 `hdfs-site.xml` 当中

    <property>
      <name>dfs.namenode.name.dir</name>
      <value>file:///export/servers/hadoop-2.6.0-cdh5.14.0/hadoopDatas/namenodeDatas</value>
    </property>
    <property>
      <name>dfs.namenode.edits.dir</name>
      <value>file:///export/servers/hadoop-2.6.0-cdh5.14.0/hadoopDatas/dfs/nn/edits</value>
    </property>

### FSImage 与 edits 详解

客户端对 `hdfs` 进行写文件时会首先被记录在 `edits` 文件中。`edits` 修改时元数据也会更新。每次 `hdfs` 更新时 `edits` 先更新后客户端才会看到最新信息。

`fsimage`: 是 namenode 中关于元数据的镜像，一般称为检查点。

一般开始时对 namenode 的操作都放在 edits 中，为什么不放在 fsimage 中呢？
因为 `fsimage` 是 namenode 的完整的镜像，内容很大，如果每次都加载到内存的话生成树状拓扑结构，这是非常耗内存和 CPU。

`fsimage` 内容包含了 namenode 管理下的所有 datanode 中文件及文件 block 及 block 所在的 datanode 的元数据信息。随着 edits 内容增大，就需要在一定时间点和 `fsimage` 合并。

合并过程见 SecondaryNameNode 如何辅助管理 FSImage 与 edits

### FSimage 文件当中的文件信息查看

官方查看文档
https://hadoop.apache.org/docs/r2.6.0/hadoop-project-dist/hadoop-hdfs/HdfsImageViewer.html

使用命令 `hdfs oiv`

    cd /export/servers/hadoop-2.6.0-cdh5.14.0/hadoopDatas/namenodeDatas/current
    hdfs oiv -i fsimage_0000000000000000150 -p XML -o qlg.xml

（md5 校验文件，不是真正文件）

### edits 当中的文件信息查看

官方查看文档
https://hadoop.apache.org/docs/r2.6.0/hadoop-project-dist/hadoop-hdfs/HdfsEditsViewer.html

查看命令 `hdfs oev`

    cd /export/servers/hadoop-2.6.0-cdh5.14.0/hadoopDatas/dfs/nn/edits
    hdfs oev -i edits_inprogress_0000000000000000001 -o slg.xml -p XML

### secondarynameNode 如何辅助管理 FSImage 与 Edits 文件

- 1: `secnonaryNN` 通知 `NameNode` 切换 `editlog`
- 2: `secondaryNN` 从 `NameNode` 中获得 `FSImage` 和 `editlog` (通过 `http` 方式)
- 3: `secondaryNN` 将 `FSImage` 载入内存，然后开始合并 `editlog`，合并之后成为新的 `fsimage`
- 4: `secondaryNN` 将新的 `fsimage` 发回给 `NameNode`
- 5: `NameNode` 用新的 `fsimage` 替换旧的 `fsimage`

完成合并的是 `secondarynamenode`，会请求 namenode 停止使用 edits, 暂时将新写操作放入一个新的文件中 `edits.new`。
`secondarynamenode` 从 namenode 中通过 http get 获得 edits，因为要和 fsimage 合并，所以也是通过 http get 的方式把 fsimage 加载到内存，然后逐一执行具体对文件系统的操作，与 fsimage 合并，生成新的 fsimage，然后把 fsimage 发送给 namenode，通过 http post 的方式。namenode 从 secondarynamenode 获得了 fsimage 后会把原有的 fsimage 替换为新的 fsimage, 把 edits.new 变成 edits。同时会更新 fstime。
hadoop 进入安全模式时需要管理员使用 dfsadmin 的 save namespace 来创建新的检查点。
secondarynamenode 在合并 edits 和 fsimage 时需要消耗的内存和 namenode 差不多，所以一般把 namenode 和 secondarynamenode 放在不同的机器上。
`fs.checkpoint.period`: 默认是一个小时（`3600s`)
`fs.checkpoint.size`: edits 达到一定大小时也会触发合并（默认 `64MB`)

## HDFS 的文件写入过程

详细步骤解析：

- 1、 client 发起文件上传请求，通过 RPC 与 NameNode 建立通讯，NameNode 检查目标文件是否已存在，父目录是否存在，返回是否可以上传；
- 2、 client 请求第一个 block 该传输到哪些 DataNode 服务器上；
- 3、 NameNode 根据配置文件中指定的备份数量及机架感知原理进行文件分配，返回可用的 DataNode 的地址如：A，B，C；注：Hadoop 在设计时考虑到数据的安全与高效，数据文件默认在 HDFS 上存放三份，存储策略为本地一份，同机架内其它某一节点上一份，不同机架的某一节点上一份。
- 4、 client 请求 3 台 DataNode 中的一台 A 上传数据（本质上是一个 RPC 调用，建立 pipeline），A 收到请求会继续调用 B，然后 B 调用 C，将整个 pipeline 建立完成，后逐级返回 client；
- 5、 client 开始往 A 上传第一个 block（先从磁盘读取数据放到一个本地内存缓存），以 packet 为单位（默认 64K），A 收到一个 packet 就会传给 B，B 传给 C；A 每传一个 packet 会放入一个应答队列等待应答。
- 6、 数据被分割成一个个 packet 数据包在 pipeline 上依次传输，在 pipeline 反方向上，逐个发送 ack（命令正确应答），最终由 pipeline 中第一个 DataNode 节点 A 将 pipelineack 发送给 client;
- 7、 当一个 block 传输完成之后，client 再次请求 NameNode 上传第二个 block 到服务器。

## HDFS 的文件读取过程

详细步骤解析

- 1、 Client 向 NameNode 发起 RPC 请求，来确定请求文件 block 所在的位置；
- 2、NameNode 会视情况返回文件的部分或者全部 block 列表，对于每个 block，NameNode 都会返回含有该 block 副本的 DataNode 地址； 这些返回的 DN 地址，会按照集群拓扑结构得出 DataNode 与客户端的距离，然后进行排序，排序两个规则：网络拓扑结构中距离 Client 近的排靠前；心跳机制中超时汇报的 DN 状态为 TALE，这样的排靠后；
- 3、 Client 选取排序靠前的 DataNode 来读取 block，如果客户端本身就是 DataNode, 那么将从本地直接获取数据 (短路读取特性)；
- 4、 底层上本质是建立 `Socket Stream`（`FSDataInputStream`），重复的调用父类 `DataInputStream` 的 read 方法，直到这个块上的数据读取完毕；
- 5、 当读完列表的 block 后，若文件读取还没有结束，客户端会继续向 NameNode 获取下一批的 block 列表；
- 6、 读取完一个 block 都会进行 checksum 验证，如果读取 DataNode 时出现错误，客户端会通知 NameNode，然后再从下一个拥有该 block 副本的 DataNode 继续读。
- 7、 read 方法是并行的读取 block 信息，不是一块一块的读取；NameNode 只是返回 Client 请求包含块的 DataNode 地址，并不是返回请求块的数据；
- 8、 最终读取来所有的 block 会合并成一个完整的最终文件。

大数据处理技术-HDFS的命令行使用

HDFS 命令行 大数据处理技术 - HDFS 的命令行使用 hdfs 常用的操作命令查看根路径下面的文件或者文件夹 hdfs dfs -ls / 查看 test 路径下面的文件或者文...

大数据处理技术-HDFS的JavaAPI操作

HDFS JavaAPI 大数据处理技术 - HDFS 的 JavaAPI 操作 创建 maven 工程并导入 jar 包由于 cdh 版本的所有的软件涉及版权的问题，所以并没有将所有的...

留言区

Notes
Hadoop
本文目录
<pjax>
</pjax>
<pjax></pjax>
<pjax> Are you Robot?</pjax>