15.HBase基础

1. HBase介绍,Hbase是什么?

HBase -- Hadoop Database ,是一个高可靠、高性能、面向列、可伸缩的分布式存储系统。Hbase来源于Google的论文“Bigtable: 一个结构化数据的分布式存储系统”。HBase实际上是Hadoop的一个数据库系统,它的主要作用和传统数据库系统一样存储数据和检索数据。

传统关系型数据库的一些问题:
1) 传统的RDBMS关系型数据库存储一定量数据时没有问题,但是在存储海量数据(PB、TB级别),传统数据库无法支撑。
2) 性能差(数据量很大时)。
3) 面向行的,架构不够弹性,不能任意增加列。

Hbase和传统数据库的表结构的差异(Hbase不同于传统RDBMS,是面向列的):
传统数据库的表结构:


传统数据库表结构.png

hbase表结构:


hbase表结构.png

官方实例:表结构.png

2. HBase架构设计

Hbase运行在Hadoop文件系统HDFS上,是建立在HDFS上的列式存储数据库。


HBase架构.png
  1. Master:Hbase的主节点(集群中的某一台服务器),协调客户端应用程序与RegionServer的关系,监控和记录元数据的变化和管理。
  2. RegionServer:是Hbase的从节点,用region形式处理实际的表。Region是Hbase表的基础单元组件,存储了分布式表。Hbase集群利用Master和RegionServer来协同工作。
  3. Zookeeper:在Hbase中,选举集群主节点Master,以便跟踪可用的在线服务器,同时维护集群的元数据。一般安装多个,用于提供Master的高可用性。
  4. Clinet:使用HBase RPC机制与Master和RegionServer通信。对于管理类操作(DDL操作)与Master通信,对于数据读写类操作与RegionServer通信。

通常情况下,Master和Hadoop的Namenode进程运行在同一主机上,与Datanode通信以读写Hdfs,RegionServer和Hadoop的datanode运行在同一台主机上。

HBase具有可扩展性的原因:

  1. 读取hdfs的数据,hdfs的扩展可以通过datanode的增加完成;
  2. 一个表的数据分成多个区域Region,每个区域都有一个专门的RegionServer负责数据管理及检索,而RegionServer像datanode一样可以随意增加(RegionServer运行在Datanode的机器上,可以和datanode一样多)。

3. HBase数据模型:

HBase不以关系设计为中心,可以根据需求随意增加字段。每行数据提供row_key做快速索引。

HBase表结构.png

行键:是每个记录的唯一键,它在内存或磁盘中是以字节数组保存的,没有数据类型的概念。行健的设计
列族:将相同功能或类型的列集合在一起成为列族。

除了上边几个概念外,还包括以下一些:
(1)版本:Hbase中没有Insert和Update,只有put。每put一次,就会产生一个版本,默认显示你最后一次put的内容(最新的版本),并且保留3个版本的记录。
(2)时间戳:表示数据插入到表中的时间。
(3)单元格:最基本的存储单元,在内部就是一个实际存储的值。插入单元格数据时,必须包括:rowkey + column family + column + timestamp : value。

HBase的Schema由表名和列族两项组成。另外,值结合版本信息转为字节数组存储在列中。

4. HBase环境搭建:

HBase分布式环境搭建,可以参考如下网址:
http://hbase.apache.org/book.html
角色规划:

HBase角色规划.png

HBase的单机模式不会使用HDFS系统,而是使用本地文件系统file://来存储数据。

(1)下载hbase对应的安装文件,并解压缩。

$ tar zxf hbase-0.98.6-cdh5.3.6.tar.gz -C /opt/modules/

(2)修改配置:
修改配置文件 conf/hbase-env.sh 增加Java环境变量,并且不使用HBase来管理Zookeeper:

export JAVA_HOME=/opt/modules/jdk1.7.0_67
export HBASE_MANAGES_ZK=false

修改HBase的主配置文件 conf/hbase-site.xml:

<configuration>
 <property>
    <name>hbase.rootdir</name>
    <value>hdfs://hadoop-senior01.pmpa.com:8020/hbase</value>
</property>
<property>
      <name>hbase.cluster.distributed</name>
      <value>true</value>
</property>
<property>
      <name>hbase.zookeeper.quorum</name>
      <value>hadoop-senior01.pmpa.com,hadoop-senior02.pmpa.com,hadoop-senior03.pmpa.com</value>
</property>
</configuration>

说明:

  1. hdfs的8020端口,接收Client连接的RPC端口,用于获取文件系统metadata信息。
  2. 配置hbase.rootdir属性时,不需要创建相应的目录,否则就变成了migration。

修改配置文件conf/regionservers ,添写regionserver的ip。

hadoop-senior01.pmpa.com
hadoop-senior02.pmpa.com
hadoop-senior03.pmpa.com

修改配置文件conf/backup-masters,添加作为backup master角色的主机IP。

hadoop-senior02.pmpa.com

将配置复制到其他两个主机上:

$ scp -r hbase-0.98.6-cdh5.3.6/ natty@hadoop-senior02.pmpa.com:/opt/modules/
$ scp -r hbase-0.98.6-cdh5.3.6/ natty@hadoop-senior03.pmpa.com:/opt/modules/

(3)启动HBase,测试安装:
首先,需要在三台主机启动Zookeeper服务。

$ bin/zkServer.sh start

启动hadoop集群的各个角色:

$ sbin/start-dfs.sh
$ sbin/start-yarn.sh 
$ sbin/mr-jobhistory-daemon.sh start historyserver

在启动HBase之前,一定确保没有HBase进程(例如:HMaster, HRegionServer, HQuorumPeer)存在,否则会出问题。使用脚本bin/start-hbase.sh来启动Hbase。

$ bin/start-hbase.sh 

当然,也可以分角色启动HBase,分别单独启动master和regionserver,启动方法如下:

$ bin/hbase-daemon.sh start master
$ bin/hbase-daemon.sh start regionserver

查看进程是否存在:
senior01的进程角色(Master、Regionserver):

2957 QuorumPeerMain
3203 DataNode
3730 HMaster
3450 NodeManager
4120 Jps
3090 NameNode
3822 HRegionServer

senior02的进程角色(Backup Master、Regionserver):

3113 HMaster
2400 QuorumPeerMain
3281 Jps
2504 ResourceManager
2606 NodeManager
3043 HRegionServer

senior03的进程角色(Regionserver):

2422 QuorumPeerMain
3202 Jps
2561 SecondaryNameNode
3037 HRegionServer
2666 NodeManager
2828 JobHistoryServer
2486 DataNode

至此,HBase的分布式模式搭建完成。

5. HBase Shell 基本使用:

(1)在启动了HBase之后,输入$ bin/hbase 可以获得很多参数:

  shell           Run the HBase shell
  hbck            Run the hbase 'fsck' tool
  hlog            Write-ahead-log analyzer
  hfile           Store file analyzer
  zkcli           Run the ZooKeeper shell
  upgrade         Upgrade hbase
  master          Run an HBase HMaster node
  regionserver    Run an HBase HRegionServer node
  zookeeper       Run a Zookeeper server
  rest            Run an HBase REST server
  thrift          Run the HBase Thrift server
  thrift2         Run the HBase Thrift2 server
  clean           Run the HBase clean up script
  classpath       Dump hbase CLASSPATH
  mapredcp        Dump CLASSPATH entries required by mapreduce
  pe              Run PerformanceEvaluation
  ltt             Run LoadTestTool
  version         Print the version
  CLASSNAME       Run the class named CLASSNAME

其中,shell参数可以进入hbase 的shell命令行界面。
hlog参数很重要,可以分析和查看hbase的日志。预先写日志(二进制日志文件),在客户端往HBase写操作前记录日志。HBase与传统数据库有很大区别,写操作远远多于读操作(W:R约等于10:1)。同时, write-ahead log也可以防止写丢失。

(2)启动HBase的shell命令行:

$ bin/hbase shell

bin/hbase 命令有很多选项,直接输入命令 bin/hbase 可以查看所有选项的帮助。例如,查看hbase版本:

$ bin/hbase version

HBase的命令行模式不支持退格键,输入了错的命令后无法修改,所以需要首先解决这个问题。我使用的SecureCRT终端,下面是SecureCRT的解决方案:
选项 --> 会话选项 -->终端 --> 仿真 --> 终端项选择“Linux”
做了上述配置后,可以使用 Ctrl+删除键(backspace) 在HBase shell中做退格操作。
(3)hbase shell命令:
HBase中没有数据库的概念,只有命名空间(相当于数据库的概念)。

  • 使用help命令查看命令帮助(有命令 和 命令组 的概念):
hbase(main):001:0> help
  • 如果要查看create命令如何使用(查看其它命令帮助也一样),直接在shell命令行中输入 create:
hbase(main):002:0> create

从给出的帮助信息可以找到: hbase> create 'ns1:t1', {NAME => 'f1', VERSIONS => 5} 。其中ns1是命名空间、t1是表名、f1是列族名(可以声明多个列族,每个大括号内是一个列族的信息)。

  • 创建user表、user1表;并查看所有的表(使用list):
hbase(main):003:0> create 'user','info'
hbase(main):004:0> create 'user1',{NAME => 'info1',VERSIONS => 5}
hbase(main):005:0> list

创建完表之后,从下图可以看到:每个HBase的表,在HDFS上对应一个目录。


HBase表在HDFS上的位置.png

在创建表时我没有指定namespace,默认会放在default 命名空间上。hbase命名空间是保存元数据信息的namespace。

  • 查看表的信息:
hbase(main):006:0> describe 'user1'
  • 向表中插入数据,使用put命令:
hbase(main):007:0> put
hbase(main):009:0> put 'user','10001','info:name', 'Jackson'
hbase(main):010:0> put 'user','10001','info:age','31'
hbase(main):011:0> put 'user','10001','info:sex','male'
hbase(main):012:0> put 'user','10001','info:address','beijing'
hbase(main):016:0> put 'user','10002','info:name', 'Lucy'
hbase(main):017:0> put 'user','10002','info:sex', 'female'
hbase(main):018:0> put 'user','10003','info:name', 'Honda'

查看put命令帮助得到put的语法:hbase> put 't1', 'r1', 'c1', 'value' t1:表名;r1:行键;c1:列名;'value' 是值。

  • 下面查看数据,可以使用get和scan两个命令:
hbase(main):013:0> get 'user','10001'
hbase(main):014:0> scan 'user'
hbase(main):023:0> scan 'user', {COLUMNS => ['info:name','info:age']}
hbase(main):025:0> scan 'user', {STARTROW=>'10001',STOPROW=>'10002'}

get命令一般根据行键获取单条结果。
scan命令是范围扫描,查看整个表。同时,可以在scan命令中限定范围来查找,STARTROW、STOPROW选项是很常用的,这两个选项需要注意的一点是,这个区间是左闭右开的,也就是“[ STARTROW,STOPROW )”,这点需要注意。
在scan数据时,可以通过STARTROW=> 和ENDROW=>来指定范围检索,而且支持正则表达式(前缀匹配)。

  • 删除表,在删除(drop)前需要先禁用(disable)该表:
hbase(main):027:0> disable 'user1'
hbase(main):028:0> drop 'user1'
  • 删除表中的数据(这里新做了一张表user2,并添加了一些数据来做测试):
    测试数据如下:
ROW        COLUMN+CELL                                                                                      
 01           column=info:name, timestamp=1493743972426, value=zhangsan                  
 02           column=info:name, timestamp=1493743985575, value=lisi       
 02           column=info:sex, timestamp=1493744013788, value=male        
 03           column=info:name, timestamp=1493743996438, value=wangwu

1.删除行中的某个列值:

hbase(main):036:0> delete 'user2','02','info:sex'

上边命令删除了行健为02的数据行的 info:sex列。
2.删除整行:

hbase(main):040:0> deleteall 'user2','03'

3.清空表:

hbase(main):043:0> truncate 'user2'
Truncating 'user2' table (it may take a while):
 - Disabling table...
 - Dropping table...
 - Creating table...
0 row(s) in 2.0170 seconds
  • 创建命名空间:
hbase(main):043:0> create namespace 'ns1'
hbase(main):043:0> create table 'ns1:table1','info'
hbase(main):043:0> list
hbase(main):043:0> list_namespace 'ns1'
hbase(main):043:0> list_namespace_tables 'ns1'

HBase的命名空间类似于RDBMS中的数据库的概念,可以在命名空间下创建表和管理表。每个命名空间对应于HDFS上的一个目录,这个命名空间下的表的数据也存在这个目录下。
上边命令create namespace新建了一个命名空间ns1, 在ns1空间下创建一个有一个列族info的表table1。下面列出某个命名空间下的所有表。
默认情况,有2个命名空间,分别是default和HBase。默认建的表都在default空间,HBase空间是系统命名空间。HBase空间下有2张表,一个是meta表(用来存储元数据,用户表region的相关信息),一个是namespace表(用来存储命名空间)。

6. HBase表的物理模型:

1. HBase存储结构:

HBase是按照列存储的,每个Column Family存储在单独的一个HDFS文件上。表格中的行按照Rowkey字典序进行排列,表格在行的方向上被分隔为多个Region(按行进行分隔)

按列存储,按行分隔成多个Region.png

HBase有一个典型的应用场景:查询历史订单。订单数据是海量的,使用RDBMS会非常缓慢。例如查询近10天的订单,使用HBase能完美解决。
一般地,HBase表并不多但都是很大的表(不是数据量大,而是大宽表,列可以任意添加)。

2. HBase如何来划分Region?

HBase提供了两种方式来划分Region。
第一种方式,在创建表的时候划定范围。请看下例:
在HBase shell中,查看create命令的帮助,可以看到这样一个实例:

create 'ns1:t1', 'f1', SPLITS => ['10', '20', '30', '40']

SPLITS关键字会按照RowKey划分五个Region。rowkey在0到10的数据在region1,rowkey在10到20的在region2,依此类推。
第二种方式,按照阈值自动划分。请看下例:
根据阈值自动划分。Region按大小分割,每个表开始只有一个Region,随着数据增多,当增大到一个阈值时,Region就等分成2个新Region(出现新的Region),之后出现越来越多Region。

逻辑架构.png

如上图,表A按照行被划分成相等的4个Region,RegionServer管理Region。每个RegionServer可以管理不同表格的Region,而且每个RegionServer管理的Region数量是相同的。
当要读取region3的数据时,就是RegionServer86来提供服务,但是region3的数据块不一定在RegionServer86上,因为数据块的存储单位是block(HDFS概念),可能存储在多个datanode上。上图中,类似Region4和RegionServer367的对应关系称为元数据,存储在Zookeeper中。

Paste_Image.png

Region是HBase中分布式存储和负载均衡的最小单元,但是不是存储的最小单元(底层存储)。

  • Region由一个或多个Store组成,每个Store保存一个Column Family列族。
  • 每个Store又由有一个memStore0到多个StoreFile组成。
  • memStore存储在内存中,StoreFile存储在HDFS上。
  • 每个Region还包含一个HLog(预写式日志Write-Ahead-Log,当存储数据时只有把数据写入WAL和每个Store中的memStore才算成功)
Region元素.png

3.HBase处理单点故障:

以上边的图为例,RegionServer367发生了宕机情况,将进行以下流程:
Zookeeper实时监控RegionServer,发现RegionServer367宕机。通知Master,Master会重新指派RegionServer7来管理原来RegionServer367管理的Regions。

7.HBase数据读写流程:

1. HBase检索流程

下图是HBase数据的检索流程图:


HBase检索流程.png

读取数据流程:
(1)客户端(Client)需要访问Zookeeper集群,获得元数据信息(表信息,每张表的Region信息,StartKey、EndKey)。
(2)Client找到Region对应的 RegionServer。这个信息存在hbase:meta中(Region和RegionServer的对应关系,也就是某个Region由哪个RegionServer来管理,存在hbase:meta表中)
(3)RegionServer响应客户端请求。

Region对应于哪个RegionServer服务器,这个信息在元数据表中存储。打开HBase的管理页面(60010端口):


HBase管理页面.png

在Tables一栏中,有“User Tables” 和 “Catalog Tables”,查看后者:


Tables信息.png

写数据流程:
(1)访问Zookeeper集群,获取该数据应该写入哪个Region中。
(2)向region所在的Region Server发起写请求
(3)RegionServer把数据先写进HLog(WAL),然后写入memStore(根据阈值flush到磁盘默认128MB)
(4)当memStore达到阈值,写入HFile,HFile再合并为storeFile(每个storeFile达到阈值合并,compact)
(5)当StoreFile达到阈值,合并成新的更大的StoreFile
(6)如果当前的Region达到阈值,当前Region会划分为2个新的Region(split)
有3个核心点:flush 、compact、split

2. HBase表

HBase的表分为User Tables(用户表) 和 Catalog Tables(系统自带表)。
HBase的所有表数据都存放在HDFS的/hbase/data目录下,该目录下的每一个目录是一个命名空间(类似于RDBMS的数据库概念),如下图有2个命名空间(default和hbase),用户建的表默认存在default命名空间。


HBase表在HDFS上的存储目录.png

下边的命令可以查看HBase上的命名空间:

hbase(main):005:0> list_namespace

查看某个命名空间下的所有的表(查看hbase命名空间下的所有表):

hbase(main):007:0> list_namespace_tables 'hbase'

查看meta表信息:

hbase(main):008:0> scan 'hbase:meta'

用户表由Region组成,Region信息存储在hbase:meta中。

8. HBase数据存储

1. HBase能高速实现数据读写源于HBase数据存储

  • (读)连接Zookeeper,从Zookeeper中找要读的数据。需要知道Rowkey在表中region的位置。
  • 客户端查找HRegionServer,HRegionServer管理众多region。(通过Region和RegionServer的对应关系查找)
  • HMaser也需要连接Zookeeper,作用是HMaster需要知道哪些HRegionServer是活动的及位置,然后管理HRegionServer。(HRegionServer的上下线)
  • HBase内部是把数据写到HDFS上的,DFS有客户端。
  • Region中包含HLog、Store。一个列族对应一个Store。Store中有多个MemStore及StoreFile。StoreFile是对HFile的封装。StoreFile真正存储在HDFS上。
  • 所以写数据时先往HLog上写一份,再往MemStore上写一份。当MemStore达到一定大小则往StoreFile上写。若MemStore丢失,从HLog上恢复。
  • 读数据时先到MemStore上读,再到StoreFile上读,之后合并。

2. HBase数据存储

HBase的所有文件都存在HDFS上主要包括HFile(Hadoop的二进制格式文件)和HLog File(Hadoop的Sequence File)。
HRegionServer内部管理一系列HRegion对象,每个对象对应table中的一个region。最好将IO特性一致的列设计为一个Column Family。

StoreFile合并.png

StoreFile在合并时同时进行版本合并数据删除

  • 当StoreFiles Compact后,逐步形成越来越大的StoreFile。
  • 单个StoreFile大小超过阈值后,触发split操作,把当前region分成2个region,region会下线,新分出的2个孩子region会被HMaster分配到相应的HRegionServer上,使得原先1个Region的压力得以分流到2个Region上。

推荐阅读更多精彩内容