概述
最近在进行一些数据处理的工作,用到了Hbase进行数据存储,以前也看过一点Hbase,但是在这里进行一些总结,方便以后复习,而且很多命令经常忘记,方便查看
什么是Hbase
HBase(Hadoop Database)是一个开源的、面向列(Column-Oriented),适合存储海量非结构化数
据或半结构化数据的、具备高可靠性、高性能、可灵活扩展伸缩的、支持实时数据读写的分布式存储系
统。
RDBMS与HBase的对比
3.1、关系型数据库
结构:
* 数据库以表的形式存在
* 支持FAT、NTFS、EXT、文件系统
* 使用Commit log存储日志
* 参考系统是坐标系统
* 使用主键(PK)
* 支持分区
* 使用行、列、单元格
功能:
* 支持向上扩展
* 使用SQL查询
* 面向行,即每一行都是一个连续单元
* 数据总量依赖于服务器配置
* 具有ACID支持
* 适合结构化数据
* 传统关系型数据库一般都是中心化的
* 支持事务
* 支持Join
3.2、HBase
结构:
* 数据库以region的形式存在
* 支持HDFS文件系统
* 使用WAL(Write-Ahead Logs)存储日志
* 参考系统是Zookeeper
* 使用行键(row key)
* 支持分片
* 使用行、列、列族和单元格
功能:
* 支持向外扩展
* 使用API和MapReduce来访问HBase表数据
* 面向列,即每一列都是一个连续的单元
* 数据总量不依赖具体某台机器,而取决于机器数量
* HBase不支持ACID(Atomicity、Consistency、Isolation、Durability)
* 适合结构化数据和非结构化数据
* 一般都是分布式的
* HBase不支持事务
* 不支持Join
Hbase 集群结构
HBase 系统架构
- HBaese Client
Client使用HBase的RPC机制与HMaster、HRegionServer 进行通信。
Client与HMaster进行管理类通信,与HRegion Server进行数据操作类通信。
- HRegionServer
HRegionServer内部管理了一系列HRegion对象,每个HRegion对应Table中的一个Region。
HRegion由多个Store组成。每个Store对应Table中的一个Column Family的存储,即一个
Store管理一个Region上的一个列族(CF)。每个Store包含一个MemStore和0到多个
StoreFile。Store是HBase的存储核心,由MemStore 和 StoreFile组成。
- HLog
数据在写入时,首先写入预写日志(Write Ahead Log),每个HRegion Server服务的所有Region
的写操作日志都存储在同一个日志文件中。数据并非直接写入HDFS,而是等缓存到一定数量再批量写
入,写入完成后在日志中做标记。
- MemStore
MemStore是 一个有序的内存缓存区,用户写入的数据首先放入MemStore,当MemStore满了以后Flush成一个StoreFile
(存储时对应为HFile), 当StoreFile数量增到一定阈值,触发Compact合并,将多个StoreFiles合并成一个StoreFile。
- StoreFile
StoreFiles 合并后逐步形成越来越大的StoreFile,当Region内所有StoreFiles(Hfile)的总大小超过阈值
(hbase.hregion.max.filesize)即触发分裂Split,把当前的Region Split成2个Region,
父Region下线,新Split出的2个孩子Region被HMaster分配到合适的HRegionServer 上,使得
原先1个Region的压力得以分流到2个Region上。
HBase数据模型
HBase是由row key,column family,column和cell组成,row key确定唯一的一行,column family由若干column组成,column是表的字段,cell存储了实际的值或数据。
HBase常用操作
- 进入HBase客户端命令操作界面
bin/hbase shell
- 查看帮助命令
help
- 查看当前数据库中有哪些表
hbase(main):002:0> list
- 创建一张表
hbase(main):006:0> create 'student','info'
0 row(s) in 4.7590 seconds
=> Hbase::Table - student
- 向表中存储一些数据
hbase(main):007:0> put 'student','1001','info:name','Thomas'
0 row(s) in 0.1440 seconds
hbase(main):008:0> put 'student','1001','info:sex','male'
0 row(s) in 0.0150 seconds
hbase(main):009:0> put 'student','1001','info:age','18'
0 row(s) in 0.0130 seconds
hbase(main):014:0> put 'student','1002','info:age','18'
0 row(s) in 0.0140 seconds
hbase(main):015:0> put 'student','1002','info:hobby','read'
0 row(s) in 0.0120 seconds
hbase(main):016:0> put 'student','1002','info:name','jack'
0 row(s) in 0.0060 seconds
- 扫描查看存储的数据
hbase(main):017:0> scan 'student'
ROW COLUMN+CELL
1001 column=info:age, timestamp=1566874407155, value=18
1001 column=info:name, timestamp=1566874355716, value=Thomas
1001 column=info:sex, timestamp=1566874390231, value=male
1002 column=info:age, timestamp=1566874494542, value=18
1002 column=info:hobby, timestamp=1566874584481, value=read
1002 column=info:name, timestamp=1566874626923, value=jack
2 row(s) in 0.0160 seconds
或:查看某个rowkey范围内的数据
hbase(main):018:0> scan 'student',{STARTROW=>'1001',STOPROW=>'1002'}
ROW COLUMN+CELL
1001 column=info:age, timestamp=1566874407155, value=18
1001 column=info:name, timestamp=1566874355716, value=Thomas
1001 column=info:sex, timestamp=1566874390231, value=male
1 row(s) in 0.0060 seconds
hbase(main):019:0> scan 'student',{STARTROW=>'1001',STOPROW=>'1003'}
ROW COLUMN+CELL
1001 column=info:age, timestamp=1566874407155, value=18
1001 column=info:name, timestamp=1566874355716, value=Thomas
1001 column=info:sex, timestamp=1566874390231, value=male
1002 column=info:age, timestamp=1566874494542, value=18
1002 column=info:hobby, timestamp=1566874584481, value=read
1002 column=info:name, timestamp=1566874626923, value=jack
2 row(s) in 0.0090 seconds
- 查看表结构
hbase(main):021:0> describe 'student'
Table student is ENABLED
student
COLUMN FAMILIES DESCRIPTION
{NAME => 'info', BLOOMFILTER => 'ROW', VERSIONS => '1', IN_MEMORY => 'false', KEEP_DELETED_CELLS => 'FALSE', DATA_BLOCK_ENCODING => 'NONE', TTL => 'FOREVER', COMPRESS
ION => 'NONE', MIN_VERSIONS => '0', BLOCKCACHE => 'true', BLOCKSIZE => '65536', REPLICATION_SCOPE => '0'}
1 row(s) in 0.0880 seconds
- 更新指定字段的数据
hbase(main):009:0> put 'student','1001','info:name','Nick'
hbase(main):010:0> put 'student','1001','info:age','100'
- 查看指定行的数据
hbase(main):022:0> get 'student','1001'
COLUMN CELL
info:age timestamp=1566874407155, value=18
info:name timestamp=1566874355716, value=Thomas
info:sex timestamp=1566874390231, value=male
3 row(s) in 0.0210 seconds
或:查看指定行指定列或列族的数据
hbase(main):023:0> get 'student','1001','info:name'
COLUMN CELL
info:name timestamp=1566874355716, value=Thomas
1 row(s) in 0.0080 seconds
- 删除数据
hbase(main):024:0> delete 'student','1001','info:sex'
0 row(s) in 0.0390 seconds
hbase(main):025:0> get 'student','1001'
COLUMN CELL
info:age timestamp=1566874407155, value=18
info:name timestamp=1566874355716, value=Thomas
2 row(s) in 0.0110 seconds
hbase(main):026:0> deleteall 'student','1001'
0 row(s) in 0.0050 seconds
hbase(main):027:0> get 'student','1001'
COLUMN CELL
0 row(s) in 0.0040 seconds
=> 1
- 清空表数据
hbase(main):029:0> truncate 'student'
Truncating 'student' table (it may take a while):
- Disabling table...
- Truncating table...
0 row(s) in 8.1010 seconds
- 删除表
hbase(main):031:0> drop 'student'
ERROR: Table student is enabled. Disable it first.
Drop the named table. Table must first be disabled:
hbase> drop 't1'
hbase> drop 'ns1:t1'
首先需要先让该表为disable状态,使用命令:
hbase(main):032:0> disable 'student'
0 row(s) in 4.4390 seconds
hbase(main):033:0> drop 'student'
0 row(s) in 2.4320 seconds
然后才能drop这个表,使用命令:
hbase(main):019:0> drop 'student'
(**提示:**如果直接drop表,会报错:Drop the named table. Table must first be disabled)
- 统计一张表有多少行数据
hbase(main):028:0> count 'student'
1 row(s) in 0.0470 seconds
HBase读写流程
- HBase读数据流程
HRegionServer保存着meta表以及表数据,要访问表数据,首先Client先去访问zookeeper,
从zookeeper里面获取meta表所在的位置信息,即找到这个meta表在哪个HRegionServer上保存着。
接着Client通过刚才获取到的HRegionServer的IP来访问Meta表所在的HRegionServer,从而读取到Meta,
进而获取到Meta表中存放的元数据。
Client通过元数据中存储的信息,访问对应的HRegionServer,然后扫描所在HRegionServer的Memstore和
Storefile来查询数据。
最后HRegionServer把查询到的数据响应给Client。
- HBase写数据流程
Client也是先访问zookeeper,找到Meta表,并获取Meta表元数据。
确定当前将要写入的数据所对应的HRegion和HRegionServer服务器。
Client向该HRegionServer服务器发起写入数据请求,然后HRegionServer收到请求并响应。
Client先把数据写入到HLog,以防止数据丢失。
然后将数据写入到Memstore。
如果HLog和Memstore均写入成功,则这条数据写入成功
如果Memstore达到阈值,会把Memstore中的数据flush到Storefile中。
当Storefile越来越多,会触发Compact合并操作,把过多的Storefile合并成一个大的Storefile。
当Storefile越来越大,Region也会越来越大,达到阈值后,会触发Split操作,将Region一分为二。
HBase中的3个重要机制
- flush机制
当MemStore达到阈值,将Memstore中的数据Flush进Storefile
涉及属性:
hbase.hregion.memstore.flush.size:134217728
即:128M就是Memstore的默认阈值
hbase.regionserver.global.memstore.upperLimit:0.4
即:这个参数的作用是当单个HRegion内所有的Memstore大小总和超过指定值时,flush该HRegion的所有memstore。RegionServer的flush是通过将请求添加一个队列,模拟生产消费模式来异步处理的。那这里就有一个问题,当队列来不及消费,产生大量积压请求时,可能会导致内存陡增,最坏的情况是触发OOM。
hbase.regionserver.global.memstore.lowerLimit:0.38
即:当MemStore使用内存总量达到hbase.regionserver.global.memstore.upperLimit指定值时,将会有多个MemStores flush到文件中,MemStore flush 顺序是按照大小降序执行的,直到刷新到MemStore使用内存略小于lowerLimit - compact机制
把小的Memstore文件合并成大的Storefile文件。 - split机制
当Region达到阈值,会把过大的Region一分为二。