写点什么

用 DeBug 的方式,带你掌握 HBase 文件在 Snapshot 的各种变化

发布于: 2021 年 04 月 02 日

摘要:掌握 Snapshot 可以帮助我们很好的完成 HBase 数据备份和数据迁移的工作。


本文分享自华为云社区《看看HBase Snapshot中表的文件是怎样变化的》,原文作者:Lettle whale 。

简介


HBase 的 Snapshot 功能可以在不复制数据的情况下,快速克隆一张表,完成一次数据备份。通过 Snapshot,我们在做应用升级之前生成一个快照,后续如果遇到问题可以快速回滚到快照点。Snapshot 过程不涉及底层数据文件的拷贝和移动,只是对文件做了记录,保存了一份原始文件的指针记录,所以非常迅速,掌握 Snapshot 可以帮助我们很好的完成 HBase 数据备份和数据迁移的工作。

快照文件


● 对一个表“mytable“,执行快照命令


hbase(main):078:0> snapshot 'mytable','snapshot-test'0 row(s) in 1.1110 seconds
复制代码


● 在 HDFS 目录下.hbase-snapshot 中会生成一个生成一个以快照名字“snapshot-test”命名的 snapshot 文件夹


(本文 HDFS 中 hbase 的根目录为/d-hbase)


./hdfs dfs -ls /d-hbase/.hbase-snapshotFound 2 itemsdrwxr-xr-x   - root supergroup    /d-hbase/.hbase-snapshot/.tmpdrwxr-xr-x   - root supergroup    /d-hbase/.hbase-snapshot/snapshot-test
复制代码


● Region 的所有元数据及 HFile 信息会记录到 snapshot 文件夹中,文件夹中有 2 个文件,其中.snapshotinfo 为 snapshot 基本信息,包含表名称和 snapshot 名,data.manifest 为 snapshot 执行后生成的元数据信息,里面包含了表的 schema 信息,region 信息,以及 HFile 指针


./hdfs dfs -ls /d-hbase/.hbase-snapshot/snapshot-testFound 2 items-rw-r--r--   1 root supergroup    /d-hbase/.hbase-snapshot/snapshot-test/.snapshotinfo-rw-r--r--   1 root supergroup    /d-hbase/.hbase-snapshot/snapshot-test/data.manifest
复制代码


这里我们通过 Java 代码去解读这两个文件,参考 HBase 的工具类 ExportSnapshot.java 中对快照文件的解析代码


final List<Pair<SnapshotProtos.SnapshotFileInfo, Long>> files = new ArrayList<>();HBaseProtos.SnapshotDescription snapshotDesc = SnapshotDescriptionUtils.readSnapshotInfo(fs, snapshotDir);final TableName table = TableName.valueOf(snapshotDesc.getTable());SnapshotReferenceUtil.visitReferencedFiles(conf, fs, snapshotDir, snapshotDesc, (regionInfo, family, storeFile) -> {    if (!storeFile.hasReference()) {        String region = regionInfo.getEncodedName();        String hfile = storeFile.getName();        Path path = HFileLink.createPath(table, region, family, hfile);        SnapshotProtos.SnapshotFileInfo fileInfo = SnapshotProtos.SnapshotFileInfo.newBuilder().setType(SnapshotProtos.SnapshotFileInfo.Type.HFILE).setHfile(path.toString()).build();        long size;        if (storeFile.hasFileSize()) {            size = storeFile.getFileSize();        } else {            size = HFileLink.buildFromHFileLinkPattern(conf, path).getFileStatus(fs).getLen();        }
files.add(new Pair<>(fileInfo, size)); }});
复制代码


通过读取.snapshotinfo 得到了 snapshotDesc,这个对象中,主要包含了本次 snapshot 的 name 和 table



通过读取 data.manifest 得到了本次 Snapshots 涉及到哪些 region 以及关联的 HFile



这里解析出来的路径格式为 <列族>/<表名>=<reigon 名>-<HFile>


解析这个格式,就能得到 “表名”,“列族”,“region”,“HFile”,有了上述信息,就基本能够找到原始的 HFile 路径。这个 HFile 的位置可能在 data 目录下面,也可能在 archive 目录中,因为表进行过 major_compact,HFile 会进入 archive 目录下。所以 ExportSnapshot 工具在查找 snapshot 对应的 HFile 文件时,也是找的 data 目录或者 archive 目录。

Clone 表的 Snapshot


接下来看一下,对 clone_snapshot 复制出来的表再进行 snapshot 快照,表中的文件变化是怎样的


执行命令,使用 snapshot 复制出一张表“clone_table”


clone_snapshot 'snapshot-test', 'clone_table'
复制代码


查看 clone 出来的表的文件路径,可以看到这里的 HFile 其实是个链接文件,链接的是"mytable"表下的 eddf78bf298819342f48b8199b3e5269 这个 Region 的 5b089dc6f7ca4fb8932aa2899a85f9b2 文件


./hdfs dfs -ls /d-hbase/data/default/clone_table/9fe93242bd8a96c80f350f829504cba2/famFound 1 items-rw-r--r--   1 root supergroup         /d-hbase/data/default/clone_table/9fe93242bd8a96c80f350f829504cba2/fam/mytable=eddf78bf298819342f48b8199b3e5269-5b089dc6f7ca4fb8932aa2899a85f9b2
复制代码


此时观察原始表"mytable"的 archive 下,已经有一个 back-reference 文件,以.links-开头的


./hdfs dfs -ls /d-hbase/archive/data/default/mytable/eddf78bf298819342f48b8199b3e5269/famFound 1 itemsdrwxr-xr-x   - root supergroup         /d-hbase/archive/data/default/mytable/eddf78bf298819342f48b8199b3e5269/fam/.links-5b089dc6f7ca4fb8932aa2899a85f9b2
复制代码


如果此时对 clone 表,做 major_compact


major_compact 'clone_table'
复制代码


此时会生成一个新的 region 文件,这是一个真实的数据文件


./hdfs dfs -ls /d-hbase/data/default/clone_table/9fe93242bd8a96c80f350f829504cba2/famFound 2 items-rw-r--r--   1 root supergroup       5084  /d-hbase/data/default/clone_table/9fe93242bd8a96c80f350f829504cba2/fam/50a43588d8b145f89a46649d34ecea42-rw-r--r--   1 root supergroup          0  /d-hbase/data/default/clone_table/9fe93242bd8a96c80f350f829504cba2/fam/mytable=eddf78bf298819342f48b8199b3e5269-5b089dc6f7ca4fb8932aa2899a85f9b2
复制代码


那个链接文件“mytable=eddf78bf298819342f48b8199b3e5269-5b089dc6f7ca4fb8932aa2899a85f9b2”,被移除


./hdfs dfs -ls /d-hbase/data/default/clone_table/9fe93242bd8a96c80f350f829504cba2/famFound 1 items-rw-r--r--   1 root supergroup       5084  /d-hbase/data/default/clone_table/9fe93242bd8a96c80f350f829504cba2/fam/50a43588d8b145f89a46649d34ecea42
复制代码

表在 split 时的 Snapshot


接着对上面那个”clone_table“表进行 split,并在 split 过程中的同时执行 snapshot


split 'clone_table','3'snapshot 'clone_table','clone_table_snapshot'
复制代码


初始时,在 data 目录下,父 reigon 的目录 9fe93242bd8a96c80f350f829504cba2 目录仍然在,


./hdfs dfs -ls /d-hbase/data/default/clone_table/Found 5 itemsdrwxr-xr-x   - root supergroup          0  /d-hbase/data/default/clone_table/.tabledescdrwxr-xr-x   - root supergroup          0  /d-hbase/data/default/clone_table/.tmpdrwxr-xr-x   - root supergroup          0  /d-hbase/data/default/clone_table/4169b0c3083febcc11ed6e8e716d6f93drwxr-xr-x   - root supergroup          0  /d-hbase/data/default/clone_table/611efc98e1c72502a0c31536866c4ccedrwxr-xr-x   - root supergroup          0  /d-hbase/data/default/clone_table/9fe93242bd8a96c80f350f829504cba2
复制代码


分裂完成后,data 目录下的父 region 目录 9fe93242bd8a96c80f350f829504cba2 被移除


./hdfs dfs -ls /d-hbase/data/default/clone_table/Found 4 itemsdrwxr-xr-x   - root supergroup          0  /d-hbase/data/default/clone_table/.tabledescdrwxr-xr-x   - root supergroup          0  /d-hbase/data/default/clone_table/.tmpdrwxr-xr-x   - root supergroup          0  /d-hbase/data/default/clone_table/4169b0c3083febcc11ed6e8e716d6f93drwxr-xr-x   - root supergroup          0  /d-hbase/data/default/clone_table/611efc98e1c72502a0c31536866c4cce
复制代码


同时观察 archive 目录,一开始也是有父 reigon 和子 region 的目录,子 reigon 里面的文件是 split 产生的 reference 文件,链接的是父 reigon 的 HFile,都是“50a43588d8b145f89a46649d34ecea42-9fe93242bd8a96c80f350f829504cba2”


过了几分钟后,只剩下了父 reigon 的目录


./hdfs dfs -ls /d-hbase/archive/data/default/clone_table/9fe93242bd8a96c80f350f829504cba2/famFound 1 items-rw-r--r--   1 root supergroup       5084  /d-hbase/archive/data/default/clone_table/9fe93242bd8a96c80f350f829504cba2/fam/50a43588d8b145f89a46649d34ecea42
复制代码


此时,再通过之前的 java 代码分析 data.manifest 中的信息,



发现这里是包含父 Region 以及分裂后的 2 个子 Region 的 HFile 信息,且关联的子 Region 里的 HFile 也是分裂后真实存在的。


这里突然有个疑问,假如后面根据这个文件信息去恢复数据时,会不会重复去把父 Region 和子 Region 都去恢复,于是执行了 ExportSnapshot 命令,将 snapshot 对应的文件到导出来,导出来的也是包含这 3 个 Region 的真实数据文件,这表明此过程中的确会出现有重复数据文件的问题,虽然多个文件会包含同一份数据,不过对业务不会有影响,会随着后续 Compact 消除掉。


后续继续做了几次相同的试验,在 split 过程中执行 snapshot,data.manifest 中有时候出现 1 个父 Region 和 2 个子 Region 的信息,有时候出现 1 个父 Region 和 1 个子 Region 的信息,说明打快照是对表的 HFile 瞬时的记录,并不会特意去等待分裂完成。

了解快照文件的意义


可以基于快照的原理去开发 HBase 全量数据迁移工具,解析快照元数据,获得表的所有文件路径列表,从而不依赖 ExportSnapshot 工具,进行更灵活的文件迁移,将表的所有文件通过流的方式拷贝到目的集群 HDFS 中,进而可以使用 LoadIncrementalHFiles 这样的工具,将 HFile 装载到新的表中。


点击关注,第一时间了解华为云新鲜技术~


发布于: 2021 年 04 月 02 日阅读数: 90
用户头像

提供全面深入的云计算技术干货 2020.07.14 加入

华为云开发者社区,提供全面深入的云计算前景分析、丰富的技术干货、程序样例,分享华为云前沿资讯动态,方便开发者快速成长与发展,欢迎提问、互动,多方位了解云计算! 传送门:https://bbs.huaweicloud.com/

评论

发布
暂无评论
用DeBug的方式,带你掌握HBase文件在Snapshot的各种变化