你好,游客 登录 注册 搜索
背景:
阅读新闻

HBase入门精要--百闻不如一Run

[日期:2016-07-25] 来源:百闻不如一Run  作者:Luo's Blog [字体: ]

HBase,基于Google Bigtable实现的开源、分布式、可伸缩的列式存储数据库,诞生于Hadoop,也是Hadoop生态的重要一环,如今作为一个Apache顶级项目,早已经不能将其仅仅看作Hadoop的一部分,基于Storm,Spark等框架的数据处理方案中,都有它的身影,可以说它已经成为大数据工具箱中非常重要的一种数据存储工具,也因此必然会被很纳入很多人学习计划。

HBase

对于一个新技术的入门,我认为一种有效的学习方式是:

对其有简要认知后,通过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" : {
        111 : "value1",
        123 : "value2"
        },
      "column2" : {103 : "value3"}
    },
    "family2" : { ... }
  },
  "row2" : {
    "family3" : { ... }
  },
  // ...
}

而关于其 稀疏 这一特性,可以用下图来辅助理解:

图2 HBase的行和列所构成的更像标签,而不是表格

对于我们熟悉的关系型数据库,如MySQL,一张表中每一行都有相同的列,即使部分行的某些列不存储数据,也有消耗,如图中的NULL。而HBase,各行是相对独立的,可以有完全不同的列。

二.部署

如果最初阶段你需要HBase环境的主要目的是想熟悉对HBase的CRDU操作,那么看完 独立部署 后,可以直接跳到 三.基本操作 。

如果希望在部署环境过程中对HBase的架构也做一个简要了解,那么建议进行 伪分布式部署 ;如果伪分布式部署你能够很快完成,那么相信完全的分布式部署对你来说也并不困难,并且本文的主要目的是快速入门,因此不提供完全分布式部署的过程指引,如有需要,请参考官方指南 quickstart_fully_distributed 。

0. 基础条件

  • 需要Java,支持JDK7和JDK8
  • 需要ssh,伪分布式部署需要 ssh localhost 能正常连接,分布式部署需要配置各节点间的无密码登陆( ssh passwordless login )

注:1.0.0版本开始,HBase内部组件(HMaster,HRegionServer)的默认端口从60xxx变更为16xxx

1. 独立部署

如果想要最快速的搭建供你练习HBase数据库操作的环境,那么这可能是你想要的。

独立部署模式下,HBase的所有进程都运行在一个JVM中,数据直接存储在本地磁盘。

a. 下载安装包并解压

wget https://mirrors.tuna.tsinghua.edu.cn/apache/hbase/1.2.2/hbase-1.2.2-bin.tar.gz
tar 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/ 来访问。

2. 伪分布式部署

伪分布式模式下,HBase的所有组件还是运行在同一台主机,不同的是,每个组件独立运行在不同的JVM。更重要的是,我们可以在该模式下启动多个Regionserver和master,构成一个虚拟的分布式架构以供学习,这是很多 快速入门 文章所略过的重点。

该模式下,可以对接HDFS,但那涉及hadoop的部署,为以更短的时间达到当前阶段的目的,本文仍存储在本地磁盘。

a. HBase架构概要

图3 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.sh
    localhost: starting zookeeper, logging to /usr/local/hbase/bin/../logs/hbase-hbase-zookeeper-iZ25n0dx8rxZ.out
    starting master, logging to /usr/local/hbase/bin/../logs/hbase-hbase-master-iZ25n0dx8rxZ.out
    starting regionserver, logging to /usr/local/hbase/bin/../logs/hbase-hbase-1-regionserver-iZ25n0dx8rxZ.out
    

可以看到依次启动了zookeeper、master和regionserver,启动日志为 ./logs 路径下的 .log 文件。

  • 查看启动的进程以及占用的端口:

    [hbase@iZ25n0dx8rxZ logs]$ jps
    4610 HRegionServer
    4456 HQuorumPeer
    5338 Jps
    4522 HMaster
    [hbase@iZ25n0dx8rxZ logs]$ netstat -lnp|grep 4522
    tcp        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 4610
    tcp        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 4456
    tcp        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 1
      starting 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服务端口),以此类推。
    • web UI访问: http://ip:1601n/
    • 日志:启动日志在 ./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
      
    • 主节点切换:要观察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 directory
      INFO  [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的操作。

  1. 连接: ./bin/hbase shell

    [hbase@iZ25n0dx8rxZ hbase]$ ./bin/hbase shell
    HBase Shell; enter 'help<RETURN>' for list of supported commands.
    Type "exit<RETURN>" to leave the HBase Shell
    Version 1.2.2, r3f671c1ead70d249ea4598f1bbcc5151322b3a13, Fri Jul  1 08:28:55 CDT 2016
    hbase(main):001:0>
    
  2. 建表: create ‘test’, ‘cf1’, ‘cf2’ ,即[create ‘表名’, ‘列族名’,..],列族名可以有多个, list 用于查看有哪些表

    hbase(main):008:0> create 'test','cf1','cf2'
    0 row(s) in 1.2280 seconds
    => Hbase::Table - test
    hbase(main):009:0>
    
  3. 写数据: put ‘test’, ‘row1’, ‘cf1:c1’, ‘value1’ ,即[put ‘表名’,’行键’,’列族名:列名’,’数据’]

    hbase(main):001:0> put 'test','row1','cf1:c1','value1'
    0 row(s) in 0.3160 seconds
    hbase(main):002:0> put 'test','row1','cf1:c1','value2'
    0 row(s) in 0.3020 seconds
    
  4. 查看数据:

    • 全表数据: scan ‘test’ ,即[scan ‘表名’]
      hbase(main):001:0> scan 'test'
      ROW                                            COLUMN+CELL                                                                                                                             
       row1                                          column=cf1:c1, timestamp=1469277197280, value=value2                                                                                    
      1 row(s) in 0.2710 seconds
      hbase(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 seconds
      hbase(main):006:0>
      
  5. 版本数量:每个列族有一个单独的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}

  6. 删除数据:
    • 删除指定单元格: delete ‘test’,’row1’,’cf1:c1’,1469277197280 , 将删除指定版本以及比其更早的版本
    • 删除指定行的指定列: delete ‘test’,’row1’,’cf1:c1’
    • 删除整行: deleteall ‘test’,’row1’
  7. 禁用表: disable ‘test’ ,即[disable ‘表名’],在要删除表或者变更配置时,要先禁用该表。相应的,要重新启用该表,使用[enable ‘表名’]
  8. 删除表: drop ‘test’ ,即[drop ‘表名’]
  9. 退出HBase shell: exit 或者 quit
  10. 完整的命令列表,参考 hbase-shell-commands

四. 尾声

 

本文简要介绍了HBase的数据模型、快速搭建基本操作环境的步骤以及基于HBase shell的HBase数据库基本操作,旨在协助想要学习HBase的朋友快速进入到对HBase的操作和使用阶段,消除陌生感和距离感。在这之后,我们可能想问,真正应用在工程上的操作HBase的方式有哪些,HBase存取数据的完整过程是怎样的,怎样去设计一个适合的表结构,等等,那么,请带着这些问题继续你的HBase之路。





收藏 推荐 打印 | 录入:elainebo | 阅读:
本文评论   查看全部评论 (0)
表情: 表情 姓名: 字数
点评:
       
评论声明
  • 尊重网上道德,遵守中华人民共和国的各项有关法律法规
  • 承担一切因您的行为而直接或间接导致的民事或刑事法律责任
  • 本站管理人员有权保留或删除其管辖留言中的任意内容
  • 本站有权在网站内转载或引用您的评论
  • 参与本评论即表明您已经阅读并接受上述条款