本文簡單介紹 HBase 的數據導入工具 ImportTSV 闯狱。通過一次將 hive 大表導入 HBase 的實戰(zhàn)案例戏售,梳理期間遇到的問題乏梁,調研更優(yōu)的導入方式颂跨。本文著重關注:
- 如何借助 ImportTSV 工具將數據(文件:tsv、csv犬缨、hive 表) 導入 HBase喳魏,有哪些坑需要考慮?
- HBase 如何建表遍尺,如何創(chuàng)建預分區(qū)截酷?
- Hive 數據導入 HBase 是否有其他方式,更有的方式乾戏?
1 ImportTSV 介紹
ImportTsv 是 HBase 提供的一個命令行工具迂苛,將存儲在 HDFS 上的數據文件,通過指定的分隔符解析后鼓择,導入到 HBase 表中三幻。(TSV :Tab-separated values)
這樣的方式導入數據與正常寫入流程不同的是,跳過了 WAL呐能、Memcache 與 Flush 的過程念搬,直接將 HFile 文件移動到 HBase 表空間目錄下即可,不影響 RegionServer 的性能摆出。
ImportTsv 提供兩種導入的方式:
- 直接 MR 任務寫入:這對小數據量朗徊,可以直接一行命令導入
- 先導出 hfile 再 bulkload:針對大數據量,高效導入
方案 1 :直接導入
首先創(chuàng)建 hbase 表:user (大表一定要預分區(qū)偎漫,不然全部會寫到一個 region)爷恳,然后執(zhí)行命令導入:
hbase org.apache.hadoop.hbase.mapreduce.ImportTsv -Dimporttsv.separator="," -Dimporttsv.columns=HBASE_ROW_KEY,info:name,info:gender,info:age,info:idNumber,info:address,info:birthday user /tmp/user.txt
- 指定分隔符為逗號
- 指定導入的列:第一列為 HBASE_ROW_KEY,其他列都是 info列族下的name象踊,gender温亲,age,idNumber杯矩,address栈虚,birthday列
- 指定需要導入的表名:user
- 指定數據文件在HDFS上的目錄地址:/tmp/user.txt
方案 2:hfile + bulkload
- 建 HBase 表(大表一定要預分區(qū),不然全部會寫到一個 region)
- 生成 hfile
- bulkload
hbase org.apache.hadoop.hbase.mapreduce.ImportTsv -Dimporttsv.separator="," -Dimporttsv.bulk.output=/louisvv/hfile_tmp -Dimporttsv.columns=HBASE_ROW_KEY,info:name,info:gender,info:age,info:idNumber,info:address,info:birthday user /yw/user.txt
2 實戰(zhàn)案例
2.1 需求描述
Hive 表 42 億行數據導入 HBase史隆,采用上述提到的方案 2 : hfile + bulkload
Hive 表信息:
表名:hive_pub.dim_ip_cover_all_info_20220801_001
行數:42 億
rowkey 為表第一個字段 ip_num魂务,是 ip 轉出的數值,保證唯一泌射。
數據樣例如下:
ip_num ip begin_ip end_ip country province_name city_name
1214810642 72.104.138.18 72.55.192.0 72.135.255.255 美國 美國
1214810654 72.104.138.30 72.55.192.0 72.135.255.255 美國 美國
137497864 8.50.13.8 8.47.158.0 8.127.255.255 美國 美國
137497876 8.50.13.20 8.47.158.0 8.127.255.255 美國 美國
137497888 8.50.13.32 8.47.158.0 8.127.255.255 美國 美國
137497900 8.50.13.44 8.47.158.0 8.127.255.255 美國 美國
137497912 8.50.13.56 8.47.158.0 8.127.255.255 美國 美國
137497924 8.50.13.68 8.47.158.0 8.127.255.255 美國 美國
3699562708 220.130.216.212 220.130.216.0 220.130.217.255 中國 臺灣 彰化縣
3699562720 220.130.216.224 220.130.216.0 220.130.217.255 中國 臺灣 彰化縣
2.2 實現(xiàn)方案
2.2.1 HBase 創(chuàng)建帶預分區(qū)的表
這一步非常重要头镊,hbase 建表如果不預分區(qū),所有數據默認會寫到一個分區(qū)魄幕,導入后需要長時間的 split ,compaction颖杏。 以下是我們的建表語句纯陨,指定壓縮,預分區(qū)文件為手動生成的: /tmp/split.txt。
create 'ns:xx', {NAME => 'cf',COMPRESSION => 'snappy' },SPLITS_FILE => '/tmp/split.txt'
下面的重點的就是如何創(chuàng)建預分區(qū)翼抠,預分區(qū)的目的是讓數據均衡分布在不同了 region - 分區(qū)咙轩。理解預分區(qū)需要理解 HBase rowkey 的字典排序,可以參考:[HBase] - 理解 HBase Rowkey 字典排序 - 簡書
需要基于 rowkey 分布特征阴颖,劃分分區(qū)活喊,讓數據均衡, hbase 提供三種預分區(qū)算法量愧,注意DecimalStringSplit 算法 HBase 低版本1.4 以下不支持:
- UniformSplit: rowkey 前綴完全隨機
- HexStringSplit: rowkey 是十六進制的字符串作為前綴的
- DecimalStringSplit: rowkey 是 10 進制數字字符串作為前綴的钾菊,范圍 0-9999999 (HBase 1.4 以下版本不支持)
了解 rowkey 特征,如果適用以上算法偎肃,可以直接采用這種方式建表煞烫。例如以下是創(chuàng)建一個 50 個 region 的表,采用 UniformSplit 分區(qū)算法累颂。
create 'ns:xx', {NAME => 'cf',COMPRESSION => 'snappy' }, { NUMREGIONS => 50, SPLITALGO => 'UniformSplit' }
如果 rowkey 特征不適用于上述三種算法滞详,需要自己生成分區(qū)區(qū)間,語法為:
# 直接指定
create 'ns:xx', {NAME => 'cf',COMPRESSION => 'snappy' }, SPLITS => ['10','20','30','40']
# 通過文件指定
create 'ns:xx', {NAME => 'cf',COMPRESSION => 'snappy' }, SPLITS_FILE => '/tmp/split.txt'
分析本案例:rowkey 的特點為:數值型紊馏,范圍為:0-9999999料饥,數據分布較為均衡。
數據行數:42億朱监,數據量 1.2 T岸啡。
根據數據分布,輸出 split 分區(qū)文件如下赌朋,按照這個粒度凰狞,一共有 200+ 分區(qū)。這個可以通過手工或者腳本生成沛慢。
100|
105|
110|
115|
...
995|
具體分多少個分區(qū)赡若,這個不一定需要絕對精準,可以大概估算团甲,分區(qū)多逾冬,粒度細,分區(qū)少躺苦,粒度粗身腻。 region個數估算,大致可以依據公示 :<region 個數> = <總數據量> / <單個region 的大小>(5-8G)
來估算匹厘。
上述數據分粗一點嘀趟,可以以1開頭,2開頭愈诚, 3開頭她按, 4開頭...9開頭牛隅,一共 10 個分區(qū)。如果數據量大了 10 個分區(qū)可能太少酌泰。
1
2
3
4
5
6
7
8
9
一個 todo 疑問媒佣,是否有其他生成 splits 的方式,更優(yōu)的方式陵刹?
2.2.2 導出 hive 數據
導出 hive 數據到 hdfs(字段逗號分隔)
2.2.3 生成 hfile
利用 importTsv 命令生成 hfile默伍,需要指定列分隔符,HBASE_ROW_KEY 標識第一個字段為 rowkey衰琐,最后一個參數是數據文件的位置也糊。
hbase org.apache.hadoop.hbase.mapreduce.ImportTsv -Dimporttsv.separator="|" \
-Dimporttsv.bulk.output=/data/hfile_tmp/ \
-Dimporttsv.columns=HBASE_ROW_KEY,cf:ip,cf:begin_ip,cf:end_ip,cf:country,cf:province_name,cf:city_name \
-Dmapreduce.map/reduce.memory.mb=5120 \
-Dmapreduce.map/reduce.java.opts=-Xmx4096m \
ns:xx /path/to/hdfs/tsvfile
2.2.4 bulkload 導入 HBase
bulkload 的實現(xiàn)原理可以參考之前的文章:HBase Bulkload 遷移數據及問題思考 - 簡書
命令如下:
hbase org.apache.hadoop.hbase.mapreduce.LoadIncrementalHFiles /path/to/hfile hbase_table
2.2.5 major compact
導入后執(zhí)行一次 major compact 有助于提高數據本地化率, 合并小文件碘耳。操作建議在閑時執(zhí)行显设。命令在 hbase shell 執(zhí)行:
major_compact 'ns:table'
3 其他導入方式
上述流程稍顯麻煩,是否還有其他更優(yōu)的方式辛辨?
可以基于 Hive-HBase Integration 來導入 (https://cwiki.apache.org/confluence/display/Hive/HBaseIntegration)捕捂。 步驟如下:
創(chuàng)建 HBase 表(同樣注意創(chuàng)建預分區(qū))
創(chuàng)建 hive 表 ,目的是為了生成 hfile斗搞,
需要注意指攒,hive 下需要添加 HBase 相關的 jar:
add jar /lib/hive-hbase-handler-2.3.3.jar;
add jar /lib/hbase-protocol-1.1.1.jar;
add jar /lib/hbase-common-1.1.1.jar;
add jar /lib/hbase-client-1.1.1.jar;
add jar /lib/hbase-server-1.1.1.jar;
創(chuàng)建表:
create table stu_info{
name string comment '名字',
age int comment'年齡'
}
STORED AS
INPUTFORMAT 'org.apache.hadoop.mapred.TextInputFormat'
OUTPUTFORMAT 'org.apache.hadoop.hive.hbase.HiveHFileOutputFormat'
TBLPROPERTIES ('hfile.family.path' = '/user/hive-hbase/info');
輸出格式一定要為:HiveHFileOutputFormat。/user/hive-hbase/info 是生成的 hfile 在 HDFS 上的路徑僻焚,其中 info 為 Hbase 的 family允悦。
- 導入數據到 Hive 表:生成 hfile
insert overwrite table stu_info select xxx from xxx
到 hfile.family.path 目錄查看生成的 hfile
- bulkload hfile 到 hbase 表
bin/hbase org.apache.hadoop.hbase.mapreduce.LoadIncrementalHFiles /user/hive-hbase/info/ hbase_table
參考致謝:
使用ImportTSV向HBase中導入數據 | LouisvV's Blog
hive表數據導入到Hbase - CodeAntenna
Creating HBase HFiles From a Hive Table - Cloudera Community - 244627
理解 HBase Rowkey 字典排序 - 簡書
HBase Bulkload 遷移數據及問題思考 - 簡書