HDFS 快照
概述
HDFS 快照是只读的某个时间点的文件系统拷贝。可以在一个子树或者整个文件系统上执行快照。一般使用快照的场景有数据备份、防止用户错误及灾难恢复。
HDFS 快照的实现是很有效的:
- 快照的创建是瞬间的:代价是 O(1),除了索引点(inode)查找时间。
- 只有发生跟快照相关的修改时才需要额外的内存:内存使用是 O(M),M 是修改的文件/目录的数目。
- DataNode 上的块不会拷贝:快照文件记录块列表及文件的大小。不会拷贝数据。
- 快照不会对常规的 HDFS 操作有不利的影响:修改是以时间倒序排列的,因此当前的数据可以直接访问。快照数据是通过从当前数据减去修改来计算的。
快照表目录
快照表可以在任何目录上创建,只要目录被设置为快照表。一个快照表目录可以同时容纳 65536 个快照。快照表目录的数量没有限制。管理员可以设置任何目录为快照表。如果一个快照表目录下存在快照,那么这个目录在所有的快照被删除前不能被删除也不能重命名。嵌套的快照表目录当前是不允许的。就是说,如果一个目录的一个上级目录/下级目录是快照表目录,那么这个目录不能被设置为快照表。
快照路径
对于一个快照表目录,路径组件“.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
注意,这个例子使用了保持选项保持时间戳、属主关系、权限、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:结束快照的名称。
- 结果:
+:文件/目录被创建。
−:文件/目录被删除。
M:文件/目录被修改。
R:文件/目录被重命名。
重命名实体表明一个文件/目录被重命名但依然在同一个快照表目录中。如果一个文件/目录被重命名到快照表目录的外部,那么这个文件/目录报告为被删除。一个文件/目录从外部重命名到快照表中会报告为新创建。
快照差异报告不保证相同的操作序列。例如,重命名目录“/foo”为“/foo2”,然后向文件“/foo2/bar”追加数据,差异报告将是:
R. /foo -> /foo2
M. /foo/bar
换言之,被重命名目录下的文件/目录的修改会用被重名前原来的路径报告(上面例子中的“/foo/bar”)。
也可以参见 DistributedFileSystem 中对应的 Java API SnapshotDiffReport getSnapshotDiffReport(Path path, String fromSnapshot, String toSnapshot)。