HDFS 快照

概述

HDFS 快照是文件系统的只读时间点副本。可以在文件系统子树或整个文件系统上创建快照。快照的一些常见用例是数据备份、防止用户错误和灾难恢复。

HDFS 快照的实现非常高效

  • 快照创建是即时的:成本为 O(1)(不包括 inode 查找时间)。

  • 仅当相对于快照进行修改时才使用额外的内存:内存使用量为 O(M),其中 M 是已修改的文件/目录的数量。

  • 数据节点中的块不会被复制:快照文件记录块列表和文件大小。没有数据复制。

  • 快照不会对常规 HDFS 操作造成不利影响:修改记录按时间倒序,以便可以直接访问当前数据。快照数据通过从当前数据中减去修改计算得出。

可快照目录

一旦目录被设置为可快照,就可以对任何目录进行快照。可快照目录可以容纳 65,536 个同时快照。可快照目录的数量没有限制。管理员可以将任何目录设置为可快照。如果可快照目录中存在快照,则在删除所有快照之前,不能删除或重命名该目录。

目前不允许嵌套可快照目录。换句话说,如果其祖先/后代之一是可快照目录,则不能将目录设置为可快照。

快照路径

对于可快照目录,路径组件“.snapshot”用于访问其快照。假设 /foo 是一个可快照目录,/foo/bar/foo 中的一个文件/目录,并且 /foo 有一个快照 s0。那么,路径 /foo/.snapshot/s0/bar 指向 /foo/bar 的快照副本。通常的 API 和 CLI 可以使用“.snapshot”路径。以下是一些示例。

  • 列出可快照目录下的所有快照

    hdfs dfs -ls /foo/.snapshot
    
  • 列出快照 s0 中的文件

    hdfs dfs -ls /foo/.snapshot/s0
    
  • 从快照 s0 复制文件

    hdfs dfs -cp -ptopax /foo/.snapshot/s0/bar /tmp
    

    请注意,此示例使用 preserve 选项来保留时间戳、所有权、权限、ACL 和 XAttr。

升级到具有快照功能的 HDFS 版本

HDFS 快照功能引入了一个新的保留路径名称,用于与快照交互:.snapshot。从不支持快照的较旧版本 HDFS 升级时,需要首先重命名或删除名为 .snapshot 的现有路径,以避免与保留路径冲突。有关更多信息,请参阅HDFS 用户指南中的升级部分。

快照操作

管理员操作

本节中描述的操作需要超级用户权限。

允许快照

允许创建目录快照。如果操作成功完成,则该目录将变为可快照。

  • 命令

    hdfs dfsadmin -allowSnapshot <path>
    
  • 参数

    path 可快照目录的路径。

另请参阅 HdfsAdmin 中相应的 Java API void allowSnapshot(Path path)

禁止快照

禁止创建目录的快照。必须在禁止快照之前删除该目录的所有快照。

  • 命令

    hdfs dfsadmin -disallowSnapshot <path>
    
  • 参数

    path 可快照目录的路径。

另请参阅 HdfsAdmin 中的相应 Java API void disallowSnapshot(Path path)

用户操作

本节介绍用户操作。请注意,HDFS 超级用户可以在不满足各个操作中权限要求的情况下执行所有操作。

创建快照

创建可快照目录的快照。此操作需要可快照目录的所有者权限。

  • 命令

    hdfs dfs -createSnapshot <path> [<snapshotName>]
    
  • 参数

    path 可快照目录的路径。
    snapshotName 快照名称,这是一个可选参数。如果省略,则使用格式为 "'s'yyyyMMdd-HHmmss.SSS" 的时间戳生成默认名称,例如 "s20130412-151029.033"

另请参阅 FileSystem 中的相应 Java API Path createSnapshot(Path path)Path createSnapshot(Path path, String snapshotName)。这些方法中返回了快照路径。

删除快照

从可快照目录中删除快照。此操作需要可快照目录的所有者权限。

  • 命令

    hdfs dfs -deleteSnapshot <path> <snapshotName>
    
  • 参数

    path 可快照目录的路径。
    snapshotName 快照名称。

另请参阅 FileSystem 中的相应 Java API void deleteSnapshot(Path path, String snapshotName)

重命名快照

重命名快照。此操作需要可快照目录的所有者权限。

  • 命令

    hdfs dfs -renameSnapshot <path> <oldName> <newName>
    
  • 参数

    path 可快照目录的路径。
    oldName 旧快照名称。
    newName 新快照名称。

另请参阅 FileSystem 中的相应 Java API void renameSnapshot(Path path, String oldName, String newName)

获取可快照目录列表

获取当前用户有权对其进行快照的所有可快照目录。

  • 命令

    hdfs lsSnapshottableDir
    
  • 参数:无

另请参阅 DistributedFileSystem 中的相应 Java API SnapshottableDirectoryStatus[] getSnapshottableDirectoryListing()

获取快照差异报告

获取两个快照之间的差异。此操作需要对两个快照中所有文件/目录的读取访问权限。

  • 命令

    hdfs snapshotDiff <path> <fromSnapshot> <toSnapshot>
    
  • 参数

    path 可快照目录的路径。
    fromSnapshot 起始快照的名称。
    toSnapshot 结束快照的名称。

    请注意,snapshotDiff 可用于获取两个快照之间的差异报告,或快照与目录的当前状态之间的差异报告。用户可以使用 “.” 来表示当前状态。

  • 结果

    + 文件/目录已创建。
    - 文件/目录已删除。
    M 文件/目录已修改。
    R 文件/目录已重命名。

RENAME 条目表示文件/目录已重命名,但仍位于同一可快照目录下。如果文件/目录被重命名到可快照目录外部,则报告为已删除。从可快照目录外部重命名的文件/目录报告为新创建的。

快照差异报告不保证相同的操作顺序。例如,如果我们将目录 “/foo” 重命名为 “/foo2”,然后向文件 “/foo2/bar” 追加新数据,则差异报告将为

R. /foo -> /foo2
M. /foo/bar

即,重命名目录下的文件/目录的更改使用重命名之前的原始路径报告(在上述示例中为 “/foo/bar”)。

另请参阅 DistributedFileSystem 中相应的 Java API SnapshotDiffReport getSnapshotDiffReport(Path path, String fromSnapshot, String toSnapshot)