HBase官方文档
HBase-安装部署
前置要求
Zookeeper正常启动、Hadoop正常部署
修改配置文件
conf/hbase-env.sh
export HBASE_MANAGES_ZK=false
hbase-site.xml
<configuration>
<property>
<name>hbase.rootdir</name>
<value>hdfs://bigdata100:8020/hbase</value>
</property>
<property>
<name>hbase.cluster.distributed</name>
<value>true</value>
</property>
<property>
<name>hbase.zookeeper.quorum</name>
<value>bigdata100,bigdata102,bigdata104</value>
</property>
</configuration>
conf/regionservers
bigdata100
bigdata102
bigdata104
软连接hadoop配置文件到HBase
ln -s /opt/module/hadoop-3.1.3/etc/hadoop/core-site.xml /opt/module/hbase/conf/core-site.xml
ln -s /opt/module/hadoop-3.1.3/etc/hadoop/hdfs-site.xml /opt/module/hbase/conf/hdfs-site.xml
HBase远程发送到其他集群
xsync hbase/
启动hbase
方式一
bin/hbase-daemon.sh start master
bin/hbase-daemon.sh start regionserver
bin/hbase-daemon.sh stop master
bin/hbase-daemon.sh stop regionserver
如果集群之间的节点时间不同步,会导致regionserver无法启动,抛出ClockOutOfSyncException异常,maxclockskew设置更大的值
<property>
<name>hbase.master.maxclockskew</name>
<value>180000</value>
<description>Time difference of regionserver from master</description>
</property>
方式二
bin/start-hbase.sh
bin/stop-hbase.sh
HBase-架构
数据模型
NameSpace:命名空间,类似于关系型数据库的DatabBase概念,每个命名空间下有多个表。HBase有两个自带的命名空间,分别是hbase和default,hbase中存放的是HBase内置的表,default表是用户默认使用的命名空间。
Region:类似于关系型数据库的表概念。不同的是,HBase定义表时只需要声明列族即可,不需要声明具体的列。这意味着,往HBase写入数据时,字段可以动态、按需指定。因此,和关系型数据库相比,HBase能够轻松应对字段变更的场景。
Row:HBase表中的每行数据都由一个RowKey和多个Column(列)组成,数据是按照RowKey的字典顺序存储的,并且查询数据时只能根据RowKey进行检索,所以RowKey的设计十分重要。
Column:HBase中的每个列都由ColumnFamily(列族)和ColumnQualifier(列限定符)进行限定,例如info:name,info:age。建表时,只需指明列族,而列限定符无需预先定义。
TimeStamp:用于标识数据的不同版本(version),每条数据写入时,如果不指定时间戳,系统会自动为其加上该字段,其值为写入HBase的时间
Cell:由{rowkey,columnFamily:columnQualifier,timeStamp}唯一确定的单元。cell中的数据是没有类型的,全部是字节码形式存贮
基本架构
RegionServer:RegionServer为Region的管理者,其实现类为HRegionServer
- 对于数据的操作:get,put,delete;
- 对于Region的操作:splitRegion、compactRegion。
Master:Master是所有RegionServer的管理者,其实现类为HMaster
- 对于表的操作:create,delete,alter
- 对于RegionServer的操作:分配regions到每个RegionServer,监控每个RegionServer的状态,负载均衡和故障转移。
Zookeeper:HBase通过Zookeeper来做Master的高可用、RegionServer的监控、元数据的入口以及集群配置的维护等工作。
HDFS:HDFS为HBase提供最终的底层数据存储服务,同时为HBase提供高可用的支持。
架构原理
StoreFile:保存实际数据的物理文件,StoreFile以HFile的形式存储在HDFS上。每个Store会有一个或多个StoreFile(HFile),数据在每个StoreFile中都是有序的。
MemStore:写缓存,由于HFile中的数据要求是有序的,所以数据是先存储在MemStore中,排好序后,等到达刷写时机才会刷写到HFile,每次刷写都会形成一个新的HFile。
WAL:由于数据要经MemStore排序后才能刷写到HFile,但把数据保存在内存中会有很高的概率导致数据丢失,为了解决这个问题,数据会先写在一个叫做Write-Aheadlogfile的文件中,然后再写入MemStore中。所以在系统出现故障的时候,数据可以通过这个日志文件重建。
读流程
- Client先访问zookeeper,获取hbase:meta表位于哪个RegionServer
- 访问对应的RegionServer,获取hbase:meta表,根据读请求的namespace:table/rowkey,查询出目标数据位于哪个RegionServer中的哪个Region中。并将该table的region信息以及meta表的位置信息缓存在客户端的metacache,方便下次访问。
- 与目标RegionServer进行通讯;
- 分别在BlockCache(读缓存),MemStore和StoreFile(HFile)中查询目标数据,并将查到的所有数据进行合并。此处所有数据是指同一条数据的不同版本(timestamp)或者不同的类型(Put/Delete)。
- 将从文件中查询到的数据块(Block,HFile数据存储单元,默认大小为64KB)缓存到BlockCache。6)将合并后的最终结果返回给客户端。
写流程
- Client先访问zookeeper,获取hbase:meta表位于哪个RegionServer
- 访问对应的RegionServer,获取hbase:meta表,根据读请求的namespace:table/rowkey,查询出目标数据位于哪个RegionServer中的哪个Region中。并将该table的region信息以及meta表的位置信息缓存在客户端的metacache,方便下次访问
- 与目标RegionServer进行通讯
- 将数据顺序写入(追加)到WAL
- 将数据写入对应的MemStore,数据会在MemStore进行排序
- 向客户端发送ack
- 等达到MemStore的刷写时机后,将数据刷写到HFile
memStore刷写时机
当某个memstroe的大小达到了hbase.hregion.memstore.flush.size(默认值128M),其所在region的所有memstore都会刷写。当memstore的大小达到了hbase.hregion.memstore.flush.size(默认值128M)*hbase.hregion.memstore.block.multiplier(默认值4)时,会阻止继续往该memstore写数据
当regionserver中memstore的总大小达到java_heapsize*hbase.regionserver.global.memstore.size(默认值0.4)hbase.regionserver.global.memstore.size.lower.limit(默认值0.95),region会按照其所有memstore的大小顺序(由大到小)依次进行刷写。直到regionserver中所有memstore的总大小减小到上述值以下。当regionserver中memstore的总大小达到java_heapsizehbase.regionserver.global.memstore.size(默认值0.4)时,会阻止继续往所有的memstore写数据
到达自动刷写的时间,也会触发memstoreflush。自动刷新的时间间隔由该属性进行配置hbase.regionserver.optionalcacheflushinterval(默认1小时)
当WAL文件的数量超过hbase.regionserver.max.logs,region会按照时间顺序依次进行刷写,直到WAL文件数量减小到hbase.regionserver.max.log以下(该属性名已经废弃,现无需手动设置,最大值为32)
StoreFile Compaction
由于memstore每次刷写都会生成一个新的HFile,且同一个字段的不同版本(timestamp)和不同类型(Put/Delete)有可能会分布在不同的HFile中,因此查询时需要遍历所有的HFile为了减少HFile的个数,以及清理掉过期和删除的数据,会进行StoreFileCompaction Compaction分为两种,分别是MinorCompaction和MajorCompaction。MinorCompaction会将临近的若干个较小的HFile合并成一个较大的HFile,但不会清理过期和删除的数据。MajorCompaction会将一个Store下的所有的HFile合并成一个大HFile,并且会清理掉过期和删除的数据
Region Split
默认情况下,每个Table起初只有一个Region,随着数据的不断写入,Region会自动进行拆分。刚拆分时,两个子Region都位于当前的RegionServer,但处于负载均衡的考虑,HMaster有可能会将某个Region转移给其他的RegionServer。 RegionSplit时机 当1个region中的某个Store下所有StoreFile的总大小超过hbase.hregion.max.filesize,该Region就会进行拆分(0.94版本之前)。 当1个region中的某个Store下所有StoreFile的总大小超过Min(R^2*“hbase.hregion.memstore.flush.size”,hbase.hregion.max.filesize"),该Region就会进行拆分,其中R为当前RegionServer中属于该Table的个数(0.94版本之后)
HBase-SHELL操作
进入HBase客户端命令行
bin/hbase shell
查看帮助命令
help
查看当前数据库中有哪些表
list
创建表
create 'student','info'
插入数据到表
put 'student','1001','info:sex','male'
put 'student','1001','info:age','18'
put 'student','1002','info:name','Janna'
put 'student','1002','info:sex','female'
put 'student','1002','info:age','20'
扫描查看表数据
scan 'student'
scan 'student',{STARTROW => '1001', STOPROW => '1002'}
scan 'student',{STARTROW => '1001'}
查看表结构
describe 'student'
更新指定字段的数据
put 'student','1001','info:name','Nick'
put 'student','1001','info:age','100'
统计表数据行数
count 'student'
删除数据
deleteall 'student','1001'
delete 'student','1002','info:sex'
清空表数据
truncate 'student'
删除表
如果直接drop表会报错
disable 'student'
drop 'student'
HBase-API操作
引入依赖
<dependencies>
<dependency>
<groupId>org.apache.hbase</groupId>
<artifactId>hbase-client</artifactId>
<version>2.0.5</version>
</dependency>
<dependency>
<groupId>org.apache.hbase</groupId>
<artifactId>hbase-server</artifactId>
<version>2.0.5</version>
</dependency>
</dependencies>
代码案例地址
HBase-MapReduce
官方MapReduce
查看HBase的MapReduce任务执行
bin/hbase mapredcp
查看mapreduce的参数指令
hadoop jar ${HBASE_HOME}/lib/hbase-mapreduce-2.0.5.jar
导入环境变量
命令行操作,临时生效
export HBASE_HOME=/opt/module/hbase-2.0.5
export HADOOP_HOME=/opt/module/hadoop-3.1.3
export HADOOP_CLASSPATH=`${HBASE_HOME}/bin/hbase classpath`
配置文件方式,永久生效,在/etc/profile 配置,并在hadoop-env.sh 中配置(在for循环之后配置)
# /etc/profile配置
export HBASE_HOME=/opt/module/hbase-2.0.5
export HADOOP_HOME=/opt/module/hadoop-3.1.3
# hadoop-env.sh配置
export HADOOP_CLASSPATH=$HADOOP_CLASSPATH:/opt/module/hbase-2.0.5/lib/*
运行MapReduce任务
# 统计student表中有多少行数据
${HADOOP_HOME}/bin/hadoop jar ${HBASE_HOME}/lib/hbase-mapreduce-2.0.5.jar rowcounter student
执行MapReduce到HBase表中
# 创建HBase表
hive> create 'fruit','info'
# 创建数据
hdfs dfs -mkdir /input_fruit
hdfs dfs -put fruit.tsv /input_fruit
# 执行
yarn jar ${HBASE_HOME}/lib/hbase-mapreduce-2.0.5.jar importtsv \
-Dimporttsv.columns=HBASE_ROW_KEY,info:name,info:color fruit \
hdfs://bigdata100:8020/input_fruit/
# 查看结果
hive> scan 'fruit'
自定义MapReduce
通过MapReduce将数据从一张表迁入另外一张表
案例地址
通过MapReduce将HDFS数据写入到Hbase
案例地址
HBase-集成Hive
特点 | Hive | HBase |
---|
| Hive的本质其实就相当于将HDFS中已经存储的文件在Mysql中做了一个双射关系,以方便使用HQL去管理查询 | 是一种面向列族存储的非关系型数据库 | | 用于数据分析、清洗Hive适用于离线的数据分析和清洗,延迟较高 | 适用于单表非关系型数据的存储,不适合做关联查询,类似JOIN等操作 | | 基于HDFS、MapReduceHive存储的数据依旧在DataNode上,编写的HQL语句终将是转换为MapReduce代码执行 | 数据持久化存储的体现形式是HFile,存放于DataNode中,被ResionServer以region的形式进行管理 | | | 面对大量的企业数据,HBase可以直线单表大量数据的存储,同时提供了高效的数据访问速度 |
环境准备
拷贝Hive所依赖的Jar包
export HBASE_HOME=/opt/module/hbase
export HIVE_HOME=/opt/module/hive
ln -s $HBASE_HOME/lib/hbase-common-2.0.5.jar $HIVE_HOME/lib/hbase-common-2.0.5.jar
ln -s $HBASE_HOME/lib/hbase-server-2.0.5.jar $HIVE_HOME/lib/hbase-server-2.0.5.jar
ln -s $HBASE_HOME/lib/hbase-client-2.0.5.jar $HIVE_HOME/lib/hbase-client-2.0.5.jar
ln -s $HBASE_HOME/lib/hbase-protocol-2.0.5.jar $HIVE_HOME/lib/hbase-protocol-2.0.5.jar
ln -s $HBASE_HOME/lib/hbase-it-2.0.5.jar $HIVE_HOME/lib/hbase-it-2.0.5.jar
ln -s $HBASE_HOME/lib/htrace-core-3.2.0-incubating.jar $HIVE_HOME/lib/htrace-core-3.2.0-incubating.jar
ln -s $HBASE_HOME/lib/hbase-hadoop2-compat-2.0.5.jar $HIVE_HOME/lib/hbase-hadoop2-compat-2.0.5.jar
ln -s $HBASE_HOME/lib/hbase-hadoop-compat-2.0.5.jar $HIVE_HOME/lib/hbase-hadoop-compat-2.0.5.jar
同时在hive-site.xml 中修改zookeeper的属性,如下
<property>
<name>hive.zookeeper.quorum</name>
<value>bigdata100,bigdata102,bigdata104</value>
</property>
<property>
<name>hive.zookeeper.client.port</name>
<value>2181</value>
</property>
建立Hive表,关联HBase表,插入数据到Hive表的同时能够影响HBase表
CREATE TABLE hive_hbase_emp_table(
empno int,
ename string,
job string,
mgr int,
hiredate string,
sal double,
comm double,
deptno int)
STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler'
WITH SERDEPROPERTIES ("hbase.columns.mapping" = ":key,info:ename,info:job,info:mgr,info:hiredate,info:sal,info:comm,info:deptno")
TBLPROPERTIES ("hbase.table.name" = "hbase_emp_table");
Hive和HBase分别都生成了对应的表
不能直接将数据load进hive所关联的hbase的表中,需要通过临时添加,即可完成数据同步
insert into table hive_hbase_emp_table select * from emp;
建立Hive外部表,关联HBase表
CREATE EXTERNAL TABLE relevance_hbase_emp(
empno int,
ename string,
job string,
mgr int,
hiredate string,
sal double,
comm double,
deptno int)
STORED BY
'org.apache.hadoop.hive.hbase.HBaseStorageHandler'
WITH SERDEPROPERTIES ("hbase.columns.mapping" = ":key,info:ename,info:job,info:mgr,info:hiredate,info:sal,info:comm,info:deptno")
TBLPROPERTIES ("hbase.table.name" = "hbase_emp_table");
关联后就可以使用Hive函数进行分析操作
hive (default)> select * from relevance_hbase_emp;
HBase-优化
高可用
在HBase中HMaster负责监控HRegionServer的生命周期,均衡RegionServer的负载,如果HMaster挂掉了,那么整个HBase集群将陷入不健康的状态,并且此时的工作状态并不会维持太久。所以HBase支持对HMaster的高可用配置
环境配置
在conf目录下创建backup-masters文件,在backup-masters文件中配置高可用HMaster节点,分发到其他集群,启动Hbase
touch backup-masters
echo bigdata102 > backup-masters
xsync backup-masterssh
预分区
手动设置预分区
create 'staff1','info','partition1',SPLITS => ['1000','2000','3000','4000']
生成16进制序列预分区
create 'staff2','info','partition2',{NUMREGIONS => 15, SPLITALGO => 'HexStringSplit'}
按照文件中设置的规则预分区
aaaa
bbbb
cccc
create 'staff3','partition3',SPLITS_FILE => '/root/splits.txt'
使用Java创建预分区
public static void prePartition(String tableName, String... columnFamily) throws IOException {
HBaseAdmin admin = ConfigurationUtils.getHBaseAdmin();
if (isTableExist(tableName)) {
System.out.println("表 " + tableName + "已存在");
} else {
byte[][] bys = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
HTableDescriptor descriptor = new HTableDescriptor(TableName.valueOf(tableName));
for (String cf : columnFamily) {
descriptor.addFamily(new HColumnDescriptor(cf));
}
admin.createTable(descriptor, bys);
System.out.println("表 " + tableName + "创建成功");
}
}
RowKey设计
一条数据的唯一标识就是rowKey,那么这条数据存储于哪个分区,取决于rowKey处于哪个一个预分区的区间内,设计rowKey的主要目的,就是让数据均匀的分布于所有的region中,在一定程度上防止数据倾斜
-
生成随机数、hash、散列值(SHA1) -
字符串反转 -
字符串拼接
基础优化
允许在HDFS的文件中追加内容
配置文件:hdfs-site.xml 、hbase-site.xml
属性:dfs.support.append
说明:开启HDFS追加同步,可以优秀的配合HBase的数据同步和持久化,默认值为true
优化DataNode允许的最大文件打开数
配置文件:hdfs-site.xml 属性:dfs.datanode.max.transfer.threads 说明:HBase一般都会同一时间操作大量的文件,根据集群的数量和规模以及数据动作,设置为4096或者更高。默认值:4096
优化延迟高的数据操作的等待时间
属性:dfs.image.transfer.timeout 说明:如果对于某一次数据操作来讲,延迟非常高,socket需要等待更长的时间,建议把该值设置为更大的值(默认60000毫秒)以确保socket不会被timeout掉
优化数据的写入效率
配置文件:mapred-site.xml 属性:mapreduce.map.output.compress 、mapreduce.map.output.compress.codec 说明:开启这两个数据可以大大提高文件的写入效率,减少写入时间。第一个属性值修改为true,第二个属性值修改为:org.apache.hadoop.io.compress.GzipCodec或者其他压缩方式
设置RPC监听数量
配置文件:hbase-site.xml 属性:hbase.regionserver.handler.count 说明:默认值为30,用于指定RPC监听的数量,可以根据客户端的请求数进行调整,读写请求较多时,增加此值
优化HStore文件大小
配置文件:hbase-site.xml 属性:hbase.hregion.max.filesize 说明:默认值10737418240(10GB),如果需要运行HBase的MR任务,可以减小此值,因为一个region对应一个map任务,如果单个region过大,会导致map任务执行时间过长。该值的意思就是,如果HFile的大小达到这个数值,则这个region会被切分为两个Hfile
优化HBase客户端缓存
配置文件:hbase-site.xml 属性:hbase.client.write.buffer 说明:用于指定Hbase客户端缓存,增大该值可以减少RPC调用次数,但是会消耗更多内存,反之则反之。一般我们需要设定一定的缓存大小,以达到减少RPC次数的目的
指定scan.next扫描HBase所获取的行数
配置文件:hbase-site.xml 属性:hbase.client.scanner.caching 说明:用于指定scan.next方法获取的默认行数,值越大,消耗内存越大
flush、compact、split机制
当MemStore达到阈值,将Memstore中的数据Flush进Storefile;compact机制则是把flush出来的小文件合并成大的Storefile文件。split则是当Region达到阈值,会把过大的Region一分为二
属性:hbase.hregion.memstore.flush.size:134217728 ,128M就是Memstore的默认阈值
这个参数的作用是当单个HRegion内所有的Memstore大小总和超过指定值时,flush该HRegion的所有memstore。RegionServer的flush是通过将请求添加一个队列,模拟生产消费模型来异步处理的。那这里就有一个问题,当队列来不及消费,产生大量积压请求时,可能会导致内存陡增,最坏的情况是触发OOM
hbase.regionserver.global.memstore.upperLimit:0.4
hbase.regionserver.global.memstore.lowerLimit:0.38
当MemStore使用内存总量达到hbase.regionserver.global.memstore.upperLimit指定值时将会有多个MemStoresflush到文件中,MemStoreflush顺序是按照大小降序执行的,直到刷新到MemStore使用内存略小于lowerLimit
|