封面画师:画师JW     封面ID:79686153

1. HBase 简介

HBase 是一种分布性、可扩展、支持海量数据存储的 NoSQL 数据库。

1.1 HBase 的数据模型

逻辑上,HBase 的数据模型同关系型数据库类型,数据存储在一张表类,有行有列。但从 HBase 的底层物理存储结构(K-V)来看,HBase 更像一个 multi-dimensional map。

表结构(HBase 逻辑结构):

表组织结构

参考资料:HBase数据模型介绍

高表行多,宽表列多。

Region 是一张表的切片,而且是横向切片,相当于对宽表的切分。

store 是真正存储的内容。

HBase 物理存储结构:

HBase物理存储结构

如果需要在 Windows 和 Linux 上测试 HBase,由于时间戳的关系,请保证这两个系统的时间是一致的。当你查询某个列时,HBase 会返回时间戳较大的列的数据。

1.2 数据模型

Name Space

命名空间,类似于关系型数据库的 database 概念,每个命名空间下有多个表,HBase 有两个自带的命名空间,分别是 hbasedefault,hbase 中存放的是 HBase 内置的表,default 是用户默认使用的命名空间。

Region

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

表的切片。当数据不多时,表和 Region 是一一对应的关系,一个表就是一个 Region;当数据量大起来时,一个表就会被切分成多个 Region。除了系统自动帮我们切分,我们也可以进行手动切分。

HBase 中的列名相当于 HBase 中的数据。

Row

HBase 表中的每行数据都是由一个 RowKey 和多个 Column(列)组成,数据是按照 RowKey 的 字典顺序存储 的,并且查询数据时只能根据 RowKey 进行检索,所以 RowKey 的设计十分重要。

因此我们查询数据时,除了可以全局扫描,还可以范围扫描。

Column

HBase 中的每个列都是有 Column Family(列族)和 Column Qualifier(列限定符)进行限定,例如:info:name , info:age。建表时,只需指名列族,而列限定符无需预先定义。

Time Stamp

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

Cell

由{RowKey, column Family: column Qualifier, time stamp}唯一确定单元。cell 中的数据是没有类型的,全部是 字节码形式存储


1.3 基础架构

当 HMaster 节点挂掉后,做数据级别(表内数据)的增删改查是没问题的,但是做表级别的是不行的。

RegionServer 的作用:(DML)

Data:get、put、delete

Region:splitRegion、compactRegion

Master 的作用:(DDL)

Table:create、delete、alter

RegionServer:分配 regions 到每个 RegionServer,监控每个 RegionServer 的状态。

2. HBase 的安装

已单独写成笔记文档。

3. HBase Shell 操作

基本操作

进入 HBase 客户端命令行:

1
[root@db06 mofan]# bin/hbase shell

查看帮助命令:

1
Hbase(mian):001:0> help

查看当前数据库中 有哪些表:

1
Hbase(mian):002:0> list

3.1 DDL

创建表:

创建表时,必须指定至少一个列族。

1
2
hbase(main):002:0> create 'student','info'
hbase(main):003:0> create 'stu','info1','info2'

查看表具体信息:

1
hbase(main):004:0> desc 'student'

变更表信息(版本号):

1
hbase(main):009:0> alter 'student', {NAME=>'info',VERSIONS=>3}

删除表:

1
2
hbase(main):011:0> disable 'student'
hbase(main):012:0> drop 'student'

我们在删除表时,必须先 disable 表,即:表在可用状态(enable)下不能被删除,需要删除得将其设置成不可用状态(disable)。

查看当前所有命名空间:

1
hbase(main):014:0> list_namespace

创建命名空间:

1
hbase(main):015:0> create_namespace 'bigdata'

在指定的命名空间下创建一个表:

1
hbase(main):017:0> create 'bigdata:stu',"info"

删除命名空间:

1
2
3
hbase(main):019:0> disable 'bigdata:stu'
hbase(main):020:0> drop 'bigdata:stu'
hbase(main):021:0> drop_namespace 'bigdata

删除命名空间时,不许保证当前命名空间为空。

3.2 DML

增加 & 查询

向指定表内插入数据:

1
hbase(main):024:0> put 'stu','1001','info1:name','mofan'

解析:向 stu 表中插入数据,RowKey:1001,列族 info1 下的 name 列,插入值:mofan

查询表内所有数据:

1
hbase(main):025:0> scan 'stu'

我们查询出来的数据是按照 RowKey 的字典顺序进行升序排序的,这很重要!

查询表中指定条件的数据:

1
hbase(main):026:0> get 'stu','1001'

解析:查询 stu 表内,RowKey 为 1001 的数据

我们先插入几条数据备用:

1
2
3
4
5
hbase(main):027:0> put 'stu','1001','info1:sex','male'
hbase(main):028:0> put 'stu','1001','info2:addr','sichuan'
hbase(main):029:0> put 'stu','1002','info1:name','lisi'
hbase(main):030:0> put 'stu','1002','info1:phone','13212341234'
hbase(main):031:0> put 'stu','1003','info2:addr','beijing'
1
hbase(main):035:0> get 'stu','1001','info1:name'

解析:查询 stu 表内,RowKey 为 1001,列族 info1 下的 name 列的所有数据

1
hbase(main):037:0> get 'stu','1001','info1'

解析:查询 stu 表内,RowKey 为 1001,列族 info1 下的所有数据

使用 scan 进行范围扫描查询:

1
hbase(main):039:0> scan 'stu',{STARTROW=>'1001',STOPROW=>'1003'}

解析:查询 stu 表中,RowKey 大于等于 1001,小于 1003 的数据。[1001,1003),左闭右开。 我们在进行查询的时候,也可以只指定 STARTROW 或 STOPROW。

使用过滤器查询参考链接:HBase基础之常用过滤器hbase shell操作

修改 & 删除

修改指定单元格的数据:

1
hbase(main):003:0> put 'stu','1001','info1:name','zhangsan'

解析:将 stu 表中,RowKey 为 1001info1 列族下的 name 列的数据改为 zhangsan。因为是修改数据,因此必须要有原数据才可修改,否则就是增加数据或报错。

数据修改后,并不是立即在 HBase 中删除,它会修改数据版本,高版本的数据会覆盖低版本的数据,相当于一种软删除,我们可以用下列方式 查询 10 个版本以内的指定数据表内的所有数据

1
hbase(main):006:0> scan 'stu',{RAW=>true,VERSIONS=>10}

我们可以在插入数据时,指定数据的时间戳,然后我们再查询的时候就只会 返回时间戳最大的数据

1
hbase(main):007:0> put 'stu','1001','info1:name','wangwu',1588693216333

1588693216333 为指定的时间戳,进行操作时,请将这里的时间戳设置为 mofan 之后,zhangsan 之前。如果你是根据我一步步完成了命令的,现在进行查询 stu 表中的数据,得到的返回结果是张三。

结果示例:

1
2
3
4
5
6
7
ROW                    COLUMN+CELL                                                 
1001                  column=info1:name, timestamp=1588733177444, value=zhangsan
1001                  column=info1:sex, timestamp=1588693722432, value=male    
1001                  column=info2:addr, timestamp=1588693772674, value=sichuan
1002                  column=info1:name, timestamp=1588693795475, value=lisi
1002                  column=info1:phone, timestamp=1588693813969, value=13212341234
1003                  column=info2:addr, timestamp=1588693930008, value=beijing

正是因为这个原因,我们在 Windows 和 Linux 进行 HBase 相关的操作时,请 务必保证两个系统的时间是一致的


删除指定单元格的数据:

1
hbase(main):010:0> delete 'stu','1001','info1:sex'

解析:删除 stu 表中,RowKey 为 1001info1 列族下 sex 列的数据。

使用 delete 删除数据时,如果此单元格有低版本的数据,那么查询数据时,会返回该单元格低版本的数据,而不是自己将该单元格所有版本数据全部删除。

我们可以查询表中 10 个版本以内的数据,得到如下结果:

1
2
3
4
5
1001                  column=info1:name, timestamp=1588733177444, type=Delete     
1001                  column=info1:name, timestamp=1588733177444, value=zhangsan   
1001                  column=info1:name, timestamp=1588693216333, value=wangwu     
1001                  column=info1:name, timestamp=1588693216129, value=mofan
....

我们发现刚刚删除的单元格的 type 变成了 Delete,然后我们查询数据,我们又会发现,返回的是 wangwu,而不是一条数据都没,这也验证了我们的结论。

删除单元格内所有版本的数据:

1
hbase(main):022:0> deleteall 'stu','1001','info1:name'

解析:删除 stu 表中,RowKey 为 1001info1 列族下 sex 列的 所有版本 数据。

如果这时我们再查询数据,我们无法查看到 name 列下的数据。我们查询表中 10 个版本以内的数据,得到如下结果:

1
1001                  column=info1:name, timestamp=1588735280872, type=DeleteColumn 

删除的单元格的 type 变成了 DeleteColumn,当单元格类型为 DeleteColumn 时,查询数据不会返回低版本数据。

根据时间戳删除数据:

先插入一条数据,再进行删除:

1
hbase(main):004:0> put 'stu','1001','info1:name','zhaoliu'

我们使用 scan 查询这条数据:

1
1001                  column=info1:name, timestamp=1588744342719, value=zhaoliu

根据时间戳删除:

1
hbase(main):007:0> delete 'stu','1001','info1:name',1588744342718

注意:我们这里 使用的时间戳比查询出的小 1,我们测试能否删除成功。执行操作后我们可以发现,并没有删除成功。那么我们 让两个时间戳相等 再进行一次删除:

1
hbase(main):007:0> delete 'stu','1001','info1:name',1588744342719

执行操作后,我们发现时间戳为 1588744342719 的数据的 type 已经变成了 Delete,证明删除成功。

测试根据列族进行删除:

1
hbase(main):014:0> delete 'stu','1002','info1'

虽然显示 运行成功,但是我们查询数据后发现 并没有被删除

1
2
3
4
1002                  column=info1:, timestamp=1588745457853, type=Delete           
1002                  column=info1:name, timestamp=1588693795475, value=lisi       
1002                  column=info1:phone, timestamp=1588693813969, value=13212341234  
1002                  column=info2:, timestamp=1588745078579, type=Delete

根据 RowKey 进行删除:

我们删除 RowKey 为 1001 的数据,因为数据不够,我们先插入一条再进行删除:

1
2
hbase(main):023:0> put 'stu','1001','info1:sex','female'
hbase(main):026:0> deleteall 'stu','1001'

清空整个表的数据:

1
hbase(main):029:0> truncate 'stu'

解析:清空 stu 整个表的数据。

3.3 DML (多版本)

测试一

由于我们刚 清空了 stu 表,我们先往 stu 表中 put 两条数据:

1
2
hbase(main):032:0> put 'stu','1005','info1:name','zhangsan'
hbase(main):033:0> put 'stu','1005','info1:name','lisi'

然后我们进行版本查询:

1
hbase(main):036:0> get 'stu','1005',{COLUMN=>'info1:name',VERSIONS=>3}

查询结果:

1
2
COLUMN                 CELL                                                         
info1:name            timestamp=1588748200158, value=lisi 

我们发现,尽管进行了版本查询,但结果只返回了一条数据。这是因为 我们的 stu 表只能存储 1 个版本,因此查询时只返回了时间戳大的版本

测试二

我们新建一个表进行测试:

1
hbase(main):002:0> create 'stu2','info'

插入数据:

1
2
hbase(main):005:0> put 'stu2','1005','info:name','zhangsan'
hbase(main):006:0> put 'stu2','1005','info:name','lisi'

设置 info 列族可存储 2 个版本 数据:

1
2
hbase(main):007:0> alter 'stu2',{NAME=>'info',VERSIONS=>2}
hbase(main):008:0> put 'stu2','1005','info:name','wangwu'

进行版本查询:

1
hbase(main):009:0> get 'stu2','1005',{COLUMN=>'info:name',VERSIONS=>3}

这时候我们发现数据依然只有一条(wangwu),是因为我们先 put 了数据,才进行版本设置。我们需要先进行版本设置,再 put 数据。

再次插入数据:

1
2
hbase(main):012:0> put 'stu2','1001','info:name','zhaoliu'
hbase(main):013:0> put 'stu2','1001','info:name','sunqi'

进行版本查询:

1
hbase(main):015:0> get 'stu2','1001',{COLUMN=>'info:name',VERSIONS=>3}

这时候我们发现查询的数据就有两条了(zhaoliu、sunqi)。

那么我们再向 stu 表,RowKey 为 1001,info 列族中 name 列中插入一条数据:

1
hbase(main):016:0> put 'stu2','1001','info:name','zhouba'

再进行版本查询:

1
hbase(main):017:0> get 'stu2','1001',{COLUMN=>'info:name',VERSIONS=>3}

查询出来的数据依旧只有 2 条(zhaoba、sunqi),虽然我们查找了 3 个版本的数据,但我们设置了 info 列数只能存储两个版本的数据。

删除

在 Shell 模式下,如果我们在允许多个版本数据存在的表里对数据进行删除,会直接删除指定的所有版本数据,无法做到选择删除。