Hbase-安装部署Hbase-架构Hbase-SHELL操作Hbase-API操作Hbase-MapReduce
官方MapReduce自定义MapReduce Hbase-集成HiveHbase-优化
高可用预分区RowKey设计基础优化
Hbase官方文档
Hbase-安装部署前置要求
Zookeeper正常启动、Hadoop正常部署
修改配置文件
conf/hbase-env.sh
export Hbase_MANAGES_ZK=false
hbase-site.xml
conf/regionservers
bigdata100bigdata102bigdata104
软连接hadoop配置文件到Hbase
ln -s /opt/module/hadoop-3.1.3/etc/hadoop/core-site.xml /opt/module/hbase/conf/core-site.xmlln -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 masterbin/hbase-daemon.sh start regionserverbin/hbase-daemon.sh stop masterbin/hbase-daemon.sh stop regionserver
如果集群之间的节点时间不同步,会导致regionserver无法启动,抛出ClockOutOfSyncException异常,maxclockskew设置更大的值
方式二
bin/start-hbase.shbin/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客户端命令行
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'
删除数据
# 删除某rowkey的全部数据deleteall 'student','1001'# 删除某rowkey的某一列数据delete 'student','1002','info:sex'
清空表数据
# 清空表的操作顺序为先 disable,然后再 truncate。truncate 'student'
删除表
如果直接drop表会报错
# 首先需要先让该表为disable状态disable 'student'# 然后才能drop这个表:drop 'student'
Hbase-API操作引入依赖
代码案例地址
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.5export HADOOP_HOME=/opt/module/hadoop-3.1.3export HADOOP_CLASSPATH=`${Hbase_HOME}/bin/hbase classpath`
配置文件方式,永久生效,在/etc/profile配置,并在hadoop-env.sh中配置(在for循环之后配置)
# /etc/profile配置export Hbase_HOME=/opt/module/hbase-2.0.5export 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_fruithdfs 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所依赖的Jar包
export Hbase_HOME=/opt/module/hbaseexport HIVE_HOME=/opt/module/hiveln -s $Hbase_HOME/lib/hbase-common-2.0.5.jar $HIVE_HOME/lib/hbase-common-2.0.5.jarln -s $Hbase_HOME/lib/hbase-server-2.0.5.jar $HIVE_HOME/lib/hbase-server-2.0.5.jarln -s $Hbase_HOME/lib/hbase-client-2.0.5.jar $HIVE_HOME/lib/hbase-client-2.0.5.jarln -s $Hbase_HOME/lib/hbase-protocol-2.0.5.jar $HIVE_HOME/lib/hbase-protocol-2.0.5.jarln -s $Hbase_HOME/lib/hbase-it-2.0.5.jar $HIVE_HOME/lib/hbase-it-2.0.5.jarln -s $Hbase_HOME/lib/htrace-core-3.2.0-incubating.jar $HIVE_HOME/lib/htrace-core-3.2.0-incubating.jarln -s $Hbase_HOME/lib/hbase-hadoop2-compat-2.0.5.jar $HIVE_HOME/lib/hbase-hadoop2-compat-2.0.5.jarln -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的属性,如下
建立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-mastersecho bigdata102 > backup-mastersxsync backup-masterssh
预分区手动设置预分区
create 'staff1','info','partition1',SPLITS => ['1000','2000','3000','4000']
生成16进制序列预分区
create 'staff2','info','partition2',{NUMREGIONS => 15, SPLITALGO => 'HexStringSplit'}
按照文件中设置的规则预分区
# splits.txtaaaabbbbcccc# sqlcreate '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 { // 自定义算法 产生一系列 hash 散列值存储在二维数组中 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)); } // 通过HTableDescriptor实例和散列值二维数组创建带有预分区的Hbase表 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