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

简介

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-snapshot
Found 2 items
drwxr-xr-x - root supergroup /d-hbase/.hbase-snapshot/.tmp
drwxr-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-test
Found 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/fam
Found 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/fam
Found 1 items
drwxr-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/fam
Found 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/fam
Found 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 items
drwxr-xr-x - root supergroup 0 /d-hbase/data/default/clone_table/.tabledesc
drwxr-xr-x - root supergroup 0 /d-hbase/data/default/clone_table/.tmp
drwxr-xr-x - root supergroup 0 /d-hbase/data/default/clone_table/4169b0c3083febcc11ed6e8e716d6f93
drwxr-xr-x - root supergroup 0 /d-hbase/data/default/clone_table/611efc98e1c72502a0c31536866c4cce
drwxr-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 items
drwxr-xr-x - root supergroup 0 /d-hbase/data/default/clone_table/.tabledesc
drwxr-xr-x - root supergroup 0 /d-hbase/data/default/clone_table/.tmp
drwxr-xr-x - root supergroup 0 /d-hbase/data/default/clone_table/4169b0c3083febcc11ed6e8e716d6f93
drwxr-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/fam
Found 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装载到新的表中。

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

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

用DeBug的方式,带你掌握HBase文件在Snapshot的各种变化的更多相关文章

  1. VC++ Debug编译方式

    字节填充 VC++在Debug编译方式下,new的内存用0xcd(助记词为Cleared Data)填充,防止未初始化: delete后,内存用0xdd(Dead Data)填充,防止再次被使用. 这 ...

  2. 在Salesforce中通过 Debug Log 方式 跟踪逻辑流程

    在Salesforce中通过 Debug Log方式 跟踪逻辑流程 具体位置如下所示: Setup ---> Logs ---> Debug Logs ---> Monitored ...

  3. 详解vue 路由跳转四种方式 (带参数)

    详解vue 路由跳转四种方式 (带参数):https://www.jb51.net/article/160401.htm 1.  router-link ? 1 2 3 4 5 6 7 8 9 10 ...

  4. 【转】asp.net(c#)使用HttpWebRequest附加携带请求参数以post方式模拟上传大文件(以图片为例)到Web服务器端

    原文地址:http://docode.top/Article/Detail/10002 目录: 1.Http协议上传文件(以图片为例)请求报文体内容格式 2.完整版HttpWebRequest模拟上传 ...

  5. MySQL如何导出带日期格式的文件

    一网友问在MySQL中如何只用SQL语句导出带日期格式的文件.觉得有点意思,于是尝试了一下.导出文件使用SELECT INTO OUTFILE 但是OUTFILE后面的值不能使用变量,所以只能使用动态 ...

  6. PHP自带Session隐患(session文件独占锁引起阻塞)

    PHP自带Session隐患(session文件独占锁引起阻塞) PHP默认的会话处理器是session.save_handler = files(即文件).如果同一个客户端同时并发发送多个请求(如a ...

  7. Python 破解带密码保护的Zip文件

    今天发生了个有趣的事情,有个朋友发了一个带密码保护的Zip文件给我,却不给我密码,我就琢磨这怎么可以'猜'到密码呢? 经过一系列的尝试,最终使用python把这个密码给'猜'出来了.要想写出破解密码的 ...

  8. Ajax实现带进度条的文件上传

    Ajax实现带进度条的文件上传 文件上传页面运行效果 上传文件并显示进度条运行效果 代码如下; DiskFileItemFactory factory = new DiskFileItemFactor ...

  9. javac编译带包的java文件需要在命令处加参数

    不带包:javac aaa.java 带包:javac -d . aaa.java 带包就是 java文件中含有 package com.aaa;

随机推荐

  1. Dart Generic All In One

    Dart Generic All In One Dart 泛型 https://dart.dev/guides/language/language-tour#generics /** * * @aut ...

  2. js 检测浏览器开发者控制台是否被打开

    var element = new Image(); Object.defineProperty(element, "id", { get: function () { debug ...

  3. Vue 组件的通信方式都有哪些?

    说一下 Vue 组件的通信方式都有哪些?(父子组件,兄弟组件,多级嵌套组件等等) 一.父组件向子组件传值 二.子组件向父组件传值 三.兄弟组件传值 四.跨组件 一.父组件向子组件传值 1.1props ...

  4. 原生javascript开发计算器实例

    计算器的主要作用是进行数字运算,开发一个计算器功能的web实例,有助于更好的掌握js基础的数字运算能力. 本实例详细分析一个js计算器的开发步骤,学习本教程时最好先具备一些基础的js知识. 计算器包括 ...

  5. 最常用SQL joins:内连接(交集)、左外连接、右外连接、左连接、右连接、全连接(并集),全外连接

    1.内连接.两个表的公共部分用Inner join,Inner join是交集的部分. Select * from TableA A inner join TableB B on A.key=B.ke ...

  6. oracle 导入导出dmp

    exp 用户名/密码@地址:端口/serviceName file=D:\710.dmp exp test710/test710@192.168.15.134:1521/doit file=D:\71 ...

  7. Python爬虫系统化学习(3)

    一般来说当我们爬取网页的整个源代码后,是需要对网页进行解析的. 正常的解析方法有三种 ①:正则匹配解析 ②:BeatuifulSoup解析 ③:lxml解析 正则匹配解析: 在之前的学习中,我们学习过 ...

  8. 【译】Rust宏:教程与示例(一)

    原文标题:Macros in Rust: A tutorial with examples 原文链接:https://blog.logrocket.com/macros-in-rust-a-tutor ...

  9. 基于docker快速搭建hbase集群

    一.概述 HBase是一个分布式的.面向列的开源数据库,该技术来源于 Fay Chang 所撰写的Google论文"Bigtable:一个结构化数据的分布式存储系统".就像Bigt ...

  10. 原生JS快速实现拖放

    原生 JS 快速实现拖放 拖放是很常见的一种交互效果,很多时候我们都会借助于第三方的控件来实现,其实用原生 js 实现起来也非常的方便.接下来我们就用原生 js 和 css 快速实现拖放效果 html ...