【小宅按】 Hive和Hbase在大数据架构中处在不同位置,Hive是一个构建在Hadoop基础之上的数据仓库,Hbase是一种NoSQL数据库,非常适用于海量明细数据的随机实时查询, 在大数据架构中,Hive和HBase是协作关系如果两者结合,可以利用MapReduce的优势针对HBase存储的大量内容进行离线的计算和分析。

引言 为什么要集成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表等。基本通信原理如下:

访问

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中的表。

(二)Hbae作为Hive的数据源,通过整合,让HBase支持JOIN、GROUP等SQL查询语法。

(三)构建低延时的数据仓库

一、 配置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 文件,在添加如下配置

hbase.rootdir

hdfs://test1:9000/hbase

The directory shared byregion servers.

hbase.zookeeper.property.clientPort

2181

Property from ZooKeeper'sconfig zoo.cfg. The port at which the clients will connect.

zookeeper.session.timeout

120000

hbase.zookeeper.quorum

test1

hbase.tmp.dir

/root/hbase/tmp

hbase.cluster.distributed

false

说明: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;


hbase输入:

list

describe ‘t_employee’


可以看到表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'

然后切换到hive中查询该表

select * from t_employee;

然后在hive中删除该表

注:这里是要让大家看到数据同步的结果,所以将表删除了。如果大家要做测试的话,是没有必要删除该表的,因为在后面还会使用该表。

在hive中将表t_employee删除

drop table t_employee;

在Hbase中查看:

可以看到在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;

在Hbase中查看:

2.4关联查询测试

从hive映射HBase

外部表测试——创建一个指向已经存在的Hbae表的Hive表

先在hbase中建一张t_employee_info表,添加两个列族 st1,st2

然后查看表结构

输入:

create 't_employee_info','st1','st2'

describe 't_employee_info'

对于在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");

然后在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'

然后在hive中查询该表

输入:

select * from t_employee_info;

查询到数据之后,然后将t_employee 和t_employee_info进行关联查询。

输入:

select * from t_employee a join t_employee_info b where a.id=b.id ;

说明:通过关联查询,可以得出表之间是可以关联查询的。

使用Hive集成HBase表的需注意对HBase表进行预分区,增大其MapReduce作业的并行度

合理的设计rowkey使其尽可能的分布在预先分区好的Region上

通过set hbase.client.scanner.caching设置合理的扫描缓存


作者:hellfire