HBase入门精要-百闻不如一Run - 简书 http://www.jianshu.com/p/6aeceb5d49cf
零.导读
HBase,基于Google Bigtable实现的开源、分布式、可伸缩的列式存储数据库,诞生于Hadoop,也是Hadoop生态的重要一环,如今作为一个Apache顶级项目,早已经不能将其仅仅看作Hadoop的一部分,基于Storm,Spark等框架的数据处理方案中,都有它的身影,可以说它已经成为大数据工具箱中非常重要的一种数据存储工具,也因此必然会被很纳入很多人学习计划。对于一个新技术的入门,我认为一种有效的学习方式是:
对其有简要认知后,通过Quick Start式的使用,获得直观的感知,消除距离感,然后再带着使用过程中的疑问去了解其背后的真相,最后支撑我们将其应用到实际工程。
我将消除距离感这一阶段,称之为百闻不如一Run。
本文分三部分带你完成对HBase的百闻不如一Run:数据模型概述、环境部署和基本操作。
版本:本文基于HBase 1.2.2 --Release date: 11/Jul/16
一. HBase数据模型
HBase是对Bigtable的开源实现,所以先来认识一下Bigtabl概念,引用Google's BigTable Paper中的精简描述:
A Bigtable is a sparse, distributed, persistent multidimensional sorted map.
The map is indexed by a row key, column key, and a timestamp; each value in the map is an uninterpreted array of bytes.
HBase的数据模型与此非常相似,用一张参考自上述论文的图来辅助理解:
图1 HBase某张表中某一行缩存储数据的一种可视化呈现
HBase的结构:
命名空间(namespace):0.96版本开始支持,是对多个表的逻辑分组,类似于关系数据库的database,在本文暂不关心。
表(table):一张表中包含若干行。
行(row):一行包括一个行键(row key)和若干列族,一张表中的行按照行键排序,并用行键作为索引。图1中展示了一个行键为row1的行。
列族(column family):每个列族包含若干个列,列族需要在建表时预定义,运行期间可以动态加入新的列。图1中的"data"、"meta"就是row1行中的两个列族。 在物理层面,HBase的数据存储是在列族这一层级进行组织,每个列族单独存储。
列(column):每个列都归属于某个列族,以列族名作为前缀,通常使用列族名:修饰符的形式来标识一个列,可以将其中的修饰符部分看作列名。图1中的"meta:mimetype"和"meta:size"即是列族meta中的成员。
单元格(cell):存储的每一个值存放在一个单元格中,由[行,列,版本号]来唯一指向一个单元格。图1中彩色标识的矩形块即可看作是一个单元格
版本(version):版本号默认是时间戳形式,同一列中可能包含若干单元格,这些单元格由版本号唯一区分,根据版本号降序排列,HBase查询时,如果不指定版本号,默认返回最新的值。图1中的t3,t6等即代表版本号。版本是HBase多维特性的表现。
Google论文中Bigtable描述为一个map,那么从Map的维度,用JSON格式,HBase的结构可以理解为:
{ // ... "row1" : { "family1" : { "column1" : { timestamp2 : "value1", timestamp3 : "value2" }, "column2" : {timestamp : "value3"} }, "family2" : { ... } }, "row2" : { "family3" : { ... } }, // ...}
而关于其稀疏这一特性,可以用下图来辅助理解:
对于我们熟悉的关系型数据库,如MySQL,一张表中每一行都有相同的列,即使部分行的某些列不存储数据,也有消耗,如图中的NULL。而HBase,各行是相对独立的,可以有完全不同的列。
二.部署
如果最初阶段你需要HBase环境的主要目的是想熟悉对HBase的CRDU操作,那么看完独立部署后,可以直接跳到三.基本操作。如果希望在部署环境过程中对HBase的架构也做一个简要了解,那么建议进行伪分布式部署;如果伪分布式部署你能够很快完成,那么相信完全的分布式部署对你来说也并不困难,并且本文的主要目的是快速入门,因此不提供完全分布式部署的过程指引,如有需要,请参考官方指南quickstart_fully_distributed。
- 基础条件
需要Java,支持JDK7和JDK8
需要ssh,伪分布式部署需要ssh localhost能正常连接,分布式部署需要配置各节点间的无密码登陆(ssh passwordless login)
注:1.0.0版本开始,HBase内部组件(HMaster,HRegionServer)的默认端口从60xxx变更为16xxx
- 独立部署
如果想要最快速的搭建供你练习HBase数据库操作的环境,那么这可能是你想要的。独立部署模式下,HBase的所有进程都运行在一个JVM中,数据直接存储在本地磁盘。
a. 下载安装包并解压
wget https://mirrors.tuna.tsinghua.edu.cn/apache/hbase/1.2.2/hbase-1.2.2-bin.tar.gztar zxvf hbase-1.2.2-bin.tar.gz -C target-dir
b. 配置
在/etc/hosts中配置localhost的地址:127.0.0.1 localhost
JAVA_HOME:在conf/hbase-env.sh中配置,例如:export JAVA_HOME=/usr/local/jdk
配置HBase和zookeeper保存数据的位置:如果不配置,默认写在/tmp目录下
在conf/hbase-site.xml.中配置,地址格式有两种,例如:<configuration> <property> <name>hbase.rootdir</name> <value>file:///home/hbase/hbase1.2.2</value> </property> <property> <name>hbase.zookeeper.property.dataDir</name> <value>/home/hbase/hbase1.2.2/zookeeper</value> </property></configuration>
c. 启动和停止可以直接在HBase安装目录运行bin/start-hbase.sh启动:
[hbase@iZ25n0dx8rxZh base]$ ./bin/start-hbase.sh starting master, logging to /usr/local/hbase/bin/../logs/hbase-hbase-master-iZ25n0dx8rxZ.out
启动日志默认位于./logs/hbase-[username]-master-[yourhostname].log,启动成功后,用jps命令可以看到名为HMaster的进程。接下来,你就可以使用hbase的shell来进行操作练习了。要停止hbase,使用bin/stop-hbase.sh。
d. UI访问Hbase内建了一个用Jetty提供服务的web UI页面来查看该HBase环境的各种信息,默认端口16010,尝试用http://hostip:16010/来访问。
- 伪分布式部署
伪分布式模式下,HBase的所有组件还是运行在同一台主机,不同的是,每个组件独立运行在不同的JVM。更重要的是,我们可以在该模式下启动多个Regionserver和master,构成一个虚拟的分布式架构以供学习,这是很多快速入门文章所略过的重点。该模式下,可以对接HDFS,但那涉及hadoop的部署,为以更短的时间达到当前阶段的目的,本文仍存储在本地磁盘。
a. HBase架构概要
作为入门阶段,先从粗粒度对HBase的架构进行简单了解:HMaster:主要负责监控集群、管理RegionServers的负责均衡等,可以用主-备形式部署多个Master。HRegionServers:负责响应用户的I/O操作请求,客户端对HBase读写数据是与RegionServer交互。Zookeeper:负责选举Master的主节点;服务注册;保存RegionServers的状态等。可以使用系统内建的zookeeper,也可以使用独立的zookeeper,只需要在配置文件中调整即可。HDFS:真正的数据持久层,并非必须是HDFS文件系统,但搭配HDFS是最佳选择,也是目前应用最广泛的选择。
b. 开始部署伪分布式模式下,需要保证ssh localhost能够成功连接(将HBase所属用户的publickey追加到其自身的authorized_keys中)。如果你跟随本文启动了独立模式的HBase,先将其停止。
开启分布式配置最基本的伪分布式配置,只需要在独立模式的配置基础上,追加开启分布式模式的配置,即将hbase.cluster.distributed配置为true,例如:<configuration> <property> <name>hbase.rootdir</name> <value>/home/hbase/hbase1.2.2</value> </property> <property> <name>hbase.zookeeper.property.dataDir</name> <value>file:///home/hbase/hbase1.2.2/zookeeper</value> </property> <property> <name>hbase.cluster.distributed</name> <value>true</value> </property> </configuration>
在安装目录运行bin/start-hbase.sh[hbase@iZ25n0dx8rxZ hbase]$ ./bin/start-hbase.shlocalhost: starting zookeeper, logging to /usr/local/hbase/bin/../logs/hbase-hbase-zookeeper-iZ25n0dx8rxZ.outstarting master, logging to /usr/local/hbase/bin/../logs/hbase-hbase-master-iZ25n0dx8rxZ.outstarting regionserver, logging to /usr/local/hbase/bin/../logs/hbase-hbase-1-regionserver-iZ25n0dx8rxZ.out
可以看到依次启动了zookeeper、master和regionserver,启动日志为./logs路径下的.log文件。
查看启动的进程以及占用的端口:
[hbase@iZ25n0dx8rxZ logs]$ jps4610 HRegionServer4456 HQuorumPeer5338 Jps4522 HMaster[hbase@iZ25n0dx8rxZ logs]$ netstat -lnp|grep 4522tcp 0 0 172.16.5.23:16000 0.0.0.0:* LISTEN 4522/java tcp 0 0 0.0.0.0:16010 0.0.0.0:* LISTEN 4522/java [hbase@iZ25n0dx8rxZ logs]$ netstat -lnp|grep 4610tcp 0 0 172.16.5.23:16201 0.0.0.0:* LISTEN 4610/java tcp 0 0 0.0.0.0:16301 0.0.0.0:* LISTEN 4610/java [root@iZ25n0dx8rxZ logs]$ netstat -lnp|grep 4456tcp 0 0 0.0.0.0:2188 0.0.0.0:* LISTEN 4456/java
HMaster占用16000(工作进程)和16010(Master的web UI服务端口)
HRegionServer占用16201(工作进程)和16301(Regionserver的web UI服务)
HQuorumPeer是HBase内建zookeeper进程,默认端口2181(即zookeeper的默认配置)。如果是独立的zookeeper,进程名是QuorumPeerxxx,没有第一个字母H。
启动和停止备份Master节点(backup HMaster):
运行./bin/local-master-backup.sh start n来启动一个备份节点,如:
[hbase@iZ25n0dx8rxZ hbase]$ ./bin/local-master-backup.sh start 1starting master, logging to /usr/local/hbase/bin/../logs/hbase-hbase-1-master-iZ25n0dx8rxZ.out
启动成功后,jps命令可以看到总共有两个HMaster进程。
端口:n用来指定占用的端口号,规则为[默认端口号+n],如例子中的./bin/local-master-backup.sh start 1所启动的HMaster占用16001(工作端口)和16011(web UI服务端口),以此类推。
日志:启动日志在./logs/hbase-[username]-n-master-[hostname].log,在上例的日志中,可以看到这样一行日志说明该节点目前是作为备用节点:master.ActiveMasterManager: Another master is the active master, iz25n0dx8rxz,16000,1469262015657; waiting to become the next active master
注意:如果使用1.2.2之前版本的安装包(如1.1.5),运行启动脚本后backup Master可能会因为端口被占用而无法启动,这是因为脚本里面,没有按照规则更改backup Master的工作端口,启动时仍然使用默认的16000,而该端口已经被前面启动的主节点占用。可以通过如下方法解决该问题:手动在./bin/local-master-backup.sh
脚本中为HBASE_MASTER_ARGS
赋值这句话内添加-D hbase.master.port=expr 16000 + $DN
来设置backup Master的工作端口,添加后这句话的完整内容如下:HBASE_MASTER_ARGS="-D hbase.master.port=expr 16000 + $DN
-D hbase.master.info.port=expr 16010 + $DN
-D hbase.regionserver.port=expr 16020 + $DN
-D hbase.regionserver.info.port=expr 16030 + $DN
--backup"
web UI访问地址:http://ip:1601n/
主节点切换:要观察HBase的Master组件主节点切换,可以使用kill -9 PID停止当前主节点(即最初启动的HMaster),此时刚启动的备份节点将切换为主节点,可以在备份节点的日志(./logs/hbase-[username]-1-master-[hostname].log)中看到如下内容:
INFO [iZ25n0dx8rxZ:16001.activeMasterManager] master.ActiveMasterManager: Deleting ZNode for /hbase/backup-masters/iz25n0dx8rxz,16001,1469267021567 from backup master directoryINFO [iZ25n0dx8rxZ:16001.activeMasterManager] master.ActiveMasterManager: Registered Active Master=iz25n0dx8rxz,16001,1469267021567
停止:使用./bin/local-master-backup.sh stop n来停止你的备份节点。
多备:可以一次启动多个backup HMaster,命令类似于./bin/local-master-backup.sh start x y z。
启动和停止额外的RegionServer运行额外RegionServer的方式与backup HMaster类似,启动:./bin/local-regionservers.sh start n,停止:./bin/local-regionservers.sh stop n
web UI访问地址:http://ip:1630n/
三. 基本操作
本节介绍使用HBase shell在直接在服务器上对HBase进行基本操作,HBase shell是在(J)Ruby的IRB的基础上增加了HBase特有的命令,遵循IRB的操作。
连接:./bin/hbase shell[hbase@iZ25n0dx8rxZ hbase]$ ./bin/hbase shellHBase Shell; enter 'help<RETURN>' for list of supported commands.Type "exit<RETURN>" to leave the HBase ShellVersion 1.2.2, r3f671c1ead70d249ea4598f1bbcc5151322b3a13, Fri Jul 1 08:28:55 CDT 2016hbase(main):001:0>
建表:create 'test', 'cf1', 'cf2',即[create '表名', '列族名',..],列族名可以有多个,list用于查看有哪些表
hbase(main):008:0> create 'test','cf1','cf2'0 row(s) in 1.2280 seconds=> Hbase::Table - testhbase(main):009:0>
写数据:put 'test', 'row1', 'cf1:c1', 'value1',即[put '表名','行键','列族名:列名','数据']
hbase(main):001:0> put 'test','row1','cf1:c1','value1'0 row(s) in 0.3160 secondshbase(main):002:0> put 'test','row1','cf1:c1','value2'0 row(s) in 0.3020 seconds
查看数据:全表数据:scan 'test',即[scan '表名']hbase(main):001:0> scan 'test'ROW COLUMN+CELLrow1 column=cf1:c1, timestamp=1469277197280, value=value2 1 row(s) in 0.2710 secondshbase(main):002:0>
可以看到在put时指定的属性之外,有一个timestamp属性来作为版本标识,我们查看全表数据时,row1的cf1:c1列中展示的值是我们后一次写入的value2,sacn和get在不指定版本时,得到的是最近版本的数据
指定行的数据:get 'test', 'row1',即[get '表名','行键']
指定版本的数据:hbase(main):005:0> get 'test','row1',{COLUMN=>'cf1:c1',TIMESTAMP=>1469277197280}COLUMN CELL cf1:c1 timestamp=1469277197280, value=value1 1 row(s) in 0.0270 secondshbase(main):006:0>
版本数量:每个列族有一个单独的VERSIONS属性,默认为1,可以在建表时指定:create 'test1',{NAME=>'cf1',VERSIONS=>3}
,代表该列族的每个列最多保存最近3个版本的数据,也可以通过alter来更新:alter 'test1',NAME=>'cf1',VERSIONS=>3
。查询数据时,可以通过设置VERSIONS来指定显示最近几个版本的数据(最大范围不超过该列族的VERSIONS属性值):get 'test','row1',{COLUMN=>'cf1:c1',VERSIONS=>2}
删除数据:删除指定单元格:delete 'test','row1','cf1:c1',1469277197280,将删除指定版本以及比其更早的版本
删除指定行的指定列:delete 'test','row1','cf1:c1'
删除整行: deleteall 'test','row1'
禁用表:disable 'test',即[disable '表名'],在要删除表或者变更配置时,要先禁用该表。相应的,要重新启用该表,使用[enable '表名']
删除表:drop 'test',即[drop '表名']
退出HBase shell:exit或者quit
完整的命令列表,参考hbase-shell-commands
四. 尾声
本文简要介绍了HBase的数据模型、快速搭建基本操作环境的步骤以及基于HBase shell的HBase数据库基本操作,旨在协助想要学习HBase的朋友快速进入到对HBase的操作和使用阶段,消除陌生感和距离感。在这之后,我们可能想问,真正应用在工程上的操作HBase的方式有哪些,HBase存取数据的完整过程是怎样的,怎样去设计一个适合的表结构,等等,那么,请带着这些问题继续你的HBase之路。
References
Apache HBase ™ Reference GuideGoogle's BigTable PaperUnderstanding HBase and BigTable