HBase是一种分布式、可扩展、支持海量数据存储的NoSQL数据库。
- 是一种面向列簇存储的非关系型数据库。
- 用于存储结构化和非结构化的数据,适用于单表非关系型数据的存储,不适合做关联查询,类似JOIN等操作。
- 基于HDFS,数据持久化存储的体现形式是HFile,存放于DataNode中,被ResionServer以region的形式进行管理。
- 延迟较低,接入在线业务使用,面对大量的企业数据,HBase可以实现单表大量数据的存储,同时提供了高效的数据访问速度。
一、逻辑结构

二、物理结构

三、数据模型
3.1、Name Space
命名空间,类似于关系型数据库的 DataBase 概念,每个命名空间下有多个表。HBase有两个自带的命名空间,分别是”hbase”和”default”,”hbase”中存放的是HBase内置的表,”default”表是用户默认使用的命名空间。
3.2、Region
Region 的概念和关系型数据库的分区或分片类似(但只需要声明列族、不需要声明列)。
Region 是 HBase中 分布式存储 和 负载均衡 的最小单元,Region 包括完整的行,所以 Region 是以行为单位 表的一个子集。不同的 Region 可以分别在不同的 RegionServer 上。
每个表一开始只有一个 Region,每个 Region 会保存一个表里 某段连续的数据,随着数据不断插 入表,Region不断增大,当增大到一个阀值的时候,Region就会二等分,生成两个新的Region;
Table 中的所有行都按照 RowKsey 的字典序排列,Table 在行的方向上分割为多个 Region,基于 Rowkey 的不同范围分配到不通的 Region 中(Rowkey的范围,第一个Rowkey的起始索引 和 最后一Rowkey的结束索引为空串” “,每个Region是前闭后开[起始索引, 结束索引) )。
3.3、Row
HBase 表中的每行数据都由 一个 RowKey 和 一个或多个 Column(列)组成,数据是按照 RowKey 的字典顺序存储的,并且查询数据时只能根据 RowKey 进行检索,所以 RowKey 的设计十分重要。
3.4、Row Key
Rowkey 的概念和 mysql 中的主键类似,Hbase 使用 Rowkey 来唯一的区分某一行的数据。Hbase只支持3种查询方式:
1、基于Rowkey的单行查询;
2、基于Rowkey的范围扫描 ;
3、全表扫描;
因此,Rowkey对Hbase的性能影响非常大。设计的时候要兼顾基于Rowkey的单行查询也要键入Rowkey的范围扫描。
Rowkey 行键可以是任意字符串(最大长度是64KB,实际应用中长度一般为 10-100bytes),最好是16。在HBase 内部,Rowkey 保存为字节数组。HBase会对表中的数据按照 Rowkey 字典序排序,所以不同的rowkey设计对查询性能影响较大。
3.5、Column Family(列簇)
Hbase 通过列簇划分数据的存储,列簇下面可以包含任意多的列,实现灵活的数据存取。列簇是由一个一个的列组成(任意多),在列数据为空的情况下,不会占用存储空间。
Hbase 创建表的时候必须指定列簇。就像关系型数据库创建的时候必须指定具体的列是一样的。
Hbase的列簇不是越多越好,官方推荐的是列簇最好小于或者等于3。一般是1个列簇。
新的列簇成员(列)可以随后动态加入,Family下面可以有多个Qualifier,所以可以简单的理解为,HBase中的列是二级列,也就是说Family是第一级列,Qualifier是第二级列。
权限控制、存储以及调优都是在列簇层面进行的;
HBase把同一列簇里面的数据存储在同一目录下,由几个文件保存。
3.6、Column
HBase中的每个列,由列簇加上列限定符组成,一般是“列簇:列标识(column family : column qualifier)”,例如 info : name,info : age。创建表的时候只需指明列簇,不用指定列标识。
列限定符属于数据的一部分,每条数据的列限定符都可以不一样
3.7、Time Stamp(version)
用于标识数据的不同版本(version),针对每个列簇进行设置(若列簇的version=3,那它下面的所有列的version都有3个版本),若建表时没有指定version,默认值version=1
在写入数据的时候,如果没有指定相应的timestamp,HBase会自动添加一个timestamp(默认与服务器时间保持一致)。timestamp也可以由客户显式赋值,如果应用程序要避免数据版本冲突,就必须自己生成具有唯一性的时间戳。
每个cell中,不同版本的数据按照时间倒序排序,即最新的数据排在最前面。
为了避免数据存在过多版本造成的的管理(包括存贮和索引)负担,hbase 提供了两种数据版本回收方式: 1、保存数据的最后 n 个版本 ; 2、保存最近一段时间内的版本(设置数据的生命周期 TTL)。
3.8、Cell
由{Rowkey,ColumnFamily : ColumnQualifier, TimeStamp} 确定唯一的cell。
cell 中的所有字段数据 都没有数据类型,全部是字节码形式存储。被视为字节数组byte[]
四、HBase架构

包括了HMaster、HRegionSever、HRegion、HLog、Store、MemStore、StoreFile、HFile等。
HBase底层依赖HDFS,通过DFS Cilent进行HDFS操作。HMaster负责把HRegion分配给HRegionServer,每一个HRegionServer可以包含多个HRegion,多个HRegion共享HLog,HLog用来做灾难恢复。每一个HRegion由一个或多个Store组成,一个Store对应表的一个列族,每个Store中包含与其对应的MemStore以及一个或多个StoreFile(是实际数据存储文件HFile的轻量级封装),MemStore是在内存中的,保存了修改的数据,MemStore中的数据写到文件中就是StoreFile。
4.1、HMaster
HMaster的主要功能有:<br />①把HRegion分配到某一个RegionServer,即RegionServer的负载均衡。<br />②有RegionServer宕机了,HMaster可以把这台机器上的Region迁移到active的RegionServer上。<br />③在Region Split后,负责新Region的分配 。<br />④通过HDFS的dfs client接口回收垃圾文件(无效日志等)<br />注:HMaster(主节点)没有单点问题,HBase中可以启动多个HMaster,通过Zookeeper的Master Election机制保证总有一个Master运行。<br />⑤负责DDL的操作
4.2、HRegionServer
从节点
①维护HMaster分配给它的HRegion,处理对这些HRegion的IO请求,也就是说客户端直接和HRegionServer打交道。(从图中也能看出来)
②负责切分正在运行过程中变得过大的HRegion
③负责DML的操作
4.3、HRegion
下面我们看看HRegion的结构:
每个HRegion由多个Store构成,每个Store保存一个列族(Columns Family),表有几个列族,则有几个Store,每个Store由一个MemStore和多个StoreFile组成,MemStore是Store在内存中的内容,写到文件后就是StoreFile。StoreFile底层是以HFile的格式保存。
- HBase自动把表水平划分为多个region,每个region会保存一个表里面的某个连续数据(每条数据都有一个rowkey,按照rowkey字典排序)
- 每个表一开始都是只有一个region,随着数据不断插入表,region不断增大,当增大到一个阈值的时候,region就会等分成两个region(裂变,由hmaster实现分配到相应的regionserver服务器,实现负载均衡)
- 当table中的行不断增多,就会有越来越多的region。这样一张完整的表就会保存在多个RegionServer上
一个region由多个store组成,一个store对应一个列族。
3.4、Store
每一个region由一个或多个store组成,至少是一个store,hbase会把一起访问的数据放在一个store里面,即为每个 ColumnFamily建一个store,如果有几个ColumnFamily,也就有几个Store。一个Store由一个memStore和0或者 多个StoreFile组成。 HBase以store的大小来判断是否需要切分region
3.4.1、MemStore
memStore 是放在内存里的。保存修改的数据即keyValues。当memStore的大小达到一个阀值(默认64MB)时,memStore会被flush到文 件,即生成一个快照。目前hbase 会有一个线程来负责memStore的flush操作。
3.4.2、StoreFile
memStore内存中的数据写到文件后就是StoreFile,StoreFile底层是以HFile的格式保存。当storefile文件的数量增长到一定阈值后,系统会进行合并(minor、major compaction),在合并过程中会进行版本合并和删除工作,形成更大的storefile。
3.5、HLog
HLog(WAL log):WAL意为write ahead log(预写日志),用来做灾难恢复使用,HLog记录数据的变更(换句话说,无论要写什么数据,都要先在这个日志里登记一下新数据,再写入MemStore),包括序列号和实际数据,所以一旦region server 宕机,就可以从log中回滚还没有持久化的数据。

(HLog文件结构)
HLog文件就是一个普通的Hadoop Sequence File,Sequence File的Key是HLogKey对象,HLogKey中记录了写入数据的归属信息,除了table和Region名字外,同时还包括sequence number和timestamp,timestamp是”写入时间”,sequence number 的起始值为0,或者是最近一次存入文件系统中的sequence number。
HLog Sequence File 的Value是HBase的KeyValue对象,即对应HFile中的KeyValue,包括:row、column family、qualifier、timestamp、value,以及“Key Type”(比如PUT或DELETE)。3.6、HFile
HBase的数据最终是以HFile的形式(KeyValue的格式)存储在HDFS中的,HBase中HFile有着自己的格式。

(HFile结构图)
HFile由六部分组成:Data(数据块):保存表中的数据(KeyValue的形式),这部分可以被压缩。
- Meta (元数据块):存储用户自定义KeyValue。
- File Info:固定长度;记录了文件的一些元信息,例如:AVG_KEY_LEN,AVG_VALUE_LEN, LAST_KEY, COMPARATOR, MAX_SEQ_ID_KEY等。
- Data Index(数据块索引):记录了每个Data块的起始索引。
- Meta Index(元数据块索引):记录了每个Meta块的起始索引。
- Trailer:固定长度;用于指向其他数据块的起始点。
3.6.1、KeyValue结构

它包含了:key length、value length、key和value。
Key部分:开始是固定长度的数值,表示RowKey的长度;
紧接着是 RowKey;然后是固定长度的数值,表示Family的长度;
然后是Family;
接着是Qualifier;然
后是两个固定长度的数值,表示Time Stamp和Key Type(Put/Delete)。
Value部分:没有复杂的结构,就是纯粹的二进制数据。举个例子:执行这条语句:Put #1: rowkey=row1, cf:attr1=value1。KeyValue的核心部分将会是这样:rowlength -----------→ 4(row1长度)row -----------------→ row1columnfamilylength --→ 2columnfamily --------→ cfcolumnqualifier -----→ attr1timestamp -----------→ server time of Putkeytype -------------→ Put
3.7、Zookeeper
ZK集群的作用:
①通过zk集群的事件处理机制,可以保证集群中只有一个运行的Hmater
②Zookeeper集群中记录了-ROOT-表的位置
在这里顺便介绍一下Hbase中两张特殊的表:-ROOT-表与.META.表
-ROOT-表:记录了所有.META.表的元数据信息,-ROOT-表只有一个Region
.META.表:记录了Hbase中所有用户表的HRegion的元数据信息,.META.表可以有多个Region
③Zookeeper集群实时监控着HRegionServer这些服务器的状态,将HRegionServer的上线和下线信息实时通知给Hmaster节点,使得Hmaster节点可以随时感知各个HRegionServer的健康状态。
