在遇到將Hive中的數據同步到HBase時,一般都是通過在Hive中創建映射HBase的表,然後通過insert的方式來實現,在數據量小的時候,往往還能接受,但是如果是大批量數據,除了同步時間較長,往往還會對線上的HBase服務造成影響,因為這種方式底層還是調用的HBase的put API來實現的。為了提高HBase的數據寫入,一般都會考慮使用bulkload的方式,而bulkload其實也有很多種選擇:
1.編寫MapReduce/Spark程序生成hfile文件,然後通過HBase命令load數據
2.通過HBase的ImportTsv工具生成hfile,然後通過HBase命令load數據
3.通過定製Phoenix的StorageHandler進行bulkload
4.使用Hive的方式生成hfile文件,然後通過HBase命令load數據
本文主要是介紹在CDP中使用Hive的方式,以下方式在CDH5或者CDH6是比較簡單的,但是在CDP中因為Hive默認使用了tez引擎,所以有一些差別。
前置條件
1.目標HBase表必須是新建的(即不能導入到已經存在的表)
2.目標表只能有一個Column Family
3.目標表不能是稀疏的(即每一行數據的結構必須一致)
測試環境:
1.Redhat7.9
2.採用root用戶操作
3.CM為7.4.4,CDP為7.1.7
4.集群未啟用Kerberos
1.進入Hive on Tez服務,在『hive-site.xml 的 Hive 服務高級配置代碼段(安全閥)』中增加以下配置參數,如果不增加,在後面set一些Hive參數無法正常執行。
<property><name>hive.security.authorization.sqlstd.confwhitelist.append</name><value>tez.*|hive.strict.checks.*|hive.mapred.*|mapreduce.*|total.*|hfile.*</value></property>
保存修改,回到CM主頁,會提示重啟相關服務和重新部署客戶端配置操作。
2.將涉及到的一些HBase的jar包put到HDFS中,方便後面使用,如果不想這樣操作,也可以通過Hive的hive.aux.jars.path配置來完成,把jar包到加入到這個配置里。
hadoopfs-put/opt/cloudera/parcels/CDH-7.1.7-1.cdh7.1.7.p0.15945976/jars/hbase-common-2.2.3.7.1.7.0-551.jar/tmphadoopfs-put/opt/cloudera/parcels/CDH-7.1.7-1.cdh7.1.7.p0.15945976/jars/hbase-server-2.2.3.7.1.7.0-551.jar/tmphadoopfs-put/opt/cloudera/parcels/CDH-7.1.7-1.cdh7.1.7.p0.15945976/jars/hbase-client-2.2.3.7.1.7.0-551.jar/tmphadoopfs-put/opt/cloudera/parcels/CDH-7.1.7-1.cdh7.1.7.p0.15945976/jars/hbase-protocol-2.2.3.7.1.7.0-551.jar/tmphadoopfs-put/opt/cloudera/parcels/CDH-7.1.7-1.cdh7.1.7.p0.15945976/jars/hbase-mapreduce-2.2.3.7.1.7.0-551.jar/tmphadoopfs-put/opt/cloudera/parcels/CDH-7.1.7-1.cdh7.1.7.p0.15945976/jars/hbase-shaded-mapreduce-2.2.3.7.1.7.0-551.jar/tmphadoopfs-put/opt/cloudera/parcels/CDH-7.1.7-1.cdh7.1.7.p0.15945976/jars/htrace-core4-4.2.0-incubating.jar/tmphadoopfs-put/opt/cloudera/parcels/CDH-7.1.7-1.cdh7.1.7.p0.15945976/jars/hive-hbase-handler-3.1.3000.7.1.7.0-551.jar/tmp3.準備用於導入到HBase的數據,首先建立Hive外表,並插入數據。
createexternaltabletest_hbase(s1string,s2string)rowformatdelimitedfieldsterminatedby'#'storedastextfilelocation'/tmp/test_hbase';insertintotest_hbasevalues('0000001','a'),('1000000','a'),('1000002','b'),('1000003','b'),('2000000','b'),('2000001','c'),('2000002','b'),('3000000','b'),('3100001','d'),('3100002','3'),('3100003','e'),('3100004','f'),('3100005','g'),('4000000','b'),('4000001','h'),('4100002','i'),('4000003','j');

在生成hfile文件的時候是需要對數據進行排序的,為了啟動多個reduce任務對數據進行並行排序,我們需要用分區鍵將數據按照rowkey字段將數據劃分若干個大小相同的範圍。這樣做還有一個好處就是會生成多個hfile文件,當hbase加載文件的時候會分配到多個regionserver節點上,達到預分區的效果,提高後續數據讀取和寫入的速度。
首先我們需要創建一個表用於生成數據分割文件:
createexternaltablehb_range_keys(rowkey_range_startstring)rowformatserde'org.apache.hadoop.hive.serde2.binarysortable.BinarySortableSerDe'storedasinputformat'org.apache.hadoop.mapred.TextInputFormat'outputformat'org.apache.hadoop.hive.ql.io.HiveNullValueSequenceFileOutputFormat'location'/tmp/hbase_splits/region5';--指定數據存儲目錄,接下來的步驟會用到
接下來需要根據數據rowkey字段對數據進行範圍劃分:
下面是hive官方文檔給的一個示例方法,通過對0.01%的樣本數據排序,然後選擇每第910000行數據,將數據分為了12份,這裡的假設是樣本中的分布與表中的整體分布相匹配。如果不是這種情況,則生成的分區鍵對數據範圍劃分不均衡導致並行排序時出現傾斜情況
insertoverwritetablehb_range_keysselecttransaction_idfrom(selecttransaction_idfromtransactionstablesample(bucket1outof10000ontransaction_id)sorderbytransaction_idlimit10000000)xwhere(row_sequence()%910000)=0orderbytransaction_idlimit11;因為官方的數據Fayson並沒有找到,所以為了方便造了幾條數據(參考第二章插入的數據)來進行測試,所以我們直接手動指定分區鍵:
insertintohb_range_keysvalues('1000000'),('2000000'),('3000000'),('4000000');
1.創建表用於生成保存hfile文件,'/tmp/hbsort1/info'路徑中的info是列族名稱,目前只支持單個列族
createexternaltablehbsort(row_keystring,column1string)storedasINPUTFORMAT'org.apache.hadoop.mapred.TextInputFormat'OUTPUTFORMAT'org.apache.hadoop.hive.hbase.HiveHFileOutputFormat'TBLPROPERTIES('hfile.family.path'='/tmp/hbsort/info');
2.接下來就是準備生成hfile文件,首先在beeline添加jar包設置相關參數,以及set一些Hive on Tez的參數:
--添加相關的jar包addjarhdfs:/tmp/hive-hbase-handler-3.1.3000.7.1.7.0-551.jar;addjarhdfs:/tmp/hbase-common-2.2.3.7.1.7.0-551.jar;addjarhdfs:/tmp/hbase-server-2.2.3.7.1.7.0-551.jar;addjarhdfs:/tmp/hbase-client-2.2.3.7.1.7.0-551.jar;addjarhdfs:/tmp/hbase-protocol-2.2.3.7.1.7.0-551.jar;addjarhdfs:/tmp/hbase-mapreduce-2.2.3.7.1.7.0-551.jar;addjarhdfs:/tmp/hbase-shaded-mapreduce-2.2.3.7.1.7.0-551.jar;addjarhdfs:/tmp/htrace-core4-4.2.0-incubating.jar;setmapred.reduce.tasks=5;--hb_range_keys表條數+1sethive.mapred.partitioner=org.apache.hadoop.hive.ql.exec.tez.TezTotalOrderPartitioner;--指定上一步驟生成的分區鍵文件地址setmapreduce.totalorderpartitioner.path=/tmp/hbase_splits/region5/000000_0;settotal.order.partitioner.path=/tmp/hbase_splits/region5/000000_0;sethfile.compression=snappy;--指定snappy壓縮

3.將數據寫入表中生成hfile文件:
insertoverwritetablehbsortselects1,s2fromtest_hbaseclusterbys1;
1.首先將存放hfile文件的目錄的屬組改為fayson用戶,fayson用戶用於執行HBase的bulkload命令。
sudo-uhdfshadoopfs-chown-Rfayson:fayson/tmp/hbsort2.執行HBase的bulkload命令
hbaseorg.apache.hadoop.hbase.mapreduce.LoadIncrementalHFiles/tmp/hbsorttest_bulk

3.使用hbase shell查詢數據已經全部導入

4.進入HBase Master頁面確認region按照預期生成,並且startkey與endkey都正確

可以看到正確的生成了5個region,startkey與endkey與hb_range_keys分區鍵表設置的一致。
1.與CDH5/6不一樣,CDP中的Hive默認使用的是tez引擎,set的一些參數是不一樣的,CDH5/6與Hive官網的一致如下:
setmapred.reduce.tasks=12;sethive.mapred.partitioner=org.apache.hadoop.mapred.lib.TotalOrderPartitioner;settotal.order.partitioner.path=/tmp/hb_range_key_list;而在CDP中則為:
setmapred.reduce.tasks=5;sethive.mapred.partitioner=org.apache.hadoop.hive.ql.exec.tez.TezTotalOrderPartitioner;setmapreduce.totalorderpartitioner.path=/tmp/hbase_splits/region5/000000_0;settotal.order.partitioner.path=/tmp/hbase_splits/region5/000000_0;2.為了能在CDP的beeline中設置上面的參數需要在CM的Hive on Tez服務中增加以下參數:
<property><name>hive.security.authorization.sqlstd.confwhitelist.append</name><value>tez.*|hive.strict.checks.*|hive.mapred.*|mapreduce.*|total.*|hfile.*</value></property>3.CDP中的Hive內表默認是ACID的託管表,所以本文所有Hive表建議都創建external表,否則會不支持。
4.如果嫌在beeline中add各種jar包麻煩,可以永久將這些jar添加到Hive的hive.aux.jars.path配置中。
5.注意在最後一步執行HBase的bulkload命令時,HBase中不允許存在test_bulk表,否則會導致region個數不能按預期生成。
6.執行HBase的bulkload命令時,需要保證hfile所在目錄的用戶屬組與執行bulkload的命令的用戶一致,本文使用的都是fayson。
參考文檔:
https://cwiki.apache.org/confluence/display/Hive/HBaseBulkLoad#HBaseBulkLoad-AddnecessaryJARshttps://blog.csdn.net/songjifei/article/details/104706388https://blog.csdn.net/alinyua/article/details/109831892