原文:http://hadoop.apache.org/docs/r2.6.4/hadoop-project-dist/hadoop-hdfs/HdfsSnapshots.html
概述
HDFS快照是文件系统在某个时刻的只读副本。快照可以是文件系统的一个子树,也可以是整个文件系统。快照的一些通用用途包含数据备份,出错保护和容灾恢复。
HDFS快照的实现是高效的:
- 快照创建瞬时性:除去inode的查询时间,算法消耗O(1)复杂度。
- 只有在对快照修改时才会消耗额外内存:内存使用O(M),M是被修改的文件或者目录数。
- DataNode的block不被复制:快照文件记录block列表和文件大小。不做数据的拷贝复制。
- 快照不会对正常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
注意一下这个例子使用了保留选项来保留timestamps,ownership,permission,ACL和XAttrs。
使用快照升级HDFS的版本
HDFS快照的特种引入一个新的保留路径.snapshot
,用来和快照交互。当从一个老版本升级HDFS时,如果已经存在.snapshot
目录,那么需要先删除或者重命名以避免冲突。详细参见HDFS的一些概念
快照操作
管理员操作
下面的操作需要超级用户权限。
允许快照
允许创建一个目录的快照。如果该操作成功,那么目录变为可快照的。
- 命令:
hdfs dfsadmin -allowSnapshot
-
参数:
|参数|描述| |---|---| |path| 可快照的目录路径。|
可以参考对应的Java API,
HdfsAdmin
类下面的void allowSnapshot(Path path)
方法。
禁止快照
禁止创建一个目录的奎照。在禁止快照前,该目录下已有的快照需要被删除。
- 命令:
hdfs dfsadmin -disallowSnapshot
-
参数:
|参数|描述| |---|---| |path| 可快照的目录路径。|
可以参考对应的Java API,
HdfsAdmin
类下面的void disallowSnapshot(Path path)
方法。
用户操作
这一部分描述用户操作。注意HDFS超级用户可以进行任何操作。
创建快照
为一个可快照的目录创建一个快照。该操作需要可快照目录的owner权限。
- 命令:
hdfs dfs -createSnapshot []
-
参数:
|参数|描述| |---|---| |path| 可快照的目录路径。| |snapshotName|快照名称,这是个可选参数。如果没有提供,系统会生成一个默认的名字,该名字使用时间戳,按照格式“'s'yyyyMMdd-HHmmss.SSS”来生成,例如“s20130412-151029.033”。|
可以参考对应的Java API,FileSystem
类下面的Path createSnapshot(Path path)
方法和Path createSnapshot(Path path, String snapshotName)
方法。这些方法会返回快照的路径。
删除快照
从一个可快照的目录删除一个快照。该操作需要可快照目录的owner权限。
- 命令:
hdfs dfs -deleteSnapshot
-
参数:
|参数|描述| |---|---| |path| 可快照的目录路径。| |snapshotName| 快照名称。|
可以参考对应的Java API,
FileSystem
类下面的void deleteSnapshot(Path path, String snapshotName)
方法。
重命名快照
重命名一个快照。该操作需要可快照目录的owner权限。
- 命令:
hdfs dfs -renameSnapshot
-
参数:
|参数|描述| |---|---| |path| 可快照的目录路径。| |oldName| 老快照名| |newName| 新快照名|
可以参考对应的Java API,
FileSystem
类下面的void renameSnapshot(Path path, String oldName, String newName)
方法。
获取可快照目录列表信息
获取当前用户有权限创建快照的所有可快照目录的列表。
- 命令:
hdfs lsSnapshottableDir
- 参数:无
可以参考对应的Java API,DistributedFileSystem
类下面的SnapshottableDirectoryStatus[] getSnapshottableDirectoryListing()
方法。
获取快照的差异报告
获取两个快照之间的差异。这个操作需要两个快照所有文件和目录的读访问权限。
- 命令:
hdfs snapshotDiff
-
参数:
|参数|描述| |---|---| |path| 可快照的目录路径。| |fromSnapshot| 对比源快照名。| |toSnapshot| 对比目的快照名。|
-
结果:
|状态|描述| |---|---| |+| 文件或目录被创建。| |-| 文件或目录被删除。| |M| 文件或目录被修改。| |R| 文件或目录被重命名。|
一个RENAME的项表明一个文件或目录被重命名过,但是仍在同一个可快照目录下。一个文件或目录如果被重命名到可快照目录外面,那么被认为删除。一个文件或目录如果从可快照目录外重命名到可快照目录内,那么会被认为是新建。
快照差别报告不保证操作顺序。举例来说,如果我们重命名一个目录“/foo”为“/foo2”,然后添加一个新文件为“/foo2/bar”,那么差别报告会是:
R. /foo -> /foo2
M. /foo/bar
这种顺序不保证体现在,在重命名目录下的文件或目录变动会被认为是在目录重命名前完成的(比如上面的例子)。可以参考对应的Java API,DistributedFileSystem
类下面的SnapshotDiffReport getSnapshotDiffReport(Path path, String fromSnapshot, String toSnapshot)
方法。