1. 程式人生 > >MapReduce over HBase Snapshot

MapReduce over HBase Snapshot

背景

       工作中有很多使用HBase作為批處理源和目標的場景。之前已經做過很多優化措施,基本原則就是減少對RegionServer的影響,特別是降低RegionServer GC的時間,比如寫入時先寫HFile再BulkLoad、使用Filter儘量只讀取需要的行和列、使用G1GC等等。但是讀取HBase表資料要通過RegionServer的堆,在大批量處理的程式中可能會帶來長時間GC的情況。

       能不能繞過RegionServer直接讀HFile中的資料呢?曾經考慮過直接從HFDS讀取HFile中的資料,但是要自己去處理檔案合併、資料版本、Filter等,將是一個非常複雜的工程。

       直到一次機會在HBase Con Asia中看到有不少公司在使用一個Feature解決這個問題,就是HBASE-8369 MapReduce over snapshot files,支援0.98及以上版本。

介紹

特點

  1. 對RegionServer不產生壓力

通過快照的連結檔案讀取對應HFile中的資料,資料不再經過RegionServer的堆,所以站在系統角度它最大的好處就是: 對RegionServer不產生壓力。

  1. 程式碼改動非常少!

          用於替代表讀取的快照讀取類中,對相關的Scan類等有足夠的支援,使用者需要關心的就是維護快照,並在程式碼中使用initTableSnapshotMapperJob換掉initTableMapperJob,所以站在工程的角度它最大的好處是:程式碼改動非常少!

相關類和方法

  1. TableSnapshotInputFormat

一個可以讓MapReudce程式讀取Hbase快照的InputFormat。

https://hbase.apache.org/apidocs/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormat.html

  1. TableMapReduceUtil.initTableSnapshotMapperJob

一個可以建立讀取Hbase快照的MapReduce job的方法

https://hbase.apache.org/apidocs/org/apache/hadoop/hbase/mapreduce/TableMapReduceUtil.html

效果

       當時的一個簡單的測試結果截圖,前一次是沒有使用SnapShot的

使用舉例

       如果MapReduce程式中原來使用的是initTableMapperJob,那麼只要加上一段Snapshot的配置程式碼,並把initTableMapperJob換成initTableSnapshotMapperJob就可以了。

HBaseProtos.SnapshotDescription.Builder builder = HBaseProtos.SnapshotDescription.newBuilder();
final HBaseProtos.SnapshotDescription snapshotDescription = builder.setName(snapshotName).build();
try (HBaseAdmin admin = new HBaseAdmin(conf)) {
useSnapshot = admin.isSnapshotFinished(snapshotDescription);
} catch (Exception e) {
System.out.println(e.getMessage());
useSnapshot = false;
}
System.out.println("snapshot Finished:" + useSnapshot);

TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName, scan, ctMapper.class,
ImmutableBytesWritable.class, Put.class, job, false, new Path("/tmp/snapshot"));


問題

 建立快照失敗

       我們認為可能是在建立快照時剛好有region正在做compaction\split\transition等等,還有一種可能是因為我們沒有去指定skipflush建立快照時需要做Flush,如果此時有大量資料要Flush成HFile,就會花費很多時間。

      我們可以用下面的這些辦法來避免快照建立失敗:

  1. 如果建立不成功就隔1分鐘再來試試,
  2. 如果源端這張表不需要一直線上的話,我們可以先把表disable掉再建快照。
  3. 為了避免transition,還可以暫時關閉balance
  4. 避免flush可以再建立快照時加上跳過flush的引數
  5. 預設的超時時間是60s我們後來改大到了10分鐘。

讀取快照失敗

       在拷貝的過程中報找不到檔案,通過讀日誌和原始碼我們瞭解到,對於快照中定義中的每個HFile,這個拷貝程式會從4個資料夾中查詢,順序是data、.tmp、mobdir、archive,原本資料可能都在data目錄下,當發生compaction/split的時候,會有產生新的HFile檔案,快照定義中的哪個老的檔案會被轉移到archive下面。理論上順著找下來也沒什麼問題,但原始碼中有一處bug,導致找到第二個目錄,就是.tmp的時候就會報錯了,不會找到archive,我們做了一點調整後打成一個新的程式替換掉原來的ExportSnapshot,解決了這個問題。