导航

  • ​​HBase定义​​
  • ​​HBase数据模型​​
  • ​​HBase系统架构​​
  • ​​HBase 写流程​​
  • ​​HBase 读流程​​
  • ​​StoreFile Compaction​​
  • ​​Region Split​​

HBase定义

HBase是一种分布式、可扩展、支持海量数据列式存储、实时读写的NoSQL数据库

它有如下优点

1)分布式、可扩展、支持海量数据列式存储:HBase 底层数据存储依赖于HDFS系统,HDFS可以通过简单地增加DataNode实现扩展,HBase读写服务节点也一样,可以通过简单的增加RegionServer节点实现计算层的扩展;Hbase 是根据列族来存储数据

2)单表容量巨大:HBase的单表可以支持千亿行、百万列的数据规模,数据容量可以达到TB甚至PB级别。传统的关系型数据库,如 Oracle和MySQL等,如果单表记录条数超过亿行,读写性能都会急剧下降,在HBase中并不会出现这样的问题

3)实时读写:Hbase 适合存储 PB 级别的海量数据,在 PB 级别的数据以及采用廉价 PC 存储的情况下,能在几十到百毫秒内返回查询数据

4)稀疏性:HBase支持大量稀疏存储,即允许大量列值为空,并不占用任何存储空间。这与传统数据库不同,传统数据库对于空值的处理要占用一定的存储空间,这会造成一定程度的存储空间浪费。因此可以使用HBase存储多至上百万列的数据,即使表中存在大量的空值,也不需要任何额外空间

5)多版本:HBase支持多版本特性,即一个 KV 可以同时保留多个版本,用户可以根据需要选择最新版本或者某个历史版本

它有如下缺点

1)Hbase 不支持 join 等复杂操作,但可通过Phoenix组件或者Spark 组件,来实现多表 join 等复杂操作。Phoenix组件主要应用于小规模聚合的 OLTP 场景,Spark 组件应用于大规模聚合的 OLAP 场景

2)HBase原生不支持全局跨行事务,只支持单行事务模型,但同样可以使用Phoenix组件提供的全局事务模型来弥补HBase的这个缺陷

3)HBase本身并没有实现二级索引功能,所以不支持二级索引查找,同样可以使用Phoenix组件来弥补HBase的这个缺陷

HBase数据模型

hbase 简介_默认值

1)Name Space

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

2)Table

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

3)Row

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

RowKey(行键)可以是任意字符串(最大长度是 64KB,实际应用中长度一般为 10-100bytes),在hbase底层,row key保存为字节数组

4)Column

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

5)Time Stamp

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

6)Cell

由{rowkey, column Family:column Qualifier, time Stamp} 唯一确定的单元。cell中的数据全部是字节码形式存储

7)Region&Store&MemStore&StoreFile

当这个​​表数据量达到一定数量时​​​,就会分裂,分裂成多个​​Region​​​,分裂的方式是​​以行的方式进行分割​​​,例如0~100万行为一个Region,100~200万行为一个Region,而每一个Region内,又可以按照​​列族​​​进行分割,不同的列族对应不同的​​Store​​,而每一个Store又由一个 MemStore 和0至多个 StoreFile 组成(下边有详细介绍)

HBase系统架构

hbase 简介_Server_02

1)Region Server

Region Server 是所有 Region的管理者,其实现类为HRegionServer,主要作用如下:

  • 对数据的操作:get, put, delete
  • 对Region的操作:splitRegion、compactRegion

2)Master

Master是所有Region Server的管理者,其实现类为HMaster,主要作用如下:

  • 对表的操作:create, delete, alter
  • 对RegionServer的操作:分配regions到每个RegionServer,监控每个RegionServer的状态,负载均衡和故障转移

3)Zookeeper

HBase通过Zookeeper来做master的高可用、RegionServer的监控、元数据的入口以及集群配置的维护等工作

4)HDFS

HDFS为HBase提供最终的底层数据存储服务,同时为HBase提供高容错的支持

RegionServer 架构

hbase 简介_Server_03

1)StoreFile

保存实际数据的物理文件,StoreFile以Hfile的形式存储在HDFS上。每个Store会有一个或多个StoreFile(HFile),数据在每个StoreFile中都是有序的

2)MemStore

写缓存,由于HFile中的数据要求是有序的,所以数据是先存储在MemStore中,排好序后,待满足刷写时机时才会刷写到HFile,每次刷写都会形成一个新的HFile

3)WAL

由于数据要经MemStore排序后才能刷写到HFile,数据保存在内存中的这段时间会有很高的概率导致数据丢失,为了解决这个问题,数据会先写在一个叫做Write ahead log 的文件中,然后再写入MemStore中。所以在系统出现故障的时候,数据可以通过这个日志文件重建

4)BlockCache

读缓存,每次查询出的数据会缓存在BlockCache中,方便下次查询

HBase 写流程

hbase 简介_hbase_04

1)Client先访问zookeeper,先询问hbase的meta表位于哪个Region Server

2)访问对应的Region Server,获取hbase的meta表,根据写请求的namespace:table/rowkey,首先查询出目标数据应该写入哪个Region Server中的哪个Region中,然后在将该region信息以及meta表的位置信息缓存到客户端的Meta cache中一份,方便下次访问

3)然后与目标Region Server进行通讯,先将数据顺序写入(追加)到WAL,在将数据写入对应的MemStore,数据会在MemStore进行排序

4)Region Server向客户端发送ack应答

5)Region Server待达到MemStore的刷写时机后,将数据刷写到HFile

MemStore 刷写时机

hbase 简介_默认值_05

(1)​​当​​​某个memstroe的大小达到了hbase.hregion.memstore.flush.size(默认值128M),​​其所在region的所有memstore都会刷写​​​;​​当​​memstore的大小达到了hbase.hregion.memstore.flush.size(默认值128M)* hbase.hregion.memstore.block.multiplier(默认值4)时,会阻止继续往该memstore写数据

memstroe的大小若为127.9M时,依旧可以往里面写数据,但是此次写数据写多少都可以吗(2000G行吗)?显然不行,所以需要有上限,即128*4

(2)当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的总大小减小到java_heapsize* 0.38以下;当region server中memstore的总大小达到java_heapsize* hbase.regionserver.global.memstore.size(默认值0.4)时,会阻止继续往所有的memstore写数据

(3)到达自动刷写的时间,也会触发memstore flush。自动刷新的时间间隔由该属性进行配置hbase.regionserver.optionalcacheflushinterval(默认1小时)

(4)当WAL文件的数量超过hbase.regionserver.max.logs(默认值32),region会按照时间顺序依次进行刷写,直到WAL文件数量减小到hbase.regionserver.max.log以下(​​该属性2.x后已经废弃​​)

HBase 读流程

hbase 简介_hbase_06

1)Client先访问zookeeper,先询问hbase的meta表位于哪个Region Server

2)访问对应的Region Server,获取hbase的meta表,根据写请求的namespace:table/rowkey,首先查询出目标数据应该位于哪个Region Server中的哪个Region中,然后在将该region信息以及meta表的位置信息缓存到客户端的Meta cache中一份,方便下次访问

3)然后与目标Region Server建立通信后,分别在MemStore和Store File(HFile)中查询目标数据,并将查到的所有数据进行合并。此处所有数据是指同一条数据的不同版本(time stamp)或者不同的类型(Put/Delete)

4)将合并后的最终结果返回给客户端

StoreFile Compaction

hbase 简介_hbase_07

由于memstore每次刷写都会生成一个新的HFile,且同一个字段的不同版本(timestamp)和不同类型(Put/Delete)有可能会分布在不同的HFile中,因此查询时需要遍历所有的HFile。​​为了减少HFile的个数,以及清理掉过期和删除的数据,会进行StoreFile Compaction​

Compaction分为两种,分别是​​Minor Compaction​​​和​​Major Compaction​​​。Minor Compaction会将​​临近的若干个较小的HFile​​​合并成一个较大的HFile,并清理掉部分过期和删除的数据。Major Compaction​​会将一个Store下的所有的HFile合并成一个大HFile​​,并且会清理掉所有过期和删除的数据

Region Split

默认情况下,每个Table起初只有一个Region,随着数据的不断写入,Region会自动进行拆分。刚拆分时,两个子Region都位于当前的Region Server,但处于负载均衡的考虑,HMaster有可能会将某个Region转移给其他的Region Server

Region Split时机:

(1)当1个region中的某个Store下所有StoreFile的总大小超过hbase.hregion.max.filesize (10G),该Region就会进行拆分(0.94版本之前)

(2)当1个region中的某个Store下所有StoreFile的总大小超过Min(initialSize*R^3 ,hbase.hregion.max.filesize"),该Region就会进行拆分。其中initialSize的默认值为2*hbase.hregion.memstore.flush.size,R为当前Region Server中属于该Table的Region个数(0.94版本之后)

阶梯型的切分策略为:

第一次split:1^3 * 256 = 256MB
第二次split:2^3 * 256 = 2048MB
第三次split:3^3 * 256 = 6912MB
第四次split:4^3 * 256 = 16384MB > 10GB,因此取较小的值10GB
后面每次split的size都是10GB了

(3)Hbase 2.0引入了新的split策略:如果当前RegionServer上该表只有一个Region,按照2 * hbase.hregion.memstore.flush.size分裂,否则按照hbase.hregion.max.filesize分裂