某天某應用找到我,說線上 bulkload
導入數據到 HBase
失敗
check
了一下 MR
日誌,報錯如下
591)|||IOException during splitting :
org.apache.hadoop.hbase.io.hfile.CorruptHFileException: Problem reading HFile Trailer from file hdfs://******/*****/f1/2adb6a82818642aca73daf999063f655 :
at java.util.concurrent.FutureTask.report(FutureTask.java:122)
at java.util.concurrent.FutureTask.get(FutureTask.java:188)
at org.apache.hadoop.hbase.mapreduce.LoadIncrementalHFiles.groupOrSplitPhase(LoadIncrementalHFiles.java:584)
at org.apache.hadoop.hbase.mapreduce.LoadIncrementalHFiles.doBulkLoad(LoadIncrementalHFiles.java:440)
at org.apache.hadoop.hbase.mapreduce.LoadIncrementalHFiles.doBulkLoad(LoadIncrementalHFiles.java:327)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at sun.reflect.misc.Trampoline.invoke(MethodUtil.java:75)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at sun.reflect.misc.MethodUtil.invoke(MethodUtil.java:279)
Caused by: org.apache.hadoop.hbase.io.hfile.CorruptHFileException: Problem reading HFile Trailer from file
hdfs://******/*****/f1/2adb6a82818642aca73daf999063f655
at org.apache.hadoop.hbase.io.hfile.HFile.pickReaderVersion(HFile.java:495)
at org.apache.hadoop.hbase.io.hfile.HFile.createReader(HFile.java:538)
at org.apache.hadoop.hbase.mapreduce.LoadIncrementalHFiles.groupOrSplit(LoadIncrementalHFiles.java:661)
at org.apache.hadoop.hbase.mapreduce.LoadIncrementalHFiles$3.call(LoadIncrementalHFiles.java:574)
at org.apache.hadoop.hbase.mapreduce.LoadIncrementalHFiles$3.call(LoadIncrementalHFiles.java:571)
at java.util.concurrent.FutureTask.run(FutureTask.java:262)
3 more
Caused by: java.lang.UnsatisfiedLinkError: org.apache.hadoop.util.NativeCodeLoader.buildSupportsSnappy()Z
at org.apache.hadoop.util.NativeCodeLoader.buildSupportsSnappy(Native Method)
at org.apache.hadoop.io.compress.SnappyCodec.checkNativeCodeLoaded(SnappyCodec.java:63)
at org.apache.hadoop.io.compress.SnappyCodec.getDecompressorType(SnappyCodec.java:195)
at org.apache.hadoop.io.compress.CodecPool.getDecompressor(CodecPool.java:181)
at org.apache.hadoop.hbase.io.compress.Compression$Algorithm.getDecompressor(Compression.java:328)
at org.apache.hadoop.hbase.io.compress.Compression.decompress(Compression.java:423)
at org.apache.hadoop.hbase.io.encoding.HFileBlockDefaultDecodingContext.prepareDecoding(HFileBlockDefaultDecodingContext.java:90)
at org.apache.hadoop.hbase.io.hfile.HFileBlock.unpack(HFileBlock.java:549)
at org.apache.hadoop.hbase.io.hfile.HFileBlock$AbstractFSReader$1.nextBlock(HFileBlock.java:1380)
at org.apache.hadoop.hbase.io.hfile.HFileBlock$AbstractFSReader$1.nextBlockWithBlockType(HFileBlock.java:1386)
at org.apache.hadoop.hbase.io.hfile.HFileReaderV2.<init>(HFileReaderV2.java:150)
at org.apache.hadoop.hbase.io.hfile.HFile.pickReaderVersion(HFile.java:483)
8 more
上面的報錯很明顯,Bulkload
導入最後一步,執行 doBulkload
的時候,將生成的 HFile
導入到 HBase
中出現問題,原因是執行 doBulkload
的客戶端 沒有 snappy
本地庫。所以只需要添加 snappy
本地庫即可。
但是這樣處理是否有問題呢:
首先我們來看一下 bulkload
的原理:
bulkload
原理就是通過 MR/Spark
程序根據 HBase
表的 region
範圍 (startkey/endkey)
來做 partition
直接生成 HFile
,然後通過 doBulkload
命令將 HFile
move
到 HBase RegionServer
的 Region
對應的列族目錄下, StoreFileManager
更新維護的 HFile
列表對象即可。bulkload
和 doBulkload
詳細原理,由於涉及的內容比較多,後面有時間的話單獨寫個博客來介紹。這裏就不展開了。
所以這裏面會使用到壓縮的地方應該有三處:
1、MR
生成 HFile
的時候
2、doBulkload
的時候
3、導入到 HBase
,然後 HBase
自身讀取/寫入/compaction
的時候
集羣是我們自己開發維護的 HBase
分支, 雖然默認已經集成了常用的 native
的庫,比如 snappy
,zstd
,但通常執行 bulkload
的 MR
程序或者 doBulkload
的客戶端與 HBase
不在一個集羣,例如這個本例就是。這會導致往壓縮的 HBase
表中導入數據失敗 。
基於以上的原因和問題,對 HBase Bulkload
做了一個簡單的改進:
思路很簡單:就是 bulkload
的時候,支持在客戶端設置壓縮格式,而不是直接使用原始表的壓縮格式。
雖然這個改進很簡單,但在我們的實際場景下,還是很有用的:
1、MR/doBulkload
客戶端可以設置非壓縮的格式,從而避免因爲沒有本地庫導致的失敗,也就是本文中出現的情況
2、bulkload
設置生成非壓縮的 HFile
格式,性能更好,後續compaction
,仍然會根據表的壓縮格式來合併,存儲容量影響很小的情況下,提高性能.
這個特性在我們的版本中結合實現的 flush
、compaction
設置異構存儲策略、壓縮編碼以及 WAL ON SSD
可以做到數據異構以及冷熱分離,比如 flush/bulkload
生成的 HFile
到 SSD
中,並且不設置壓縮和編碼;通過compaction
執行壓縮/編碼
到HDD
中. 這樣的話,發生在HBase
的關鍵路徑的寫入、導入、讀取、compaction
性能大幅提升。
3、在跨數據中心同步中,使用 bulkload replication
的情況下,表是未壓縮的,可以反過來,設置生成 HFile
壓縮,這樣可以減少跨數據中心的同步帶寬消耗。
該改進已經貢獻給了社區,感興趣可參考:
https://issues.apache.org/jira/browse/HBASE-21810
本文分享自微信公衆號 - HBase工作筆記(HBase-Notes)。
如有侵權,請聯繫 [email protected] 刪除。
本文參與“OSC源創計劃”,歡迎正在閱讀的你也加入,一起分享。