03. Hadoop 2.x 新特性

Par @Martin dans le
Tags :

Hadoop 1.x 问题

主要就是 NameNode 单点问题.

Hadoop 1.x 中, 一个集群就只有一个 NameNode, 这种架构虽然实现简单, 但会产生单点内存瓶颈、性能 瓶颈等限制.

首先, 整个 Hadoop 集群的命名空间都归一个 NameNode 管理, 这样 HDFS 所能存储的文件数量会受到 NameNode 容量的限制;

其次, 当集群进行复杂运算时, 也只有一个 NameNode 在运作, 集群的运算性能也会受到 NameNode 的限制.

最后, 虽然集群有 Second NameNode 作为辅助节点, 但并不会完成自动切换, 当 NameNode 宕掉时, 还是需要人工去处理.

虽然仅仅在像 Yahoo 和 Facebook 返种规模的大公司才会面对这样的限制问题, 但在 Hadoop 2.x 中, 官方还是给出了解决方案.

Hadoop 2.x 解决方案

Hadoop 2.x 提出了两个新特性用以解决以上问题:

  • HDFS 联邦
  • HDFS HA

Reference: 2.X 高可靠 HA 及 Federation (联盟)

HDFS 快照

在 2.x 终于实现了快照.

快照的作用是什么?

HDFS 2.x 中现在可以对目录创建 Snapshot, 创建之后不管后续目录发生什么变化, 都可以通过 snapshot 找回原来的文件和目录结构.

为了启用这种功能, 首先需要启用目标目录的 snapshot 功能, 可以通过 hdfs dfsadmin -allowSnapshot 命令来启用 snapshot 功能, 启用后, 并不会自动进行 snapshot 保存, 还需要先对现场手动创建一次 snapshot, 通过下面的命令来执行: hdfs dfs -createSnapshot [].

可以为相同的目录创建多个 snapshot, 不同的 snapshot 通过名字来区分, 默认是 syyyyMMdd-HHmmss.SSS, 例如 /storage/WALs/.snapshot/s20140515-084657.639.

实现原理

实现上是通过在每个目标节点下面创建 snapshot 节点, 后续任何子节点的变化都会同步记录到 snapshot 上. 例如删除子节点下面的文件, 并不是直接文件元信息以及数据删除, 而是将他们移动到 snapshot 下面. 这样后续还能够恢复回来.

另外 snapshot 保存是一个完全的现场, 不仅是删除的文件还能找到, 新创建的文件也无法看到. 后一种效果的实现是通过在 snapshot 中记录哪些文件是新创建的, 查看列表的时候将这些文件排除在外.

在 HDFS 中 INode 表示一个节点, 其中 INodeFile 表示文件, INodeDirectory 表示目录. INodeFileWithSnapshot 表示带有快照的文件, INodeDirectoryWithSnapshot 表示带有快照的目录, (INodeDirectorySnapshottable 表示可以创建快照的目录, INodeDirectoryWithSnapshot 不能创建新的快照, 只能将目录的变化记录到现有的快照里面) 相关的类结构如下:

图中红线表示的是关键类的引用关系, 其中最重要的是 DirectoryDiffList, 里面保存了一些快照和当前目录的差别. 每一个 DirectoryDiff 中包含快照以及儿子变化, 是实现快照功能的核心. ChilderenDiff 中 created list 保存的是从快照时间之后新创建的节点, deteled list 保存的新删除的节点. snapshot 中的 root 节点保存了 snapshot 的 name, 可以通过这个找到对应的快照.

例子分析

我们通过一个例子来分析整个 snapshot 的实现细节:

1. 文件目录树如下图所示, 并且我们已经通过命令启动了 a 的 snapshot 功能, 结构如下图所示:

图中 .snapshot 是虚拟节点, 保存了所有的 snapshot 列表, 其中 diff 中还保存当前节点下面的变化, 一个 snapshot 对应于一个 diff. 要注意的是 snapshot 中可以被多个目录的 diff 引用, 后续会进行说明.

2. 当我们执行 createSnapshot 命令时, 结果如下:

3. 当删除文件 e 的时候, 不论是删除一个文件还是一个目录, 只要是直接子节点, 都会将节点转换为快照版本. 例如 e 会变成 INodeFileWithSnapshot, 在 a 的 DirectoryDiff 中 ChildDiff 中 deleted 列表中将会包含 e, 而在 a 的正常节点下会被删除. 目录节点的处理同样.

4. 删除孙子节点是的情况

处理这种节点的原则是: 先将孙子节点转变为 Snapshot 版本, 然后将父节点变为 snapshot 版本, 同时将孙子节点版本加入到直接父节点的 diff 列表中. 为了能够通过同一个 snapshot 找到当时的文件, 需要将新的 diff 指向到老的 snapshot 版本上. 图中 d 节点是 INodeDirectoryWithSnapshot (不是 INodeDiretorySnapshottable, 本身不允许在 d 上创建 snapshot).

快照命令

  • 设置一个目录为可快照:
    • hdfs dfsadmin -allowSnapshot <path>
  • 取消目录可快照:
    • hdfs dfsadmin -disallowSnapshot <path>
  • 生成快照:
    • hdfs dfs -createSnapshot <path> [<snapshotName>]
  • 删除快照:
    • hdfs dfs -deleteSnapshot <path> <snapshotName>
  • 列出所有可快照目录:
    • hdfs lsSnapshottableDir
  • 比较快照之间的差异:
    • hdfs snapshotDiff <path> <fromSnapshot> <toSnapshot>

Refrences

HDFS snapshot 占用空间吗
HDFS Snapshot 原理
HDFS 快照管理