综述
HDFS快照是一个只读的基于时间点文件系统拷贝。快照可以是整个文件系统的也可以是一部分。常用来作为数据备份,防止用户错误和容灾。
HDFS实现了:
- Snapshot 创建的时间 复杂度为O(1),但是不包括INode 的寻找时间
- 只有当修改SnapShot时,才会有额外的内存占用,内存使用量为O(M),M 为修改的文件或者目录数
- 在datanode 上面的blocks 不会复制,做Snapshot 的文件是纪录了block的列表和文件的大小,但是没有数据的复制
- Snapshot 并不会影响HDFS 的正常操作:修改会按照时间的反序记录,这样可以直接读取到最新的数据。快照数据是当前数据减去修改的部分计算出来的。
可以被快照的目录
快照会存储在snapshottable的目录下。snapshottable下存储的snapshots 最多为65535个。没有限制snapshottable目录的数量。管理员可以设置任何的目录成为snapshottable。如果snapshottable里面存着快照,那么文件夹不能删除或者改名。
网络的snapshottable目录现在是不允许的。另外如果一个目录的父目录或者子目录是snapshottable,那么这个文件夹不能作为snapshottable。
快照的目录
对于一个snapshottable文件夹,".snapshot" 被用于进入他的快照 /foo 是一个snapshottable目录,/foo/bar是一个/foo下面的文件目录,/foo有一个快照s0,那么路径就是
/foo/.snapshot/s0/bar
引用快照副本/foo/bar。常用的API和CLI能够在".snapshot" 的路径下运行。下面是一些例子。
列出snapshottable目录的所有快照
- hdfs dfs -ls /foo/.snapshot
列出在快照s0的所有文件
- hdfs dfs -ls /foo/.snapshot/s0
从s0拷贝一个文件:
- hdfs dfs -cp /foo/.snapshot/s0/bar /tmp
注意".snapshot"正在被前一个版本的HDFS使用,他必须在升级之前重命名,否则会升级失败。
操作
管理员操作
本节的操作需要超级用户权限。
快照可用
快照目录建立。如果这个操作成果,那么目录会变成snapshottable。
命令
- hdfs dfsadmin -allowSnapshot <path>
- 参数:
path | snapshottable目录路径. |
同时请参考在HdfsAdmin中 void allowSnapshot(Path path)的API。
快照不可用
文件夹里面的所有快照在失效快照前必须被删除,如果没有该目录会被建立。
命令:
- hdfs dfsadmin -disallowSnapshot <path>
- 参数:
path | snapshottable目录路径. |
同时请参考在HdfsAdmin中 void disallowSnapshot(Path path)的API。
用户操作
本小节描述用户操作。注意HDFS超级用户可以执行所有的操作除了有权限的需求的操作。
创建快照
snapshottable目录创建一个快照。这个操作需要snapshottable目录的权限。
命令
- hdfs dfs -createSnapshot <path> [<snapshotName>]
- 参数:
path | The path of the snapshottable directory. |
snapshotName | "'s'yyyyMMdd-HHmmss.SSS", 例如 "s20130412-151029.033". |
可以createSnapshot(Path path)和createSnapshot(Path path, String snapshotName)在文件系统中的API,方法的返回值是snapshot 路径
删除快照
从一个snapshottable目录删除的快照。这个操作需要snapshottable目录的权限。
命令:
- hdfs dfs -deleteSnapshot <path> <snapshotName>
- 参数:
path | The path of the snapshottable directory. |
snapshotName | 快照名字 |
参考FileSystem类void deleteSnapshot(Path path, String snapshotName)的API
重命名快照
重命名快照。这个命令也需要snapshottable目录的权限。
命令:
- hdfs dfs -renameSnapshot <path> <oldName> <newName>
- 参数:
path | The path of the snapshottable directory. |
oldName | 老的快照名字 |
newName | 新的快照名字 |
参考FileSystem类 void renameSnapshot(Path path, String oldName, String newName) 的API
snapshottable目录列表
获取当前用户的所有snapshottable。
命令:
- hdfs lsSnapshottableDir
- 参数: 无
参考DistributedFileSystem类 SnapshottableDirectoryStatus[] getSnapshottableDirectoryListing() 的API
获取快照差异报告
得到两个快照之间的不同。需要两个目录的权限。
命令:
- hdfs snapshotDiff <path> <fromSnapshot> <toSnapshot>
- 参数:
path | The path of the snapshottable directory. |
fromSnapshot | 开始的快照名字 |
toSnapshot | 结束的快照名字。 |
参考DistributedFileSystem类 SnapshotDiffReport getSnapshotDiffReport(Path path, String fromSnapshot, String toSnapshot) 的API