值得信賴的合信雲 【文章來源:華為社群】
引言 為什麼要內建Hive和HBase
Hive和Hbase在大資料架構中處在不同位置,Hive是一個建構在Hadoop基礎之上的資料倉庫,主要解決分布式存儲的大資料處理和計算問題,Hive提供了類SQL語句,叫HiveQL,
通過它可以使用SQL查詢存放在HDFS上的資料,sql語句最終被轉化為Map/Reduce任務運作,但是Hive不能夠進行互動查詢——它隻能夠在Haoop上批量的執行Map/Reduce任務。
Hive适合用來對一段時間内的資料進行分析查詢,例如,用來計算趨勢或者網站的日志。Hive不應該用來進行實時的查詢。因為它需要很長時間才可以傳回結果。
Hbase是Hadoop database 的簡稱,是一種NoSQL資料庫,非常适用于海量明細資料(十億、百億)的随機實時查詢,如交易清單、軌迹行為等。
在大資料架構中,Hive和HBase是協作關系,Hive友善地提供了Hive QL的接口來簡化MapReduce的使用, 而HBase提供了低延遲的資料庫通路。如果兩者結合,可以利用MapReduce的優勢針對HBase存儲的大量内容進行離線的計算和分析。
Hive和HBase的通信原理
Hive與HBase整合的實作是利用兩者本身對外的API接口互相通信來完成的,
這種互相通信是通過$HIVE_HOME/lib/hive-hbase-handler-*.jar工具類實作的。通過HBaseStorageHandler,Hive可以擷取到Hive表所對應的HBase表名,列簇和列,InputFormat、OutputFormat類,建立和删除HBase表等。基本通信原理如下:
clipboard.png
spacer.gif
通路
Hive通路HBase中HTable的資料,實質上是通過MR讀取HBase的資料,而MR是使用HiveHBaseTableInputFormat完成對表的切分,擷取RecordReader對象來讀取資料的。
對HBase表的切分原則是一個Region切分成一個Split,即表中有多少個Regions,MR中就有多少個Map;
讀取HBase表資料都是通過建構Scanner,對表進行全表掃描,如果有過濾條件,則轉化為Filter。當過濾條件為rowkey時,則轉化為對rowkey的過濾;Scanner通過RPC調用RegionServer的next()來擷取資料。
簡單來說,Hive和Hbase的內建就是,打通了Hive和Hbase,使得Hive中的表建立之後,可以同時是一個Hbase的表,并且在Hive端和Hbase端都可以做任何的操作。
使用場景:
(一)将ETL操作的資料通過Hive加載到HBase中,資料源可以是檔案也可以是Hive中的表。
cj1.png
(二)Hbae作為Hive的資料源,通過整合,讓HBase支援JOIN、GROUP等SQL查詢文法。
cj2.png
(三)建構低延時的資料倉庫
cj3.png
一、 配置HBase環境
修改$HBASE_HOME/conf目錄下的hbase-env.sh,添加以下配置
export JAVA_HOME=/opt/java/jdk1.8
export HADOOP_HOME=/opt/hadoop/hadoop2.8
export HBASE_HOME=/opt/hbase/hbase1.2
export HBASE_CLASSPATH=/opt/hadoop/hadoop2.8/etc/hadoop
export HBASE_PID_DIR=/root/hbase/pids
export HBASE_MANAGES_ZK=false
說明:實際配置的路徑以自己的為準。HBASE_MANAGES_ZK=false 是不啟用HBase自帶的Zookeeper叢集。
修改 hbase-site.xml
編輯hbase-site.xml 檔案,在添加如下配置
<!-- 存儲目錄 -->
<property>
<name>hbase.rootdir</name>
<value>hdfs://test1:9000/hbase</value>
<description>The directory shared byregion servers.</description>
</property>
<!-- hbase的端口 --><property>
<name>hbase.zookeeper.property.clientPort</name>
<value>2181</value>
<description>Property from ZooKeeper'sconfig zoo.cfg. The port at which the clients will connect. </description>
</property>
<!-- 逾時時間 --><property>
<name>zookeeper.session.timeout</name>
<value>120000</value>
<!-- zookeeper 叢集配置。如果是叢集,則添加其它的主機位址 --><property>
<name>hbase.zookeeper.quorum</name>
<value>test1</value>
<name>hbase.tmp.dir</name>
<value>/root/hbase/tmp</value>
<!-- false是單機模式,true是分布式模式 -->
<name>hbase.cluster.distributed</name>
<value>false</value>
說明:hbase.rootdir:這個目錄是region server的共享目錄,用來持久化Hbase 。hbase.cluster.distributed :Hbase的運作模式。false是單機模式,true是分布式模式。若為false,Hbase和Zookeeper會運作在同一個JVM裡面。
二、Hive內建HBase的配置以及測試
1,配置通信接口
因為Hive與HBase內建是利用兩者本身對外的API接口互相通信來完成的,其具體工作交由Hive的lib目錄中的hive-hbase-handler-.jar工具類來實作。是以隻需要将hive的 hive-hbase-handler-.jar 複制到hbase/lib中就可以了。
切換到hive/lib目錄下
輸入:
cp hive-hbase-handler-*.jar /opt/hbase/hbase1.2/lib
注: 如果在hive整合hbase中,出現版本之類的問題,那麼以hbase的版本為主,将hbase中的jar包覆寫hive的jar包。
2,hive和hbase內建測試
在進行測試的時候,確定hadoop、hbase、hive環境已經成功搭建好,并且都成功啟動了。
打開xshell的兩個指令視窗
一個進入hive,一個進入hbase
2.1在hive中建立映射到hbase的表
通過複制上面的jar包,我們已經實作了hive和hbase底層的打通,在上層我們需要做的是使用HQL在hive中建立一個表
與hbase進行映射,為了友善,設定兩邊的表名都為t_employee,存儲的表也是這個表名。
在hive中輸入:
create table t_employee(id int,name string) stored by 'org.apache.hadoop.hive.hbase.HBaseStorageHandler' with serdeproperties("hbase.columns.mapping"=":key,st1:name") tblproperties("hbase.table.name"="t_employee","hbase.mapred.output.outputtable" = "t_employee");
說明:
a、這裡面出現了三個t_employee表名,第一個t_employee 是hive表中的名稱,(id int,name string) 是hive表結構。
在tblproperties 語句中還出現了2個t_employee表,
"hbase.table.name"定義的是在hbase中的表名 ,這個屬性是可選的,僅當你想在Hive和Hbase中使用不同名字的表名時才需要填寫,如果使用相同的名字則可以省略;
"hbase.mapred.output.outputtable"定義的第三個t_employee是存儲資料表的名稱,指定插入資料時寫入的表,如果以後需要往該表插入資料就需要指定該值,這個可以不要,表資料就存儲在第二個表中了 。
b、stored by 'org.apache.hadoop.hive.hbase.HBaseStorageHandler' :是指定處理的存儲器,就是hive-hbase-handler-*.jar包,要做hive和hbase的內建必須要加上這一句;
c、“hbase.columns.mapping” 是定義在hive表中的字段怎麼與hbase的列族進行映射。
例如:st1就是列族,name就是列。它們之間通過“:”連接配接。
在hive中建立的t_employee表,包括兩個字段(int型的id和string型的name),映射為hbase中的表t_employee,其中:key對應hbase的rowkey,value對應hbase的st1:name列。
表成功建立之後
在hive、hbase分别中檢視表和表結構
hive中輸入
show tables;
describe t_employee;
1.jpg
hbase輸入:
list
describe ‘t_employee’
2.jpg
可以看到表t_employee在hbase中已經建立成功了
2.2資料同步測試
進入hbase之後,在t_employee中添加兩條資料 然後查詢該表
put 't_employee','1001','st1:name','zhaoqian'
put 't_employee','1002','st1:name','sunli'
scan 't_employee'
3.jpg
然後切換到hive中查詢該表
select * from t_employee;
4.jpg
然後在hive中删除該表
注:這裡是要讓大家看到資料同步的結果,是以将表删除了。如果大家要做測試的話,是沒有必要删除該表的,因為在後面還會使用該表。
在hive中将表t_employee删除
drop table t_employee;
5.jpg
在Hbase中檢視:
6.jpg
可以看到在hbase中t_employee表也被删除了,hive和hbase之間的資料同步成功!
2.3 多列和列族的映射
我們來看一個更複雜一些的例子,Hive表中的3個字段與Hbase中的2個列族的映射。
Hive建表sql指令如下:
create table t_employee2(id int,name string,age,int,salary int)
stored by 'org.apache.hadoop.hive.hbase.HBaseStorageHandler'
with serdeproperties("hbase.columns.mapping"=":id,a:b,a:c,d:e") ;
hive 表中的key字段預設與hbase中的row key 對應 ,
Hive字段(name和age)對應到1個Hbase列族(列族a的列b和c,即a:b和a:c),
另一個Hive字段(salary)對應到另一個Hbase列族的單個列(d:e),這裡我們并沒有指定hbase中的表名。
假設我們在hive 已有一salary表,現将表salary資料插入到表t_employee2:
insert overwrite table t_employee2 select * from salary;
m1.jpg
m2.jpg
2.4關聯查詢測試
從hive映射HBase
外部表測試——建立一個指向已經存在的Hbae表的Hive表
先在hbase中建一張t_employee_info表,添加兩個列族 st1,st2
然後檢視表結構
create 't_employee_info','st1','st2'
describe 't_employee_info'
17.jpg
對于在hbase已經存在的表,在hive中使用CREATE EXTERNAL TABLE來建立聯系
注意:建立外部表要使用EXTERNAL 關鍵字
create external table t_employee_info(id int,age int,sex string)
stored by 'org.apache.hadoop.hive.hbase.HBaseStorageHandler'
with serdeproperties("hbase.columns.mapping"=":key,st1:age,st2:sex")
tblproperties("hbase.table.name"="t_employee_info");
8.jpg
然後在t_employee_info 中添加資料
put 't_employee_info','1001','st2:sex','man'
put 't_employee_info','1001','st1:age','32'
put 't_employee_info','1002','st1:age','25'
put 't_employee_info','1002','st2:sex','woman'
9.jpg
然後在hive中查詢該表
select * from t_employee_info;
10.jpg
查詢到資料之後,然後将t_employee 和t_employee_info進行關聯查詢。
select * from t_employee a join t_employee_info b where a.id=b.id ;
11.png
說明:通過關聯查詢,可以得出表之間是可以關聯查詢的。
使用Hive內建HBase表的需注意