BulkLoad從hdfs導入hbase中數據總結

背景

由於新需求需要新建hbase表,將hdfs中給定的目錄下的文件導入到hbase表中,一種格式的文件(多種格式可能需要合併吧,目前沒有這個需求,但是也可以分多次導入到hbase中吧,除非rowkey的構成需要多個文件,目前沒有這種需求)。

下面總結一下,寫這個工具的過程和遇到的一些坑。

1.調研有什麼樣的方式導入

網上查了有很多種方式,比如數據少可以直接讀取插入,或者bulkload,在這不介紹沒中方式的優缺點,詳細的可以看

https://www.ibm.com/developerworks/cn/opensource/os-cn-data-import/index.html

介紹了導入到hbase的幾種方式

最後選擇的是bulkload的方式,下面介紹一下代碼和過程

2.格式化原始數據

1. 數據獲取

首先是原始數據的獲取,我們是從hdfs中直接獲取的文件,文件是採用deflate壓縮的,但是我們不需要自己去解壓,java api還是非常好用,會根據壓縮的格式獲取解壓的方法具體代碼如下:

讀取hdfs壓縮後的文件

讀取壓縮的文件主要參考這個文章,核心代碼如下

CompressionCodecFactory factory = new CompressionCodecFactory(conf);
InputStream stream = null;
CompressionCodec codec = factory.getCodec(file.getPath());
//判斷是否使用了壓縮編碼器
if (codec != null) {
     stream = codec.createInputStream(inputFs.open(file.getPath()));
} else {
     stream = inputFs.open(file.getPath());
}

最後會獲取到輸入流。

注意:1. 這裏的conf,一定要加上這個配置,不然會報錯的

// 不設置該代碼會出現錯誤:java.io.IOException: No FileSystem for scheme: hdfs
conf.set("fs.hdfs.impl", "org.apache.hadoop.hdfs.DistributedFileSystem");

2. 讀取本地的hdfs和讀取線上集羣是有區別的

如果是本地 fs.defaultFS

hdfs://master:8020改爲hdfs://xxx,我們不能直接在路徑上會報錯

Exception in thread "main" java.lang.IllegalArgumentException: java.net.UnknownHostException: xxx

xxx是自己定義的

需要配置一些參數,具體的配置可以參考,每一個配置項都寫好了

Hadoop在HA模式下遠程上傳文件的實現

2. 格式化數據

上一步解壓之後我們的數據其實和用hadoop dfs -text輸出的格式是一樣的,不需要特殊處理,只要符合

1    0    1    1    107    1511856292918    1565700796561

每一行都是這種格式中間的分隔符不限制,可以在讀取的時候作爲參數輸入

格式化之後是輸出到另一個hdfs目錄,因爲hbase的bulkload的要以hdfs的目錄或文件作爲輸入,所以可以直接寫到另一個hdfs目錄

這裏可能hdfs不是同一個集羣,那麼我們不能使用一個 FileSystem,我們需要在創建新的對象,如果是一個我們可以直接用。(這裏說的有點不太清楚,但是公司的代碼不能全都粘貼出來,到時候可以自己試一下,或者評論問一下)。

直接用 FSDataOutputStream 類就可以輸出到具體文件

經過這一步數據的準備就好了,我們可以生成一個或多個文件

3.生成HFILE

具體代碼可以參考

Java操作HBase進行Bulkload方法導入數據

這個代碼使用的hbase應該是1.0以下的,因爲HTable在我的版本中已經是廢棄的了,所以在某些步驟上我改了改。

我的Hbase是1.2.0,connectin類是org.apache.hadoop.hbase.client.Connection

HTable table = new HTable(conf, args[0]);
//更改成下面的
Table table = HBaseConfig.getConnection().getTable(tableName);
//HBaseConfig.getConnection() 是自己封裝的一個hbase的connection,這個應該和普通,
//在1.2.0適用connection來獲取表等,具體可以去看hbase的api
load.doBulkLoad(new Path(args[2]), table);
//這行代碼更改成調用新的接口

org.apache.hadoop.hbase.mapreduce.LoadIncrementalHFiles#doBulkLoad(org.apache.hadoop.fs.Path, org.apache.hadoop.hbase.client.Admin, org.apache.hadoop.hbase.client.Table, org.apache.hadoop.hbase.client.RegionLocator)

Admin=connection.getAdmin()
RegionLocator=connection.getRegionLocator(tableName)

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章