Hbase基础

Hbase简介:

Hbase是Apache旗下一个高可靠性、高性能、面向列、可伸缩的分布式数据库。利用Hbase技术可以在廉价的PC服务器上搭建大规模的存储化集群,使用HBase可以对数十亿级别的大数据机型实时性的高性能读写,在满足高性能的同时还保证了数据存取得原子性。

查询得操作速度将会受到以下两个因素的影响:
1.表会被并发地进行插入、编辑以及删除操作。
2.查询语句通常都不是简单地对一个表的查询,而有可能是多个表关联后得复杂查询,甚至可能有group by 或者order by 操作。

Hbase起源
2006年Google发布了一篇叫做BigTable:A Distributed Storage System for Structured Data的论文。BigTable是一个分布式存储系统,利用谷歌提出的MapReduce分布式并行计算模型来处理海量数据,使用谷歌分布式文件系统GFS作为底层数据存储,并采用Chubby提供协同服务管理,可以扩展到PB级别的数据和上千台机器,具备可扩展性、高性能和高可用性等特点。2007年Doug Cutting基于此论文研发了BigTable的Java开源版本,即HBase。刚开始它只是Hadoop的一部分,后来升级为Apache的顶级独立项目。它的Logo如图所示:

在这里插入图片描述

Cap理论:

在这里插入图片描述

Consistency(一致性):数据一致更新、所有数据变动都是同步的。
Availability(可用性):良好的响应性能
Partition tolerance(分区容错性):可靠性
存储结构
HBase采用key-value的形式存储数据,最基本的存储单位是列
表是由列族组成的
列族是由列组成的
列是由key-value组成的
row key的设计原则:长度原则、散列原则、唯一原则。

在HBase中,没有值的列可以省略,空值不占用任何存储空间。

HBase会将表中的数据基于row key 水平的划分为多个区域
在这里插入图片描述
每个region负责一定范围的读写和维护。这样即使一张巨大的表,由于被切割到不同的region,查询起来的延时也非常低。

集群架构

如图所示:
在这里插入图片描述

一般HBase集群有一个HMaster服务器和几个HRegionServer服务器。HMaster服务器负责维护表的结构信息,HRegionServer服务器负责存储数据。客户端通过直连HRegionServer获取数据,所以当HMaster宕机后依然可以查询数,只是不能新建表了。
HRegionServer内部管理了一系列HRegio对象,每个HRegion对应表中的一个Region,HRegion 由多个Store组成,每个Store对应表中的一个Column Family数据的存储。
Store由两部分构成,一部分是MemStore,一部分是StoreFile。MemStore是内存缓冲区,StoreFile是HDFS上的文件。数据先写入MemStore,在达到某些条件的时候,会触发刷盘(flush)操作,一次性把MemStore中的数据写入HDFS,形成一个StoreFile文件。通常当MemStore的大小达到128M(hbase.hregion.memstore.flush.size)或者占用内存达到总内存的40%(hbase.regionserver.global.memstore.upperLimit)时会触发flush操作。
随着flush操作的执行,会产生越来越多的StoreFile文件。当StoreFile文件数量增长到3(hbase.hstore.compactionThreadhold)个后,会触发合并(Compact)操作,将多个小的StoreFile合并成一个大的StoreFile。
StoreFile在完成Compact操作后,体积会越来越大。当单个StoreFile的大小超过10G(hbase.hRegion.max.filesize)后,会触发分裂(Split)操作,把当前Region分裂成2个Region。新分裂出的Region 会被Hmaster迁移到其它的HRegionServer进行管理,使得原先1个大Region压力得以分流到2个小Region上。
每个RegionServer还有1个HLog文件。HLog是HBase实现WAL(Write ahead log)方式产生的日志信息,内部是一个简单的顺序日志。所有对于该RegionServer的写入数据都会先记录到HLog中,然后再写入MemStore中。只有当写HLog和写MemStore都成功了才算数据写入完成。当RegionServer出现问题的时候,可以通过HLog来恢复MemStore中的数据。为了保证恢复的效率,HBase会限制HLog记录的日志数量,如果数量达到32(hase.regionserver.max.logs)的时候,就会触发强制flush操作。对于已经flush的数据,其对应的日志会有一个过期的概念,日志过期后,会被监控线程移动到.oldlogs文件中,然后自动删除掉。
HMaster还负责维护元数据表(.META.)。.META.记录了每表的Region信息,比如,该表有几个Region,每个Region的row key范围和所在HRegionServer等等。.META.的数据存储在某个HRegionServer上,有且只有一个Region。而.META.的位置信息则存储在Zookeeper中。因此,客户端查询数据的流程如图所示:

在这里插入图片描述
1、 Client请求Zookeeper获取.META.所在的RegionServer的地址;
2、 Client请求.META.所在的RegionServer获取数据所在的RegionServer地址;还会将.META.的信息缓存起来,以便下一次快速访问;
3、 Client请求数据所在的RegionServer获取数据。
总上所述,Hbase是由Client、Zookeeper、HMaster、HRegionServer和HDFS等几个组件组成,它们各自的功能如下:
Client:包含了访问HBase的接口,还有维护缓存加速HBase的访问。
Zookeeper:实现HMaster的高可用;监控HRegionServer的状态;存储.META.的地址。
HMaster:维护.META.;为HRegionServer分配Region;维护集群的负载均衡。
HRegionServer:处理客户端的读写请求;管理HMaster分配的Region。
HDSF:为HBase提供最终的底层数据存储服务。

shell

HBase Shell是HBase集群的命令行接口。用户可以使用Shell访问本地或远程服务器并与其进行交互。Shell同时提供了客户端和管理功能的操作。

Shell操作的第一步是启动Shell,使用以下命令:
hbase shell
要离开可以输入exit或者quit命令
命令

在输入命令的时候必须遵循一定的规则:
(1) 引用名:命令行要求在使用表名和列名时,必须通过单引号或者双引号对其引用。
(2) 引用值:命令行支持二进制、八进制、十六进制的输入和输出。用户在引用时必须使用双引号,否则会被当做文件进行处理。
(3) 使用逗号分隔参数:参数之间需要使用逗号进行分隔。
(4) 散列属性:一些命令需要使用键值对属性,要按照以下格式来完成:

create命令创建表
在HBase Shell执行以下命令:
	create 'user', 'cf1'
list命令查看有哪些表
使用list命令查看有哪些表
在HBase Shell执行以下命令:
	list
使用describe命令来查看表属性
使用describe命令来查看表属性
在HBase Shell执行以下命令:
	describe 'user'
使用put命令来插入数据

在HBase中行的每一列都存储在不同的位置,你必须指定你要存储数据到哪个单元格。而单元格需要根据表、行、列这几个维度来定位,所以一次只能向一列插入数据。如果你的一行有5列,想向这5列都插入数据,就需要编写5行语句。
在HBase Shell执行以下命令:
	put 'user', 'rk0001', 'cf1:name', 'zhangsan'
	输出结果:
	Took 0.0364 seconds
这条语句的意思是:
	向user表插入一个单元格
	这个单元格的row key为rk0001
	这个单元格的列族是cf1
	这个单元格的列名是name
	这个单元格的数据值是zhangsan
我们再插入一些数据:
向user的rk0002行的cf1列族的name列插入数据lisi
	put 'user', 'rk0002', 'cf1:name', 'lisi'
向user的rk0003行的cf1列族的name列插入数据wangwu
put 'user', 'rk0003', 'cf1:name', 'wangwu'
向user的rk0004行的cf1列族的name列插入数据zhaoliu
put 'user', 'rk0004', 'cf1:name', 'zhaoliu'
向user的rk0002行的cf1列族的age列插入数据24

put 'user', 'rk0001', 'cf1:age', 24
向user的rk0002行的cf1列族的gender列插入数据man
put 'user', 'rk0002, 'cf1:gender', 'man'
向user的rk0003行的cf1列族的birthday列插入数据1996-06-23
put 'user', 'rk0003, 'cf1:birthday', '1996-06-23'

使用scan来查看表数据

scan是最常用的查询表数据的命令,这个命令相当于传统数据库的select。通过以下命令就可以遍历出user表的数据:
scan 'user'
	输入内容如下:
		ROW                     COLUMN+CELL                                                         
 		 	rk0001                column=cf1:age, timestamp=1594263341992, value=24
rk0001                column=cf1:name, timestamp=1594262772226, value=zhangsan
 		 	rk0002                column=cf1:gender, timestamp=1594263392732, value=man
rk0002                column=cf1:name, timestamp=1594263341800, value=lisi
rk0003                column=cf1:name, timestamp=1594263341860, value=wangwu
rk0004                column=cf1:name, timestamp=1594263341924, value=zhaoliu
4 row(s)
Took 0.0606 seconds
从查询结果我们可以,ROW列显示的就是row key,COLUMN+CELL列显示的就是这个记录的列族(column冒号前的部分)、列(column冒号后的部分)、时间戳(timestamp)和值(value)等信息。而且即使是一行的不同列也是显示成不同的行,因为HBase就是这么存储数据的,所有的单元格都是离散分布的。
不过在实际环境下很少会直接这么写,因为表的数据太大了。如果你这么输入的话,会从第一条数据开始把所有数据全部展示一遍,这个消耗的时间简直无法想象。我们需要使用起始行(STARTROW)和结束行(ENDROW)来限制显示记录的条数。STARTROW和ENDROW都是可选参数,可以不输入。如果ENDROW不输入的话,就从STARTROW开始一直显示下去直到表的结尾;如果STARTROW不输入的话,就从表头开始一直显示到ENDROW为止。
下面这条命令会显示所有row key大于且等于rk0002的记录:
	scan 'user', {STARTROW => 'rk0002'}
下面这条命令会显示所有row key小于rk0004的记录:
	scan 'user', {ENDROW => 'rk0004'}
下命这条命令会显示所有row key大于且等于rk0002并且小于rk0004的记录:
	scan 'user', {STARTROW => 'rk0002', ENDROW => 'rk0004'}
使用get来获取单元格数据

除了使用scan命令以外还可以使用get命令来查询数据。只不过get命令只能查询一个单元格的记录。
get最简单的用法就是查询某个单元格的记录,例如,查询rk0001中cf1:name的值:
	get 'user', 'rk0001', 'cf1:name'
输出结果如下:
COLUMN                   CELL                                                                
 cf:name                   timestamp=1594262772226, value=zhangsan                             
1 row(s)
Took 1.1362 seconds
	当你看到这条记录的时候,你会看到时间戳属性。虽然HBase中每一个单元格都可以存储多个版本的值,但是单元格并没有version这个属性。它使用timestamp属性存储该记录的时间戳,这个时间戳就用来当版本号使用。
	如果你在写put语句的时候不指定时间戳,系统就会自动填充当前时间帮你指定。有意思的是,这个timestamp虽然说是时间的标定,其实你可以输入任何数字,比如1、2、3都可以。当使用scan或者get命令的时候默认会显示拥有最大timestamp值的数据。接下来我们试试看。
	在此之前,我们要先调整一下列族的版本数属性为5。因为刚刚的user表创建语句采用的默认版本数是1。也就意味着即使你在一个单元格中插入多个版本的数据,HBase也只会保留最后一个版本。修改版本数的命令如下:
		alter 'user', {NAME => 'cf1', VERSIONS => 5}
	这条语句中NAME是要修改的列族名称,后边跟上要修改的属性,我们修改VERSIONS为5。
	我们插入一条新数据,采用自己定义的时间戳,数字1。
		put 'user', 'rk0001', 'cf1:name', 'zhangsansan', 1
	接下来我们在使用get查询一下单元格数据:
		get 'user', 'rk0001', 'cf1:name'
	输出内容如下:
		COLUMN                   CELL                                                                
 		 cf1:name                 timestamp=1594262772226, value=zhangsan                             
1 row(s)
Took 0.0563 seconds       
	由于我们插入的zhangsansan这条数据的时间戳小于zhangsan这条记录的时间戳,而scan或者get只能看到时间戳最大的记录,所以查询出来的是zhangsan这条记录。不过zhangsansan这条记录并没有被丢弃,我们可以使用scan或get命令的VERSIONS参数来查询这个单元格的n个版本数据:
		get 'user', 'rk0001', {COLUMN => 'cf1:name', VERSIONS => 5}
输出结果如下:
	COLUMN                   CELL                                                                
 cf1:name                 timestamp=1594262772226, value=zhangsan                             
 cf1:name                 timestamp=1, value=zhangsansan                                      
1 row(s)
Took 0.0357 seconds  
	可以看到当前单元格中其实是有两个数据的。
	COLUMN参数除了可以设置为具体的某一列以外,还可以设置为其它值。比如,设置为多个列,则可以查询出多个列下所有的数据;设置为某个列族,则可以查询出该行该列族下所有列的数据;设置为多个列族,则可以查询出多个列族下所有的数据。下面是几个案例:
	查询rk0001行中cf1:name列和cf1:age列的所有数据:
		get 'user', 'rk0001', {COLUMN => ['cf1:name', 'cf1:age']}
	查询rk0001行中cf1列族中所有列的数据:
		get 'user', 'rk0001', {COLUMN => ['cf1']}
使用delete来删除单元格数据

有增就有删,接下来我们看看如何删除数据,最简单的例子如下:
		delete 'user', 'rk0002', 'cf1:age'
执行的结果就是user表中rk0002行的cf1:age单元格被删除了。
delete命令也可以跟上时间戳(timestamp)参数,就像这样:
		delete 'user', 'rk0002', 'cf1:name', 1594262772226
需要注意的是,HBase删除记录并不是真的立即删除了数据,而是放置了一个墓碑标记(tombstone marker),把这个版本数据标记为不可见。当HBase执行Compact操作合并StoreFile的时候才会去清理这些被标记的数据。这样的删除设计会对HBase的性能影响降到最低,就算在很高的并发负载下大量删除记录也不怕。被打上tombstone marker的记录还是可以被查询到的,只需要使用scan命令时设置RAW参数的值为true即可。例子如下:
	scan 'user', {RAW => true, VERSIONS => 5}
在结果我们可以找到这样一条记录:
	rk0002                  column=cf1:age, timestamp=1594263341992, type=Delete
那些type=Delete的列就是被打上墓碑标记的记录。
使用deleteall删除整行记录

如果一个列有很多行,使用delete命令一个一个删的话会把人累死。所以HBase Shell还提供了deleteall命令来删除正行记录。使用例子如下:
	deleteall 'user', 'rk0001'
这次一下就删除了整个rk0001记录。
使用disable来停用表

在使用HBase的时候,表是不能轻易被删除的。因为可能有很多客户端现在正好在使用,或者HBase正在进行Compact或者Split操作。如果这时候删除表会造成无法恢复的错误。在删除表之前需要先做一个下线(disable)操作,把表停用。停用user表的命令如下:
	disable 'user'
在没有什么数据或者没有什么人使用的情况下这条命令执行得很快。但如果在系统已经上线了, 并且负载很大的情况下disable命令会执行得很慢。因为disable要通知所有的HRegionServer来下线这个表,并且有很多涉及该表的操作需要被停用掉,以保证该表真的已经完全不参与任何工作。
当你停用掉一个表后,你可以用scan测试一下表是不是真的被关闭了:
	scan 'user'
你会发现无法使用scan命令,并且会输出一个错误信息ERROR: user is disabled,意思是表已经被关闭了,不能scan了。
如果需要启用user表,使用以下命令:
	enable 'user'
使用drop来删除表
用disable停用表后,我们就可以放心地删除表了。删除表的语句很简单,就是drop。现在我们来试下用drop命令把user表删除掉,命令如下:
	drop 'user'
然后在使用list命令查看下数据还有什么表,发现数据库中user表已经被删除。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值