HBase 入门与 Shell 基本操作


简介

HBase 是一个开源的非关系型分布式数据库(NoSQL),它参考了谷歌的 BigTable 建模,实现的编程语言为Java。它是Apache软件基金会的Hadoop项目的一部分,运行于HDFS文件系统之上,为 Hadoop提供类似于BigTable 规模的服务。因此,它可以对稀疏文件提供极高的容错率。

HBase在列上实现了BigTable论文提到的压缩算法、内存操作和布隆过滤器。HBase的表能够作为MapReduce任务的输入和输出,可以通过Java API来访问数据,也可以通过REST、Avro 或者 Thrift 的API来访问。

在 Eric Brewer的CAP理论中,HBase属于CP类型的系统。

HBase 逻辑结构

HBase 可以用于存储多种结构的数据,以 JSON 为例,存储的数据为:

{
    "row_key1": {
        "personal_info": {
            "name": "张三",
            "city": "北京",
            "phone": "131********"
        },
        "office_info": {
            "tel": "010-111111",
            "address": "上海"
        }
    },
    "row_key11": {
        "personal_info": {
            "city": "上海",
            "phone": "132********"
        },
        "office_info": {
            "tel": "010-222222"
        }
    },
    "row_key2": {
        "personal_info": {
            "name": "王五",
            "city": "广州"
        },
        "office_info": {
            "tel": "010-333333",
            "address": "上海"
        }
    }
}

存储数据稀疏,数据存储多维,不同的行具有不同的列。数据存储整体有序,按照RowKey的字典序排列,RowKey为Byte数组:

HBase 数据模型

在HBase中,数据存储在具有行和列的表中,这是与关系数据库类似的模型,但与之不同的是其具备结构松散、多维有序映射的特点,它的索引排序键由行+列+时间戳组成,HBase表可以被看做一个“稀疏的、分布式的、持久的、多维度有序Map”。

Namespace(命名空间)

命名空间,类似于关系型数据库的 database 概念,每个命名空间下有多个表。HBase 两个自带的命名空间,分别是 hbasedefault,hbase 中存放的是 HBase 内置的表,default 表是用户默认使用的命名空间。Namespace可以帮助用户在多租户场景下做到更好的资源和数据隔离。

Table(表)

类似于关系型数据库的表概念。不同的是,HBase 定义表时只需要声明列族即可,不需要声明具体的列。因为数据存储是稀疏的,所有往 HBase 写入数据时,字段可以动态、按需指定。因此,和关系型数据库相比,HBase 能够轻松应对字段变更的场景。

Row(行)

HBase 中的一行包含一个行键(RowKey)和一个或多个与其相关的值的列(Column)。在存储行时,行按字母顺序排序。出于这个原因,行键的设计非常重要。目标是以相关行相互靠近的方式存储数据。常用的行键模式是网站域。如果你的行键是域名,则你可能应该将它们存储在相反的位置(org.apache.www,org.apache.mail,org.apache.jira)。这样表中的所有Apache域都彼此靠近,而不是根据子域的第一个字母分布。

Column Family(列族)

HBase 中的列被分组为列族。 列族的所有列成员都具有相同的前缀。 例如,列 personal_info:namepersonal_info:city 都是 personal_info 列族的成员。 冒号字符(:)列族列族限定符(列名 )分隔开来。 列族前缀必须由可打印字符组成。 列族限定符,可以由任意字节组成。 列族必须在模式定义时预先声明,而列不需要在模式时定义,但可以在表启动和运行时即时创建。

由于性能原因,列族在物理上共同存在一组列和它们的值。在HBase中每个列族都有一组存储属性,例如其值是否应缓存在内存中,数据如何压缩或其行编码是如何编码的等等。表中的每一行都有相同的列族,但给定的行可能不会在给定的列族中存储任何内容。列族一旦确定后,就不能轻易修改,因为它会影响到HBase真实的物理存储结构,但是列族中的列标识(Column Qualifier)以及其对应的值可以动态增删。

Column Qualifier(列族限定符)

列限定符被添加到列族中,以提供给定数据段的索引。例如:鉴于列族的content,列限定符可能是 content:html,而另一个可能是content:pdf。虽然列族在创建表时是固定的,但列限定符是可变的,并且在行之间可能差别很大。

Column(列)

HBase 中的每个列都由一个 Column Family(列族)和一个 Column Qualifier(列族限定符或叫列名)组成,它们由冒号(:)字符分隔。例如 personal_info:namepersonal_info:city。建表时,只需指明列族,而列限定符无需预先定义。

TimeStamp (时间戳)

用于标识数据的不同版本(version),每条数据写入时,系统会自动为其加上该字段,其值为写入 HBase 的时间。

Cell(单元格)

单元格是行、列族和列限定符的组合,并且包含值和时间戳,它表示值的版本。由 {rowkey, column Family:column Qualifier, timestamp} 唯一确定HBase 中的一个单元格。单元格中的数据全部是字节码形式存储。

HBase Shell 操作

Shell的使用命令更多请参见Apache HBase Shell介绍

进入和退出Shell环境

  • 进入容器

    docker exec -it hbase-master /bin/bash
  • 执行以下命令进入Shell环境:

    /opt/hbase-1.2.6/bin/hbase shell
  • 执行以下命令退出Shell环境:

    quit
  • 使用help命令查看基本命令和对应的使用方法:

    help

namespace

  • 创建命名空间

    使用特定的 help 语法能够查看命令如何使用:

    hbase(main):002:0> help 'create_namespace'
    Create namespace; pass namespace name,
    and optionally a dictionary of namespace configuration.
    Examples:
    
      hbase> create_namespace 'ns1'
      hbase> create_namespace 'ns1', {'PROPERTY_NAME'=>'PROPERTY_VALUE'}

    创建命名空间 bigdata:

    hbase(main):001:0> create_namespace 'bigdata'
    0 row(s) in 0.2100 seconds
  • 查看所有的命名空间

    hbase(main):002:0> list_namespace
    NAMESPACE                                                                                                                      
    bigdata                                                                                                                        
    default                                                                                                                        
    hbase                                                                                                                          
    3 row(s) in 0.0220 seconds

DDL

数据定义语句:

create: 用于创建一个表。
list: 用于列出HBase的所有表。
disable: 用于禁用表。
is_disabled: 用于验证表是否被禁用。
enable: 用于启用一个表。
is_enabled: 用于验证表是否已启用。
describe: 用于提供了一个表的描述。
alter: 用于改变一个表。
exists: 用于验证表是否存在。
drop: 用于从HBase中删除表。
  • 创建表

    hbase(main):008:0> help 'create'

    在 bigdata 命名空间中创建表格 student,两个列族 info 和 msg。info 列族数据维护的版本数为 5 个,如果不写默认版本数为 1。

    hbase(main):003:0> create 'bigdata:student', {NAME => 'info', VERSIONS => 5}, {NAME => 'msg'}
    0 row(s) in 1.2750 seconds
    
    => Hbase::Table - bigdata:student

    如果创建表格只有一个列族,没有列族属性,可以简写。如果不写命名空间,使用默认的命名空间 default。

    hbase(main):004:0> create 'student1','info'
    0 row(s) in 1.2220 seconds
    
    => Hbase::Table - student1
  • 查看表

    查看表有两个命令:list 和 describe

    查看所有的表名:

    hbase(main):005:0> list
    TABLE                                                                                                                          
    bigdata:student                                                                                                                
    student1                                                                                                                       
    test                                                                                                                           
    3 row(s) in 0.0180 seconds
    
    => ["bigdata:student", "student1", "test"]

    查看一个表的详情:

    hbase(main):009:0> describe 'bigdata:student'
    Table bigdata:student is ENABLED                                                                                               
    bigdata:student                                                                                                                
    COLUMN FAMILIES DESCRIPTION                                                                                                    
    {NAME => 'info', BLOOMFILTER => 'ROW', VERSIONS => '5', IN_MEMORY => 'false', KEEP_DELETED_CELLS => 'FALSE', DATA_BLOCK_ENCODIN
    G => 'NONE', TTL => 'FOREVER', COMPRESSION => 'NONE', MIN_VERSIONS => '0', BLOCKCACHE => 'true', BLOCKSIZE => '65536', REPLICAT
    ION_SCOPE => '0'}                                                                                                              
    {NAME => 'msg', 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', REPLICATI
    ON_SCOPE => '0'}                                                                                                               
    2 row(s) in 0.0280 seconds
  • 修改表

    表名创建时写的所有和列族相关的信息,都可以后续通过 alter 修改,包括增加和删除列族。

    增加列族和修改信息都使用覆盖的方法:

    hbase(main):002:0>  alter 'student1', { NAME => 'f1', VERSIONS => 3 }
    Updating all regions with the new schema...
    0/1 regions updated.
    1/1 regions updated.
    Done.
    0 row(s) in 3.3610 seconds

    查看修改后的表:

    hbase(main):003:0> describe 'student1'
    Table student1 is ENABLED                                                                                                      
    student1                                                                                                                       
    COLUMN FAMILIES DESCRIPTION                                                                                                    
    {NAME => 'f1', BLOOMFILTER => 'ROW', VERSIONS => '3', IN_MEMORY => 'false', KEEP_DELETED_CELLS => 'FALSE', DATA_BLOCK_ENCODING 
    => 'NONE', TTL => 'FOREVER', COMPRESSION => 'NONE', MIN_VERSIONS => '0', BLOCKCACHE => 'true', BLOCKSIZE => '65536', REPLICATIO
    N_SCOPE => '0'}                                                                                                                
    {NAME => 'info', BLOOMFILTER => 'ROW', VERSIONS => '1', IN_MEMORY => 'false', KEEP_DELETED_CELLS => 'FALSE', DATA_BLOCK_ENCODIN
    G => 'NONE', TTL => 'FOREVER', COMPRESSION => 'NONE', MIN_VERSIONS => '0', BLOCKCACHE => 'true', BLOCKSIZE => '65536', REPLICAT
    ION_SCOPE => '0'}                                                                                                              
    2 row(s) in 0.0190 seconds

    删除 student1 表中f1列族:

    hbase(main):005:0> alter 'student1', NAME => 'f1', METHOD => 'delete'
    Updating all regions with the new schema...
    1/1 regions updated.
    Done.
    0 row(s) in 2.4070 seconds

    或者:

    alter 'student1', 'delete' => 'f1'
  • 删除表

    shell 中删除表格,需要先将表格状态设置为不可用。

    hbase(main):007:0> disable 'student1'
    0 row(s) in 2.2580 seconds
    hbase(main):008:0> drop 'student1'
    0 row(s) in 1.2510 seconds

DML

数据操作语句:

put: 在指定的表/行/列中放置一个单元格值。
get: 用于取行或单元格的内容。
delete:用于删除表中的单元格值。
deleteall: 用于删除给定行的所有单元格。
scan: 用于扫描并返回表数据。
count: 用于计数并返回表中的行的数目。
truncate: 清空表中的数据,其内部实现是将指定的表下线、删除、重建,该操作会丢失Region分区
truncate_preserve:清空表中的数据,其内部实现是将指定的表下线、删除、重建,并且Region分区与旧表保留一致
  • 写入数据

    格式:

    put '命令空间:表名', '行号', '列族:列名', '值'

    在 HBase 中如果想要写入数据,只能添加结构中最底层的 cell。可以手动写入时间戳指定 cell 的版本,推荐不写默认使用当前的系统时间。如果重复写入相同 rowKey,相同列的数据,会写入多个版本进行覆盖。

    hbase(main):010:0> put 'bigdata:student', '1001', 'info:name', 'zhangsan'
    hbase(main):011:0> put 'bigdata:student', '1001', 'info:name', 'lisi'
    hbase(main):012:0> put 'bigdata:student', '1001', 'info:age', '30'
  • 读取数据

    读取数据的方法有两个:get 和 scan。

    get 最大范围是一行数据,也可以进行列的过滤,读取数据的结果为多行 cell。

    hbase(main):017:0> get 'bigdata:student', '1001'
    COLUMN                           CELL                                                                                          
     info:age                        timestamp=1672133429754, value=30                                                             
     info:name                       timestamp=1672133408519, value=lisi  

    进行列的过滤:

    hbase(main):018:0> get 'bigdata:student', '1001', {COLUMN => 'info:name'}
    COLUMN                           CELL                                                                                          
     info:name                       timestamp=1672133408519, value=lisi                                                           
    1 row(s) in 0.0070 seconds

    也可以修改读取 cell 的版本数,默认读取一个。最多能够读取当前列族设置的维护版本数。

    hbase(main):003:0* get 'bigdata:student', '1001', {COLUMN => 'info:name', VERSIONS => 5}
    COLUMN                           CELL                                                                                          
     info:name                       timestamp=1672133408519, value=lisi                                                           
     info:name                       timestamp=1672133380991, value=zhangsan   

    scan 是扫描数据,能够读取多行数据,不建议扫描过多的数据,推荐使用 startRow 和 stopRow 来控制读取的数据,默认范围左闭右开。

    hbase(main):006:0> scan 'bigdata:student',  {STARTROW => '1001', STOPROW =>'1002'} 
    ROW                              COLUMN+CELL                                                                                   
     1001                            column=info:age, timestamp=1672133429754, value=30                                            
     1001                            column=info:name, timestamp=1672133408519, value=lisi                                         
    1 row(s) in 0.0190 seconds
  • 删除数据

    删除数据的方法有两个:delete 和 deleteall。

    delete 表示删除一个版本的数据,即为 1 个 cell,不填写版本默认删除最新的一个版本。

    hbase(main):007:0> delete 'bigdata:student', '1001', 'info:name'
    0 row(s) in 0.1800 seconds

    deleteall 表示删除所有版本的数据,即为当前行当前列的多个 cell。

    执行命令会标记数据为要删除,不会直接将数据彻底删除,删除数据只在特定时期清理磁盘时进行

    hbase(main):010:0> deleteall 'bigdata:student', '1001', 'info:name' 
    0 row(s) in 0.0060 seconds

参考


文章作者: 张权
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 张权 !
评论
  目录