1. Hbase与hive的对比
A. Hive(数据仓库):Hive的本质其实就相当于将HDFS中已经存储的文件在mysql中做了一个双射关系,以便使用HSQL查询。hive适用于离线数据的分析和清洗,延迟较高。hive基于hdfs和mapreduce。
B. HBase(数据库):列式存储的非关系型数据库,用于存储结构化和半结构化的数据,不适合关联查询,基于hdfs,数据的持久化存储的体现形式是Hfile,存放于DataNode中。延迟较低。
总结:Hive和HBase是两种基于hadoop的不同技术,hive是一种类sql查询引擎,并且运行mapreduce任务,Hbase是在hadoop之上的nosql的key-value数据库。这两种工具可以同时使用,hive用来统计查询,hbase用来实时查询。两者之间数据可以互相写入。
2. HBase和Hive整合
A. hive的结果导入HBase中
--创建Hive表 create external table if not exists course.score(id int,cname string,score int) row format delimited fields terminated by '\t' stored as textfile ; --数据内容 1 zhangsan 80 2 lisi 60 3 wangwu 30 4 zhaoliu 70 --加载数据 load data local inpath '/export/hive-hbase.txt' into table score; --创建hive管理表和Hbase映射 create table course.hbase_score(id int,cname string,score int) stored by 'org.apache.hadoop.hive.hbase.HBaseStorageHandler' with serdeproperties("hbase.columns.mapping" = "cf:name,cf:score") tblproperties("hbase.table.name" = "hbase_score"); --加载数据 insert overwrite table course.hbase_score select id,cname,score from course.score;
B. 将Hbase中已有的数据加载到Hive的外部表中
--在HBase中创建表并插入数据 create 'hbase_hive_score',{ NAME =>'cf'} put 'hbase_hive_score','1','cf:name','zhangsan' put 'hbase_hive_score','1','cf:score', '95' put 'hbase_hive_score','2','cf:name','lisi' put 'hbase_hive_score','2','cf:score', '96' put 'hbase_hive_score','3','cf:name','wangwu' put 'hbase_hive_score','3','cf:score', '97' --在Hive中创建外部表,映射当前映射表 CREATE external TABLE course.hbase2hive(id int, name string, score int) STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler' WITH SERDEPROPERTIES ("hbase.columns.mapping" = ":key,cf:name,cf:score") TBLPROPERTIES("hbase.table.name" ="hbase_hive_score");
C. mysql数据导入HBase
--在mysql中创建数据表并插入数据 CREATE DATABASE IF NOT EXISTS library; USE library; CREATE TABLE book( id INT(4) PRIMARY KEY NOT NULL AUTO_INCREMENT, NAME VARCHAR(255) NOT NULL, price VARCHAR(255) NOT NULL); INSERT INTO book(NAME, price) VALUES('Lie Sporting', '30'); INSERT INTO book (NAME, price) VALUES('Pride & Prejudice', '70'); INSERT INTO book (NAME, price) VALUES('Fall of Giants', '50');
D. 将HBase中的数据导入到mysql
具体流程Hbase-->hive外部表-->hive内部表-->通过sqoop-->mysql
创建hive外部表,映射hbase中的数据表 CREATE EXTERNAL TABLE course.hbase2mysql (id int,name string,price int) STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler' WITH SERDEPROPERTIES ( "hbase.columns.mapping" = ":key,info:name, info:price" ) TBLPROPERTIES( "hbase.table.name" = "hbase_book", "hbase.mapred.output.outputtable" = "hbase2mysql"); 创建hive的内部表,将外部表导入内部 CREATE TABLE course.hbase2mysqlin(id int,name string,price int); insert overwrite table course.hbase2mysqlin select * from course.hbase2mysql; 清空数据mysql TRUNCATE TABLE book; sqoop导出hive内部表数据到mysql bin/sqoop export -connect jdbc:mysql://hadoop01:3306/library -username root -password 123456 -table book -export-dir /user/hive/warehouse/course.db/hbase2mysqlin --input-fields-terminated-by '\001' --input-null-string '\\N' --input-null-non-string '\\N';
3. HBase的预分区
region:一个表的部分或者全部数据,一个region维护着startRowKey与endRowKey,加入的数据如果在这个范围内,这个数据就会交给这个region维护。
A:为什么要设置预留分区?
- 负载均衡,防止数据倾斜
- 增加数据读写效率
- 方便集群容灾调度region
- 优化Map数量
B:如何预留分区?
Hbase默认建表时候只有一个region,并且startRowKey和endRowKey是没有边界的,所有数据都默认写入到这个region,这个region会变大,当达到一定阈值时候,会切割分成两个split。所以让每个region维护一定范围的rowKey就达到了预留分区目的。
C. 如何创建预留分区?
- 手动指定预定分区
create 'staff','info','partition1',SPLITS=>['1001','1002',1000=3','1004']
- 使用16进制算法生成预分区
create 'staff2','info','partition2',{NUMREGIONS => 15, SPLITALGO => 'HexStringSplit'}
- 分区规则创建于文件当中
分区文件: aaaa bbbb cccc dddd --创建语句 create 'staff3','partition2',SPLITS_FILE => '/export/servers/splits.txt'
- 使用java api创建预分区
package com.partition; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hbase.HBaseConfiguration; import org.apache.hadoop.hbase.HColumnDescriptor; import org.apache.hadoop.hbase.HTableDescriptor; import org.apache.hadoop.hbase.TableName; import org.apache.hadoop.hbase.client.Admin; import org.apache.hadoop.hbase.client.Connection; import org.apache.hadoop.hbase.client.ConnectionFactory; import java.io.IOException; public class PasartionTest { /** * 通过javaAPI进行HBase的表的创建以及预分区操作 */ public static void main(String[] args) throws IOException { hbaseSplit(); } static public void hbaseSplit() throws IOException { //获取连接 Configuration configuration = HBaseConfiguration.create(); configuration.set("hbase.zookeeper.quorum", "hadoop01:2181,hadoop02:2181,hadoop03:2181"); Connection connection = ConnectionFactory.createConnection(configuration); Admin admin = connection.getAdmin(); //自定义算法,产生一系列Hash散列值存储在二维数组中 byte[][] splitKeys = {{1,2,3,4,5},{'a','b','c','d','e'}}; //通过HTableDescriptor来实现我们表的参数设置,包括表名,列族等等 HTableDescriptor hTableDescriptor = new HTableDescriptor(TableName.valueOf("stuff4")); //添加列族 hTableDescriptor.addFamily(new HColumnDescriptor("f1")); //添加列族 hTableDescriptor.addFamily(new HColumnDescriptor("f2")); admin.createTable(hTableDescriptor,splitKeys); admin.close(); } }
4. Hbase的rowkey设计技巧
rowkey的长度原则:最好保证rowkey在10-100字节内,建议在16字节以下。当存储当量数据时,rowkey长度过长也会占用大量磁盘空间,memstore部分数据缓存到内存,rowkey长度过长,内度利用率会降低。
散列原则:建议将rowkey的高位作为散列字段,由程序随机生成,将低位放时间字段,这样将提高数据均衡分布在每个Region Server,以实现负载均衡。
rowkey唯一原则:保证rowkey是唯一的,rowkey是按照字典排序存储的,因此设计rowkey时必须充分利用这个排序的特点,将经常读取的数据存储到一块,将最近可能会被访问的数据也放到一块。
什么是热点?
检索habse的记录首先要通过row key来定位数据行。当大量的client访问hbase集群的一个或少数几个节点,造成少数region server的读/写请求过多、负载过大,而其他region server负载却很小,就造成了“热点”现象。
热点问题产生的原因:
hbase中的数据是按照字典顺序排序的,当大量连续的rowkey几种卸载个别region,各个region之间的数据分布不均匀。
创建表时没有提前预分区,创建的表默认只有一个region,大量的数据写入region。
创建表时提前预分区,但是设计rowkey没有规律可循。
如何解决数据倾斜(热点)?
加盐:在rowkey前面加随机数。增加随机前缀以使得他和以前的rowkey的开头不一样。
哈希:在rowkey前面增加hash值。
反转:将固定格式的rowkey进行反转,如电话号码。
时间反转:将时间戳进行反转。
5. Hbase的协处理器(coprocessor)
协处理器包括两种:
observer:相当于RDBMS中 的触发器。
insert into 之前或者之后一旦监控到,可以完成其他的功能。
hbase:put,preput,postput
endpoint:相当于关系型数据库中的存储过程,完成max,sum,avg等聚合工作
协处理器的加载方式:
静态加载:通过修改hbase-site.xml,配置协处理器在配置文件中,为所有的表增加协处理器,不提倡。
动态加载:启用表aggregtaion
Hbase中的二级索引,可以存在冗余数据,空间换时间。
总结:
- Observer 允许集群在正常的客户端操作过程中可以有不同的行为表现
- Endpoint 允许扩展集群的能力,对客户端应用开放新的运算命令
- observer 类似于 RDBMS 中的触发器,主要在服务端工作
- endpoint 类似于 RDBMS 中的存储过程,主要在 client 端工作
- observer 可以实现权限管理、优先级设置、监控、 ddl 控制、 二级索引等功能
- endpoint 可以实现 min、 max、 avg、 sum、 distinct、 group by 等功能
6. HBase优化见笔记