Hbase
1. 介绍¶
HBase是一个高可靠性、高性能、面向列、可伸缩的分布式存储系统,利用HBase技术可在廉价PC Server上搭建大规模结构化的存储集群。HBase的目标是存储并处理大型数据,具体来说是仅需使用普通的硬件配置,就能够处理由成千上万的行和列所组成的大型数据。
HBase是建立在Hadoop文件系统之上的分布式面向列的数据库。它是一个开源项目,是横向扩展的。HBase是一个数据模型,类似于谷歌的大表设计,可以提供快速随机访问海量结构化数据。它利用了Hadoop的文件系统(HDFS)提供的容错能力。它是Hadoop的生态系统,提供对数据的随机实时读/写访问,是Hadoop文件系统的一部分。
人们可以直接或通过HBase的存储HDFS数据。使用HBase在HDFS读取消费/随机访问数据。 HBase在Hadoop的文件系统之上,并提供了读写访问。
HBase 和 HDFS
HDFS | HBase |
---|---|
HDFS是适于存储大容量文件的分布式文件系统。 | HBase是建立在HDFS之上的数据库。 |
HDFS不支持快速单独记录查找。 | HBase提供在较大的表快速查找 |
它提供了高延迟批量处理;没有批处理概念。 | 它提供了数十亿条记录低延迟访问单个行记录(随机存取)。 |
它提供的数据只能顺序访问。 | HBase内部使用哈希表和提供随机接入,并且其存储索引,可将在HDFS文件中的数据进行快速查找。 |
1.1 存储机制¶
HBase是一个面向列的数据库,在表中它由行排序。表模式定义只能列族,也就是键值对。一个表有多个列族以及每一个列族可以有任意数量的列。后续列的值连续地存储在磁盘上。表中的每个单元格值都具有时间戳。总之,在一个HBase:
- 表是行的集合。
- 行是列族的集合。
- 列族是列的集合。
- 列是键值对的集合。
下面给出的表中是HBase模式的一个例子。
1.2 HBase 和 RDBMS¶
HBase | RDBMS |
---|---|
HBase无模式,不具有固定列模式的概念;仅定义列族。 | RDBMS有它的模式,描述表的整体结构的约束。 |
它专门创建为宽表。 HBase是横向扩展。 | 这些都是细而专为小表。很难形成规模。 |
没有任何事务存在于HBase。 | RDBMS是事务性的。 |
它反规范化的数据。 | 它具有规范化的数据。 |
它用于半结构以及结构化数据是非常好的。 | 用于结构化数据非常好。 |
1.3 HBase架构¶
在HBase中,表被分割成区域,并由区域服务器提供服务。区域被列族垂直分为“Stores”。Stores被保存在HDFS文件。下面显示的是HBase的结构。
**注意:**术语“store”是用于区域来解释存储结构。
HBase有三个主要组成部分:客户端库,主服务器和区域服务器。区域服务器可以按要求添加或删除。
主服务器
- 分配区域给区域服务器并在Apache ZooKeeper的帮助下完成这个任务。
- 处理跨区域的服务器区域的负载均衡。它卸载繁忙的服务器和转移区域较少占用的服务器。
- 通过判定负载均衡以维护集群的状态。
- 负责模式变化和其他元数据操作,如创建表和列。
区域
- 区域只不过是表被拆分,并分布在区域服务器。
区域服务器
- 与客户端进行通信并处理数据相关的操作。
- 句柄读写的所有地区的请求。
- 由以下的区域大小的阈值决定的区域的大小。
1.4 体系结构¶
HBase的服务器体系结构遵从简单的主从服务器架构,它由HRegion Server群和HBase Master服务器构成。HBase Master负责管理所有的HRegion Server,而HBase中的所有RegionServer都是通过ZooKeeper来协调,并处理HBase服务器运行期间可能遇到的错误。HBase Master Server本身并不存储HBase中的任何数据,HBase逻辑上的表可能会被划分成多个Region,然后存储到HRegion Server群中。HBase Master Server中存储的是从数据到HRegion Server的映射。
- Client
HBase Client使用HBase的RPC机制与HMaster和HRegion Server进行通信,对于管理类操作,Client与HMaster进行RPC;对于数据读写类操作,Client与HRegionServer进行RPC。
- Zookeeper
Zookeeper Quorum中除了存储了-ROOT-表的地址和HMaster的地址,HRegionServer会把自己以Ephemeral方式注册到Zookeeper中,使得HMaster可以随时感知到各个HRegionServer的健康状态。此外,Zookeeper也避免了HMaster的单点问题。
- HMaster
每台HRegionServer都会与HMaster进行通信,HMaster的主要任务就是要告诉每台HRegion Server它要维护哪些HRegion。 当一台新的HRegionServer登录到HMaster时,HMaster会告诉它等待分配数据。而当一台HRegion死机时,HMaster会把它负责的HRegion标记为未分配,然后再把它们分配到其他的HRegion Server中。 HBase已经解决了HMaster单点故障问题(SPFO),并且HBase中可以启动多个HMaster,那么它就能够通过Zookeeper来保证系统中总有一个Master在运行。HMaster在功能上主要负责Table和Region的管理工作,具体包括:
- 管理用户对Table的增删改查操作
- 管理HRegionServer的负载均衡,调整Region分布
- 在Region Split后,负责新Region的分配
-
在HRegionServer停机后,负责失效HRegionServer上的Region迁移
-
HRegion
当表的大小超过设置值得时候,HBase会自动地将表划分为不同的区域,每个区域包含所有行的一个子集。对用户来说,每个表是一堆数据的集合,靠主键来区分。从物理上来说,一张表被拆分成了多块,每一块就是一个HRegion。我们用表名+开始/结束主键来区分每一个HRegion,一个HRegion会保存一个表里面某段连续的数据,从开始主键到结束主键,一张完整的表格是保存在多个HRegion上面。
上图表示当Table随着记录数不断增加而变大后,会逐渐分裂成多份splits,成为regions,一个region由[startkey, endkey]表示,不同的region会被Master分配给响应的RegionServer进行管理。
- HRegionServer
所有的数据库数据一般都是保存在Hadoop分布式文件系统上面的,用户通过一系列HRegion服务器获取这些数据,一台机器上面一般只运行一个HRegionServer,且每一个区段的HRegion也只会被一个HRegion服务器维护。如下图所示HRegion Server数据存储关系图。
HRegion Server主要负责响应用户的IO请求,向HDFS文件系统中读写数据,是HBase中最核心的模块。HRegionServer内部管理了一系列HRegion对象,每个HRegion对应了Table中的一个Region,HRegion中由多个HStore组成。每个HStore对应了Table中的一个Column Family的存储,可以看出每个ColumnFamily其实就是一个集中的存储单元,因此最好将具备共同IO特性的column放在一个Column Family中,这样最高效。 HStore存储时HBas存储的核心了,其中由两部分组成,一部分是MemStore,一部分是StoreFiles。MemStore是Sorted Memory Buffer,用户写入数据首先会放入MemStore,当MemStore满了以后会flush成一个StoreFile(底层是HFile),当StoreFile文件数增长到一定阈值,会触发Compact合并操作,将多个StoreFile合并成一个StoreFile,合并过程中会进行版本合并和数据删除,因此可以看出HBase其实只有增加数据,所有的更新和删除操作都是后续的compact过程中进行的,这使得用户的写操作只要进入内存中就可以立刻返回,保证了HBase IO的高性能。当StoreFiles Compact后,会逐步形成越来越大的StoreFile,当单个StoreFile大小超过一定的阈值后,会触发Split操作,同时,会把当前的Region Split成2个Region,父Region会下线,新Split出的2个孩子Region会被HMaster分配到响应的HRegion Server上,使得原先1个Region的压力得以分流道2个Region上。
理解上述HStore的基本原理之后,必须了解一下HLog的功能,因为上述的HStore在系统正常工作的前提下是没有问题的,但是在分布式系统环境中,无法避免系统出错或者宕机,一次一旦HRegion Server意外退出,MemStore中的内存数据将会丢失,这就需要引入HLog了。每一个HRegionServer中都有一个HLog对象,HLog是一个实现Write Ahead Log的类,在每次用户操作写入MemStore的同时,也会写一份数据到HLog文件中,HLog文件定期会滚动出新的,并删除旧的文件,当HRegionServer意外终止后,HMaster会通过Zookeeper感知到,HMaster首先会处理遗留的HLog文件,将其中不同Region的Log数据进行拆分,分别放到相应Region的目录下,然后再将失效的Region重新分配,领取到这些Region的HRegionServer在LoadRegion过程中,会发现有历史HLog需要处理,因此会Replay HLog中的数据到MemStore中,然后flush到StoreFiles,完成数据恢复。
- HBase存储格式
HBase中的所有数据文件都存储在Hadoop HDFS文件系统上,包括上述提到的两种文件类型:
- HFile HBase中的KeyValue数据的存储格式,HFile是Hadoop的二进制格式文件,实际上StoreFile就是对HFile做了轻量级的包装,即StoreFile底层就是HFile。
-
HLogFile,HBase中WAL(Write Ahead Log)的存储格式,物理上是Hadoop的Sequence File
-
ROOT表和META表
用户表的Regions元数据被存储在.META.表中,随着Region的增多,.META.表中的数据也会增大,并分裂成多个Regions。为了定位.META.表中各个Regions的位置,把.META.表中的所有Regions的元数据保存在-ROOT-表中,最后由Zookeeper记录-ROOT-表的位置信息。所有客户端访问用户数据前,需要首先访问Zookeeper获得-ROOT-的位置,然后方位-ROOT-表获得.META.表的位置,最后根据.META.表中的信息确定用户数据存放的位置,-ROOT-表永远不会被分割,它只有一个Region,这样可以保证最多需要三次跳转就可以定位任意一个Region。为了加快访问速度,.META.表的Regions全部保存在内存中,如果.META.表中的每一行在内存中占大约1KB,且每个Region限制为128M,下图中的三层结构可以保存Regions的数目为(128M/1KB)*(128/1KB)=2^34个。
2. 搭建¶
2.1 环境准备¶
序列号 | IP地址 | 主机名 | 安装软件 | |
---|---|---|---|---|
1 | 192.168.186.10 | master | hbase |
|
2 | 192.168.186.11 | slave1 | `hbase | |
3 | 192.168.186.12 | slave2 | hbase |
仍然是这三台机器
2.2 安装jdk¶
之前安装了,省略。
[root@master ~]# java -version java version "1.8.0_172" Java(TM) SE Runtime Environment (build 1.8.0_172-b11) Java HotSpot(TM) 64-Bit Server VM (build 25.172-b11, mixed mode) [root@slave1 ~]# java -version java version "1.8.0_172" Java(TM) SE Runtime Environment (build 1.8.0_172-b11) Java HotSpot(TM) 64-Bit Server VM (build 25.172-b11, mixed mode) [root@slave2 ~]# java -version java version "1.8.0_172" Java(TM) SE Runtime Environment (build 1.8.0_172-b11) Java HotSpot(TM) 64-Bit Server VM (build 25.172-b11, mixed mode)
2.3 部署¶
[root@master ~]# cd /usr/local/src/ [root@master src]# rz -E rz waiting to receive. [root@master src]# tar xf hbase-1.3.1-bin.tar.gz [root@master src]# mv hbase-1.3.1 /usr/local/ [root@master src]# cd /usr/local/ [root@master local]# ln -sf hbase-1.3.1 hbase
3.4 配置¶
进入conf目录,复制zoo-sample.cfg重命名为zoo.cfg,通过修改zoo.cfg来对zookeeper进行配置。这个名字固定写死,因为zookeeper启动会检查这个文件,根据这个配置文件里的信息来启动服务。
[root@master local]# cd /usr/local/hbase/conf [root@master conf]# vim hbase-site.xml [root@master conf]# cat hbase-site.xml <?xml version="1.0"?> <?xml-stylesheet type="text/xsl" href="configuration.xsl"?> <!-- /** * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ --> <configuration> <property> <name>hbase.tmp.dir</name> <value>/var/hbase</value> </property> <property> <name>hbase.rootdir</name> <value>hdfs://master:9000/hbase</value> </property> <property> <name>hbase.cluster.distributed</name> <value>true</value> </property> <property> <name>hbase.zookeeper.quorum</name> <value>master,slave1,slave2</value> </property> <property> <name>hbase.zookeeper.property.dataDir</name> <value>/usr/local/src/hbase/zookeeper</value> </property> <property> <name>hbase.master.info.port</name> <value>60010</value> </property> <property> <name>hbase.thrift.info.port</name> <value>9083</value> </property> </configuration>
hbase-default.xml
[root@master conf]# egrep -v '#|^$' hbase-env.sh export JAVA_HOME=/usr/local/jdk1.8.0_172 export CLASSPATH=.:$CLASSPATH:$JAVA_HOME/lib export HBASE_OPTS="-XX:+UseConcMarkSweepGC" export HBASE_MASTER_OPTS="$HBASE_MASTER_OPTS -XX:PermSize=128m -XX:MaxPermSize=128m" export HBASE_REGIONSERVER_OPTS="$HBASE_REGIONSERVER_OPTS -XX:PermSize=128m -XX:MaxPermSize=128m" export HBASE_MANAGES_ZK=false [root@master conf]# cat regionservers master slave1 slave2
3.5 配置环境变量¶
[root@master conf]# tail -4 /etc/profile export HBASE_HOME=/usr/local/hbase export HBASE_CLASSPATH=$HBASE_HOME/conf export HBASE_LOG_DIR=$HBASE_HOME/logs export PATH=$PATH:$HBASE_HOME/bin [root@master conf]# source /etc/profile
3.6 包分发和配置环境¶
[root@master ~]# rsync -az /usr/local/{hbase,hbase-1.3.1} slave1:/usr/local/ [root@master ~]# rsync -az /usr/local/{hbase,hbase-1.3.1} slave2:/usr/local/ [root@slave1 ~]# tail -4 /etc/profile export HBASE_HOME=/usr/local//hbase export HBASE_CLASSPATH=$HBASE_HOME/conf export HBASE_LOG_DIR=$HBASE_HOME/logs export PATH=$PATH:$HBASE_HOME/bin [root@slave1 ~]# source /etc/profile [root@slave2 ~]# tail -4 /etc/profile export HBASE_HOME=/usr/local//hbase export HBASE_CLASSPATH=$HBASE_HOME/conf export HBASE_LOG_DIR=$HBASE_HOME/logs export PATH=$PATH:$HBASE_HOME/bin [root@slave2 ~]# source /etc/profile
3.7 启动¶
在启动之前,我停止了storm和zookeeper。
[root@master sbin]# jps 16262 NameNode 16601 ResourceManager 16445 SecondaryNameNode 16877 Jps [root@slave1 conf]# jps 25749 Jps 25260 DataNode 25374 NodeManager [root@slave2 conf]# jps 14994 DataNode 15258 Jps 15099 NodeManager [root@master local]# start-hbase.sh slave1: starting zookeeper, logging to /usr/local/hbase/bin/../logs/hbase-root-zookeeper-slave1.out master: starting zookeeper, logging to /usr/local/hbase/bin/../logs/hbase-root-zookeeper-master.out slave2: starting zookeeper, logging to /usr/local/hbase/bin/../logs/hbase-root-zookeeper-slave2.out starting master, logging to /usr/local//hbase/logs/hbase-root-master-master.out Java HotSpot(TM) 64-Bit Server VM warning: ignoring option PermSize=128m; support was removed in 8.0 Java HotSpot(TM) 64-Bit Server VM warning: ignoring option MaxPermSize=128m; support was removed in 8.0 master: starting regionserver, logging to /usr/local/hbase/bin/../logs/hbase-root-regionserver-master.out slave1: starting regionserver, logging to /usr/local/hbase/bin/../logs/hbase-root-regionserver-slave1.out slave2: starting regionserver, logging to /usr/local/hbase/bin/../logs/hbase-root-regionserver-slave2.out master: Java HotSpot(TM) 64-Bit Server VM warning: ignoring option PermSize=128m; support was removed in 8.0 master: Java HotSpot(TM) 64-Bit Server VM warning: ignoring option MaxPermSize=128m; support was removed in 8.0 slave1: Java HotSpot(TM) 64-Bit Server VM warning: ignoring option PermSize=128m; support was removed in 8.0 slave1: Java HotSpot(TM) 64-Bit Server VM warning: ignoring option MaxPermSize=128m; support was removed in 8.0 slave2: Java HotSpot(TM) 64-Bit Server VM warning: ignoring option PermSize=128m; support was removed in 8.0 slave2: Java HotSpot(TM) 64-Bit Server VM warning: ignoring option MaxPermSize=128m; support was removed in 8.0 [root@master local]# jps 21699 NameNode 23941 HMaster 22039 ResourceManager 24073 HRegionServer 21882 SecondaryNameNode 23883 HQuorumPeer 24157 Jps [root@slave1 local]# jps 29409 DataNode 29523 NodeManager 31591 HQuorumPeer 31931 Jps 31663 HRegionServer [root@slave2 local]# jps 17186 HQuorumPeer 17491 Jps 16549 DataNode 17256 HRegionServer 16653 NodeManager
坑
现象: HBASE HMaster起不来,报错如下: [main] impl.MetricsSystemImpl: Source name ugi already exists! [main] master.HMasterCommandLine: Master exiting 解决: 我百度一圈,各种尝试,最后竟然是hadoop的hdfs和hbase兼容问题,我升级版本后解决。
3.8 测试¶
[root@master local]# hbase shell SLF4J: Class path contains multiple SLF4J bindings. SLF4J: Found binding in [jar:file:/usr/local/hbase-1.3.1/lib/slf4j-log4j12-1.7.5.jar!/org/slf4j/impl/StaticLoggerBinder.class] SLF4J: Found binding in [jar:file:/usr/local/hadoop-2.6.5/share/hadoop/common/lib/slf4j-log4j12-1.7.5.jar!/org/slf4j/impl/StaticLoggerBinder.class] SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation. SLF4J: Actual binding is of type [org.slf4j.impl.Log4jLoggerFactory] HBase Shell; enter 'help<RETURN>' for list of supported commands. Type "exit<RETURN>" to leave the HBase Shell Version 1.3.1, r930b9a55528fe45d8edce7af42fef2d35e77677a, Thu Apr 6 19:36:54 PDT 2017 hbase(main):001:0> status 1 active master, 0 backup masters, 3 servers, 0 dead, 0.6667 average load
- 新建表
create 'cmz_music_table' ,'meta_data','action'
hbase(main):003:0> create 'cmz_music_table' ,'meta_data','action' 0 row(s) in 1.4330 seconds => Hbase::Table - cmz_music_table hbase(main):004:0> list TABLE cmz_music_table 1 row(s) in 0.0430 seconds => ["cmz_music_table"]
- 查看表信息
describe 'cmz_music_table'
详细操作
hbase(main):008:0> describe 'cmz_music_table' Table cmz_music_table is ENABLED cmz_music_table COLUMN FAMILIES DESCRIPTION {NAME => 'action', BLOOMFILTER => 'ROW', VERSIONS => '1', IN_MEMORY => 'false', KEEP_DELETED_CELLS => 'FALSE', DATA_BLOCK_ENCODING => 'NONE', TTL => 'FOREVER', COMPRESSION => 'NONE', MIN_VERSIONS = > '0', BLOCKCACHE => 'true', BLOCKSIZE => '65536', REPLICATION_SCOPE => '0'} {NAME => 'meta_data', BLOOMFILTER => 'ROW', VERSIONS => '1', IN_MEMORY => 'false', KEEP_DELETED_CELLS => 'FALSE', DATA_BLOCK_ENCODING => 'NONE', TTL => 'FOREVER', COMPRESSION => 'NONE', MIN_VERSION S => '0', BLOCKCACHE => 'true', BLOCKSIZE => '65536', REPLICATION_SCOPE => '0'} 2 row(s) in 0.0280 seconds