简介
HBase是一种分布式、可扩展、支持海量数据存储
的NoSQL
数据库。
它参考了谷歌的
BigTable
建模,实现的编程语言为Java
。它是Apache软件基金会的Hadoop项目的一部分,运行于HDFS
文件系统之上,为 Hadoop 提供类似于BigTable 规模的服务。因此,它可以容错地存储海量稀疏的数据。
关系数据库已经流行很多年,并且Hadoop已经有了HDFS和MapReduce,为什么需要HBase?
- Hadoop可以很好地解决大规模数据的离线批量处理问题,但是,受限于HadoopMapReduce编程框架的高延迟数据处理机制,使得Hadoop无法满足大规模数据实时处理应用的需求。
- HDFS面向批量访问模式,不是随机访问模式。
- 传统的通用关系型数据库无法应对在数据规模剧增时导致的系统扩展性和性能问题(分库分表也不能很好解决)。
- 传统关系数据库在数据结构变化时一般需要停机维护;空列浪费存储空间。
逻辑结构和物理结构
逻辑结构
-
Row Key:数据的唯一标识,设计的目的是
让数据均匀的分布于所有的regin中,在一定程度上防止数据倾斜
。最大长度是
64k
,实际应用长度一般为10-100bytes。字典序排序存储。
-
列族:HBase中所有的列都属于某个列族。
列族是表的一部分,而列不是。在定义表时,必须定义列族。
-
Name Space:命名空间,类似于关系型数据库的DatabBase 概念,每个命名空间下有多个表。HBase
有两个自带的命名空间,分别是hbase
和default
,hbase 中存放的是HBase 内置的表,default 表是用户默认使用的命名空间。 -
Region:Region是HBase中分布式存储和负载均衡的最小单元。不同的Region分布到不同的RegionServer上,但并不是最小的存储单元。
Region由一个或者多个Store组成,每个store保存一个列族,每个store由一个memStore和0至多个StoreFile组成。memStore存在内存中,StoreFile存在HDFS中。
物理结构
- HBase底层使用k-v存储。
{rowkey, column Family:column, version}
定位到唯一的单元(cell)。
- Time Stamp:每个 cell 都保存着同一份数据的多个版本。版本通过时间戳来索引。时间戳的类型是 64 位整型。时间戳可以由 HBASE(在数据写入时自动 )赋值,此时时间戳是精确到毫秒 的当前系统时间。时间戳也可以由客户显式赋值。如果应用程序要避免数据版本冲突,就必须自己生成具有唯一性的时间戳。
基础架构
架构角色
-
Region Server
Region Server为Region的管理者,其实现类为
HRegionServer
,主要作用如下:- 对于数据的操作:
get,put,delete
- 对于Region的操作:
SplitRegion,CompactRegion
- 对于数据的操作:
-
Master
Master是所有Region Server的管理者,其实现类
HMaster
,主要作用如下:- 对于表的操作:
create,delete,alter
- 对于Region Server的操作:分配Region分配到每个RegionServer,监控每个RegionServer的状态,负责负载均衡和故障转移。
- 对于表的操作:
-
Zookeeper
- mater的高可用(通过Zookeeper来保证集群中只有1个master在运行,如果master异常,会通过竞争机制产生新的master提供服务。)
- Region Server的监控(通过Zookeeper来监控RegionServer的状态,当ReginServer有异常时,会通过回调的方式通知MasterRegion的上下线信息)
- 元数据的入口
-
HDFS
HDFS 为HBase 提供最终的底层数据存储服务,同时为HBase 提供高可用的支持。
安装部署
Shell操作
基本操作
-
进入 HBase 客户端命令行
hbase shell
-
查看当前命名空间下有哪些表
list
表的操作
-
创建表
create 'student','info'
-
插入数据
put 'student','10001','info:name','zhangsan'
put 'student','10001','info:age,'30'
-
扫描查看数据
scan 'student'
scan 'student',{STARTROW=>'10001',STOPROW=>'10002'} #左闭右开
-
查看表结构
describe 'student'
-
查看指定行
get 'student','10001','info:name'
-
统计行数
count 'student'
-
删除数据
delete 'student','10002'
delete 'student','10002','info:sex'
-
清空表
truncate 'student'
-
删除表
disable 'student'
drop 'student'
架构原理
-
StoreFile:
保存实际数据的物理文件,StoreFile以
HFile
的形式存储在HDFS上。每个Store会有一个或者多个StoreFile,数据在每个StoreFile上都是有序的。 -
MemStore
写缓存,由于HFile中的数据要求是有序的,所以数据先存储在MemStore中,排好序后,等到达书写时机时才会刷写到HFile,每次刷写都会形成一个新的HFile。
-
WAL(Write-Ahead logfile)
由于数据要经MemStore 排序后才能刷写到HFile,但把数据保存在内存中会有很高的概率导致数据丢失,为了解决这个问题,数据会先写在一个叫做Write-Ahead logfile 的文件中,然后再写入MemStore 中。所以在系统出现故障的时候,数据可以通过这个日志文件重建。
写流程
流程
- Client先访问zookeeper,获取
hbase:meta
表位于哪个Region Server
中 - 访问对于的
Region Server
,获取habe:meta
表,根据读请求的namespace:table/rowkey
,查询出目标数据位于哪个Region Server
中的哪个Region
中。并将该table的region信息以及meta表的位置信息缓存到客户端的meta cache,方便下次访问。 - 与目标
Region Server
进行通信。 - 将数据顺序写入(追加)到WSL。
- 将数据写入到对应的
MemStore
中,数据会在MemStore
中排序。 - 向客户端方式ack。
- 等达到MemStore的刷写时机后,将数据刷写到HFile。
数据Flush过程
所有的flush都是以Region为单位刷新
-
当某个MemStore的大小达到了
hbase.hregion.memstore.flush.size(默认值128M)
,其所在Region的所有MemStore都会刷写。当MemStore的大小达到了
hbase.hregion.memstore.flush.size(默认值128M)* hbase.hregion.memstore.block.multiplier(默认值4)
,会阻止继续往该MemStore写数据。 -
当
Region Server
中MemStore
的总大小达到java_heapsize * hbase.regionserver.global.memstore.size(默认值0.4)* hbase.regionserver.global.memstore.size.lower.limit(默认值0.95)
,Region会按照其所有MemStore的大小顺序(由大到小)依次进行刷写。直到Region Server
中所有的MemStore的总大小到上述值以下。当RegionServer中,所有Region中的MemStore的总大小达到了
java_heapsize * hbase.regionserver.global.memstore.size(默认值0.4)
时,会阻塞当前 RegionServer 的所有写请求(无法往Region中的MemStore写入数据),直到RegionServer中,所有Region中的MemStore的总大小 低于java_heapsize * hbase.regionserver.global.memstore.size(默认值0.4)* hbase.regionserver.global.memstore.size.lower.limit(默认值0.95)
时,才取消阻塞(允许写入数据)。 -
到达自动刷写的时间,也会触发MemStore flush。自动刷新的时间间隔由该属性进行配置
hbase.regionserver.optionalcacheflushinterval(默认1小时)
-
手动刷写
flush 'tableName'
读流程
读流程
- Client先访问zookeeper,获取
hbase:meta
表位于哪个Region Server
中 - 访问对于的
Region Server
,获取habe:meta
表,根据读请求的namespace:table/rowkey
,查询出目标数据位于哪个Region Server
中的哪个Region
中。并将该table的region信息以及meta表的位置信息缓存到客户端的meta cache,方便下次访问。 - 与目标
Region Server
进行通信。 - 分别在
Block Cache(读缓存)
中,MemStore
和Store File
中查询目标数据,并将查到的所有数据进行合并。此处所有数据是指同一条数据的不同版本(time stamp)或者不同类型。 - 将从文件查询到的数据块,缓存到
Block Cache
。 - 将合并的最终结果返回给客户端。
StoreFile Compaction
由于MemStore
每次刷写都会生成一个新的HFile,且同一个字段的不同版本和不同类型可能会分布在不同的HFile中,因此查询时需要便利所有的HFile。为了减少HFile的个数,以及清理到过期和删除的数据,会进行StoreFile Compaction
。
compaction分为两种,分别是Minor Compation
和Major Compaction
.
-
Minor Compaction会将临近的若干个较小的HFile 合并成一个较大的HFile,但不会清理过期和删除的数据。
触发时机:小文件[小于128M]数达到3个会触发。
-
Major Compaction 会将一个Store 下的所有的HFile 合并成一个大HFile,并且会清理掉过期和删除数据。
触发时机:默认是7天合并一次,
hbase.hregion.maiorcompaction(默认值604800000ms)
,设置为0,即取消自动合并。
Region Split
默认情况下,每个Table起初只有一个
Region
,随着数据的不断写入,Region
会自动进行拆分。刚拆分时,两个字Region都位于当前的Region Server,但出于负载均衡的考虑,HMaster有可能会将某个Region转移给其他的RegionServer。