用DeBug的方式,帶你掌握HBase檔案在Snapshot的各種變化

華為雲開發者社群發表於2021-04-02
摘要:掌握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

用DeBug的方式,帶你掌握HBase檔案在Snapshot的各種變化

通過讀取data.manifest得到了本次Snapshots涉及到哪些region以及關聯的HFile

用DeBug的方式,帶你掌握HBase檔案在Snapshot的各種變化

這裡解析出來的路徑格式為 <列族>/<表名>=<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中的資訊,

用DeBug的方式,帶你掌握HBase檔案在Snapshot的各種變化

發現這裡是包含父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 。

 

點選關注,第一時間瞭解華為雲新鮮技術~

相關文章