HBbase简介以及命令
一、Hbase简介
HBase是一个分布式的、面向列的开源数据库,该技术来源于 Fay Chang 所撰写的Google论文“Bigtable:一个结构化数据的分布式存储系统”。就像Bigtable利用了Google文件系统(File System)所提供的分布式数据存储一样,HBase在Hadoop之上提供了类似于Bigtable的能力。HBase是Apache的Hadoop项目的子项目。HBase不同于一般的关系数据库,它是一个适合于非结构化数据存储的数据库。另一个不同的是HBase基于列的而不是基于行的模式。
- HBase是一个领先的NoSQL数据库
- 是一个面向列存储的数据库
- 是一个分布式hash map
- 基于Google Big Table论文
- 使用HDFS作为存储并利用其可靠性
- HBase特点
- 数据访问速度快,响应时间约2-20毫秒
- 支持随机读写,每个节点20k~100k+ ops/s
- 可扩展性,可扩展到20,000+节点
- HBase采用Master/Slave架构
在启动HBASE服务之后我们可以使用jps查看进程如图:
那么这三个进程分别什么作用呢:
HMaster
HMaster的作用
- 是HBase集群的主节点,可以配置多个,用来实现HA
- 管理和分配Region
- 负责RegionServer的负载均衡
- 发现失效的RegionServer并重新分配其上的Region
RegionServer
RegionServer负责管理维护Region:
Master可能的进程:
-
HMaster//必须的,表明该hbase是Master
-
QuorumPeerMain//必须单独配置的Zookeeper集群,如果是内置的则为HQuorumPeer
-
HRegionServer//不是必须的,因为我们也将该Master设置为Region
-
NameNode//必须,任务调度器
-
SencondNameNode//必须,任务调度器
HRegion可能的进程:
-
QuorumPeerMain//必须单独配置的Zookeeper集群,如果是内置的则为HQuorumPeer
-
DataNode//必须,数据存储相关
二、HBase 重要概念
HBase的表结构
HBase以表的形式存储数据。表有行和列组成。列划分为若干个列族/列簇(column family),每个列族/列簇下面可以有多个普通列。
表Table
HBase是用表来存储数据的。
命名空间namespace
namespace命名空间指对一组表的逻辑分组,类似RDBMS中的database,方便对表在业务上划分。
HBase系统默认定义了两个缺省的namespace:
hbase:系统内建表,包含namespace和meta表
default:用户建表时未指定namespace的表都创建在此
行键 Row Key
行键,每一行的主键列,每行的行键要唯一,行键的值为任意字符串(最大长度是 64KB,实际应用中长度一般为 10-100bytes),在HBase内部,rowKey保存为字节数组byte[]。
行的一次读写是原子操作 (不论一次读写多少列)
区域Region
Table在行的方向上分割为多个Region。
Region是按大小分割的,每个表开始只有一个region,随着数据的增多,region不断增大,当增大到一个阀值的时候,region就会等分为两个新的region,之后会有越来越多的region。
Region是HBase中分布式存储和负载均衡的最小单元。不同的Region分布到不同的RegionServer上。
Region由一个或者多个Store组成, 每个Store保存一个column family, 每个Store又由一个MemStore(存储在内存中)和0到多个StoreFile(存储在HDFS上)组成
列族 column family
列族是每个子列的父级,每个子列都属于一个列族,一个列族包含一个或者多个相关列,创建表的时候需要指定列族,而列不需要必须指定。通过“列族名:列名”来表示某个具体的子列。
HBase中的Schema就是 TableName + Column Family Name
列限定符
就是列族下的每个子列名称,或者称为相关列,或者称为限定符,只是翻译不同。
通过columnFamily:column来定位某个子列。
存储单元 cell
我们外观看到的每个单元格其实都对应着多个存储单元,默认情况下一个单元格对应着一个存储单元,一个存储单元可以存储一份数据,如果一个单元格有多个存储单元就表示一个单元格可以存储多个值。可以通过version来设置存储单元个数。可以通过
rowKey + columnFamily + column + timestamp来唯一确定一个存储单元。cell中的数据是没有类型的,全部是字节码形式存贮。
hbase按照时间戳降序排列各时间版本,其他映射建按照升序排序。
时间戳版本号 timestamp
每个cell都保存着同一份数据的多个版本。版本通过时间戳来索引。时间戳的类型是 64位整型。时间戳可以由hbase(在数据写入时自动 )赋值,此时时间戳是精确到毫秒的当前系统时间。时间戳也可以由客户显式赋值。如果应用程序要避免数据版本冲突,就必须自己生成具有唯一性的时间戳。每个cell中,不同版本的数据按照时间倒序排序,即最新的数据排在最前面。
为了避免数据存在过多版本造成的的管理 (包括存贮和索引)负担,hbase提供了两种数据版本回收方式。一是保存数据的最后n个版本,二是保存最近一段时间内的版本(比如最近七天)。用户可以针对每个列族进行设置。
还有个重要概念:
三、HBASE 指令
HBase Shell
HBase Shell是一种操作HBase的交互模式
支持完整的HBase命令集
查看版本
hbase(main):004:0> version
1.2.0-cdh5.14.2, rUnknown, Tue Mar 27 13:31:54 PDT 2018
查看集群状态
hbase(main):003:0> status
1 active master, 0 backup masters, 1 servers, 0 dead, 2.0000 average load
查看
hbase(main):005:0> whoami
root (auth:SIMPLE)
groups: root
help
hbase(main):002:0> help 'list'
List all tables in hbase. Optional regular expression parameter could
be used to filter the output. Examples:
hbase> list
hbase> list 'abc.*'
hbase> list 'ns:abc.*'
hbase> list 'ns:.*'
基础命令
create 创建表
# 语法
create '表名', {NAME => '列族名1'}, {NAME => '列族名2'}, {NAME => '列族名3'}
# 此种方式是上上面的简写方式,使用上面方式可以为列族指定更多的属性,如VERSIONS、TTL、BLOCKCACHE、CONFIGURATION等属性
create '表名', '列族名1', '列族名2', '列族名3'
create '表名', {NAME => '列族名1', VERSIONS => 版本号, TTL => 过期时间, BLOCKCACHE => true}
# 示例
create 'tbl_user', 'info', 'detail'
create 't1', {NAME => 'f1', VERSIONS => 1, TTL => 2592000, BLOCKCACHE => true}
修改(添加、删除)表结构Schema alter
添加列蔟
删除列蔟
hbase(main):011:0> alter 'mydemo',{NAME=>'external',METHOD=>'delete'}
Updating all regions with the new schema...
1/1 regions updated.
Done.
0 row(s) in 1.9330 seconds
描述表属性
在添加列蔟之后再次描述:
exists 是否存在
disable 关闭表
hbase(main):017:0> disable 'mydemo'
0 row(s) in 2.2770 seconds
drop删除表
在删除之前需要先关闭表:
hbase(main):018:0> drop 'mydemo'
0 row(s) in 1.2860 seconds
hbase(main):019:0> list
TABLE
0 row(s) in 0.0070 seconds
=> []
create_namespace 创建表空间
hbase(main):025:0> create_namespace 'mydemo'
0 row(s) in 0.0820 seconds
hbase(main):026:0> list_namespace
NAMESPACE
default
hbase
mydemo
3 row(s) in 0.0110 seconds
然后在表空间里面建表
hbase(main):027:0> create 'mydemo:userinfo','base'
0 row(s) in 1.2320 seconds
=> Hbase::Table - mydemo:userinfo
hbase(main):028:0> create 'mydemo:scores','info'
0 row(s) in 1.2230 seconds
=> Hbase::Table - mydemo:scores
然后查询表
hbase(main):030:0> list_namespace_tables 'mydemo'
TABLE
scores
userinfo
2 row(s) in 0.0130 seconds
put 塞数据
用法:
put '表名', '行键', '列族名:列名', '列值'
hbase(main):033:0> put 'mydemo:userinfo','1','base:username','zhangsan'
0 row(s) in 0.0880 seconds
示例:
添加新列蔟
hbase(main):035:0> alter 'mydemo:userinfo','external'
Updating all regions with the new schema...
0/1 regions updated.
1/1 regions updated.
Done.
0 row(s) in 3.8800 seconds
hbase(main):036:0> put 'mydemo:userinfo','1','external:likes','player,eat'
0 row(s) in 0.0060 seconds
hbase(main):037:0> put 'mydemo:userinfo','2','base:username','lisi'
0 row(s) in 0.0070 seconds
hbase(main):038:0> put 'mydemo:userinfo','2','base:age','30'
0 row(s) in 0.0060 seconds
scan全表扫描
扫描整个列蔟:
hbase(main):040:0> scan 'mydemo:userinfo'
ROW COLUMN+CELL
1 column=base:username, timestamp=1592805945494, value=zhangsan
1 column=external:likes, timestamp=1592806184518, value=player,eat
2 column=base:age, timestamp=1592806246065, value=30
2 column=base:username, timestamp=1592806235029, value=lisi
2 row(s) in 0.0200 seconds
单独扫描base列蔟:
hbase(main):041:0> scan 'mydemo:userinfo',{COLUMN=>'base'}
ROW COLUMN+CELL
1 column=base:username, timestamp=1592805945494, value=zhangsan
2 column=base:age, timestamp=1592806246065, value=30
2 column=base:username, timestamp=1592806235029, value=lisi
2 row(s) in 0.0160 seconds
get获取数据
hbase(main):042:0> get 'mydemo:userinfo','1'
COLUMN CELL
base:username timestamp=1592805945494, value=zhangsan
external:likes timestamp=1592806184518, value=player,eat
2 row(s) in 0.0080 seconds
获取某一行某列族的数据
hbase(main):043:0> get 'mydemo:userinfo','1','external'
COLUMN CELL
external:likes timestamp=1592806184518, value=player,eat
1 row(s) in 0.0030 seconds
关于get获取的机制:
小测试:
hbase(main):048:0> create 'mydemo:mytest',{NAME=>'base',VERSIONS=>3}
0 row(s) in 2.2380 seconds
=> Hbase::Table - mydemo:mytest
hbase(main):049:0> put 'mydemo:mytest','1','base:xxx','1'
0 row(s) in 0.0090 seconds
hbase(main):050:0> put 'mydemo:mytest','1','base:xxx','11'
0 row(s) in 0.0030 seconds
hbase(main):051:0> put 'mydemo:mytest','1','base:xxx','111'
0 row(s) in 0.0030 seconds
hbase(main):052:0> get 'mydemo:mytest','1',{COLUMN=>'base',VERSIONS=>3}
COLUMN CELL
base:xxx timestamp=1592807341321, value=111
base:xxx timestamp=1592807339037, value=11
base:xxx timestamp=1592807335763, value=1
3 row(s) in 0.0100 seconds
hbase(main):053:0> put 'mydemo:mytest','1','base:xxx','1111'
0 row(s) in 0.0060 seconds
hbase(main):054:0> get 'mydemo:mytest','1',{COLUMN=>'base',VERSIONS=>3}
COLUMN CELL
base:xxx timestamp=1592807418229, value=1111
base:xxx timestamp=1592807341321, value=111
base:xxx timestamp=1592807339037, value=11
3 row(s) in 0.0090 seconds
hbase(main):055:0> get 'mydemo:mytest','1',{COLUMN=>'base',TIMESTAMP=>1592807341321}
COLUMN CELL
base:xxx timestamp=1592807341321, value=111
1 row(s) in 0.0070 seconds
count查询表中有多少行
hbase(main):013:0> count 'mydemo:userinfo'
3 row(s) in 0.0070 seconds
=> 3
incr自增
增加学号自增列
hbase(main):015:0> incr 'mydemo:userinfo','1','base:stuno',1
COUNTER VALUE = 1
0 row(s) in 0.0440 seconds
hbase(main):016:0> scan 'mydemo:userinfo'
ROW COLUMN+CELL
1 column=base:stuno, timestamp=1592815800048, value=\x00\x00\x00\x00
\x00\x00\x00\x01
1 column=base:username, timestamp=1592805945494, value=zhangsan
1 column=external:likes, timestamp=1592806184518, value=player,eat
2 column=base:age, timestamp=1592806246065, value=30
2 column=base:username, timestamp=1592806235029, value=lisi
3 column=base:username, timestamp=1592807614505, value=zhangsanfeng
3 row(s) in 0.0130 seconds
COLUMNS: 查询同一个列族的多个列
hbase(main):020:0> scan 'mydemo:userinfo',{COLUMN=>['base:username','base:age']}
ROW COLUMN+CELL
1 column=base:username, timestamp=1592805945494, value=zhangsan
2 column=base:age, timestamp=1592806246065, value=30
2 column=base:username, timestamp=1592806235029, value=lisi
3 column=base:username, timestamp=1592807614505, value=zhangsanfeng
3 row(s) in 0.0220 seconds
TIMESTAMP 指定时间戳
根据时间戳查询
hbase(main):024:0> scan 'mydemo:userinfo',{COLUMN=>'base',TIMESTAMP=>1592807614505}
ROW COLUMN+CELL
3 column=base:username, timestamp=1592807614505, value=zhangsanfeng
1 row(s) in 0.0050 seconds
TIMERANGE
表示的是”>=开始时间 and <结束时间“
# 语法
scan '表名',{TIMERANGE=>[timestamp1, timestamp2]}
# 示例
scan 'tbl_user',{TIMERANGE=>[1551938004321, 1551938036450]}
STARTROW(起始行)的用法:
ROWKEY起始行。会先根据这个key定位到region,再向后扫描
STOPROW :截止到STOPROW行,STOPROW行之前的数据,不包括STOPROW这行数据
# 语法
scan '表名', { STOPROW => '行键名'}
# 示例
scan 'tbl_user', { STOPROW => 'vbirdbest'}
hbase(main):007:0> scan 'test1',{STARTROW=>'user1|ts2',FILTER=>"PrefixFilter('user2')"}
ROW COLUMN+CELL
user2|ts4 column=sf:c1, timestamp=1592814297019, value=sku2
user2|ts5 column=sf:c2, timestamp=1592814297039, value=sku288
user2|ts6 column=sf:s1, timestamp=1592814301829, value=sku222
3 row(s) in 0.0110 seconds
hbase(main):008:0> scan 'test1',{STARTROW=>'user1|ts2',FILTER=>"PrefixFilter('user1')"}
ROW COLUMN+CELL
user1|ts2 column=sf:c1, timestamp=1592814296974, value=sku188
user1|ts3 column=sf:s1, timestamp=1592814296991, value=sku123
2 row(s) in 0.0220 seconds
LIMIT 返回的行数
hbase(main):025:0> scan 'mydemo:userinfo',{LIMIT=>2}
从第二行开始 取两行 2-3行 用来做分页的
hbase(main):026:0> scan 'mydemo:userinfo',{STARTROW=>'2',LIMIT=>2}
scan中Filter的使用方法
首先创个实验表:
hbase(main):059:0> create 'test1', 'lf', 'sf'
0 row(s) in 2.2650 seconds
=> Hbase::Table - test1
hbase(main):060:0> put 'test1', 'user1|ts1', 'sf:c1', 'sku1'
222'0 row(s) in 0.0230 seconds
hbase(main):061:0> put 'test1', 'user1|ts2', 'sf:c1', 'sku188'
0 row(s) in 0.0040 seconds
hbase(main):062:0> put 'test1', 'user1|ts3', 'sf:s1', 'sku123'
0 row(s) in 0.0050 seconds
hbase(main):063:0>
hbase(main):064:0* put 'test1', 'user2|ts4', 'sf:c1', 'sku2'
0 row(s) in 0.0060 seconds
hbase(main):065:0> put 'test1', 'user2|ts5', 'sf:c2', 'sku288'
0 row(s) in 0.0070 seconds
hbase(main):066:0> put 'test1', 'user2|ts6', 'sf:s1', 'sku222'
0 row(s) in 0.0090 seconds
查询案例:
valuefilter的使用方法:
谁的值=sku188
hbase(main):067:0> scan 'test1', FILTER=>"ValueFilter(=,'binary:sku188')"
ROW COLUMN+CELL
user1|ts2 column=sf:c1, timestamp=1592814296974, value=sku188
1 row(s) in 0.0350 seconds
谁的值包含88
hbase(main):068:0> scan 'test1', FILTER=>"ValueFilter(=,'substring:88')"
ROW COLUMN+CELL
user1|ts2 column=sf:c1, timestamp=1592814296974, value=sku188
user2|ts5 column=sf:c2, timestamp=1592814297039, value=sku288
2 row(s) in 0.0140 seconds
通过广告点击进来的(column为c2)值包含88的用户
hbase(main):003:0> scan 'test1', FILTER=>"ColumnPrefixFilter('c2') AND ValueFilter(=,'substring:88')"
ROW COLUMN+CELL
user2|ts5 column=sf:c2, timestamp=1592814297039, value=sku288
1 row(s) in 0.0150 seconds
PrefixFilter:
rowkey为user1开头的
scan 'test1', FILTER => "PrefixFilter ('user1')"
KeyOnlyFilter:
只要key,不要value
scan 'test1', FILTER=>"FirstKeyOnlyFilter() AND ValueFilter(=,'binary:sku188') AND KeyOnlyFilter()"