简介
HBase 是一个基于HDFS 的面向列的分布式数据库,属于非关系型数据库的一种。
HBase 本质上只有插入操作,更新和删除都是使用插入方式完成的,这是由其底层 HDFS 的流式访问特性(一次写入、多次读取)决定的。
HBase在更新时总会插入一个带时间戳的新行,而删除时则插入一个带有删除标记的新行。每次插入都有一个时间戳的标记,每次都是一个新的版本,Hbase会保留一定数据的版本(自行设置)。如果查询时提供时间戳则返回距离该时间最近的版本,否则返回离现在最近的版本。
一、 HBase体系结构
HBase采用Master/slaves 的主从服务器结构,由一个HMaste服务器和多个HRegion Server服务器组成,所有的服务器都通过Zoo Keeper协调并处理运行期间遇到的错误。
HMaster负责管理所有的HRegion Server,各HRegion Server负责存储许多HRegion,每一个HRegion是对HBase逻辑表的分块。
1. HRegion
HBase使用表存储数据,表由行和列组成。但是当表超过设定值大小时,Hbase会自动将表划分不同的区域,每个区域被称为HRegion。
HRegion是集群上分布式存储和负责均衡的最小单位,类似于HDFS中文件与文件块的概念。
一个HRegion保存一个表中连续的数据,通过表名及主键来区分每一个HRegion。
最开始一个表只有一个HRegion,随着HRegion增大,超出设定阈值,会分裂成两个大小基本相同的HRegion,称为HRegion分裂。
每个HRegion由HStore组成,HStore由两部分组成:Mem Store和Store File,用户写入的数据首先放入Mem Store,当Mem Store满了以后再刷入Store File。
Store File 是 HBase的最小存储单位,底层最终由HFile实现。HFile是键值对数据存储的格式,实质是HDFS的二进制文件。
2. HRegion Server
HRegion Server负责响应客户端IO请求,向HDFS中读写数据,一台机器上只运行一个HRegion Server。HRegion Server包含两个部分:HLog 和 HRegion。
HLog用于存储数据日志,实质是HDFS的Sequence File。到达HRegion的写操作首先追加到日志中,才被加入到内存中的Mem Store。
HLog 主要用于故障恢复,如果HRegion所在主机发生故障,那么所维护的HRegion会被重新分配至新的主机上,新的HRegion Server 在加载HRegion时,可通过Hlog恢复数据。
3. HMaster
HMaster主要任务是告诉每个HRegion Server需要维护哪些HRegion。在Hbase中可以启动多个HMaster,通过ZooKeeper的Master选举机制来保证系统中总会有一个HMaster在运行。
HMaster包括以下功能:
1. 管理用户对表的增改查操作
2. 管理HRegion的负责均衡,调整HRegion分布
3. 在HRegion分裂后,负责HRegion分配
4. 在HRegion Server停机后,负责失效HRegion Server上的HRegion迁移
4. zoo keeper
Zoo keeper 是存储HBase -ROOT-表和.META.表的位置,这是HBase中两张特殊的表。称为根数据表(-ROOT-)和元数据表(.META.)。
元数据表记录普通用户表的HRegion标识符信息,每个HRgion的标识符为:表名+开始主键+唯一ID。
随着用户表的HRegion的分裂,.META.表的信息也会增加,并且还可能被分割为几个HRegion,此时可以用一个-ROOT-表来保存META的HRegion信息,而-ROOT-表是不能被分割的,也就是-ROOT-表只有一个HRegion。
那么客户端(Client)在访问用户数据前需要先访问Zoo Keeper,然后访问-ROOT-表,接着访问.META.表,最后才能找到用户数据所在位置进行访问。
二、 HBase数据模型
1. 数据模型
- 表(Table):是一种稀疏表(不存储数据为NULL的数据),表的索引是行关键字、列关键字、时间戳
- 行关键字(Row Key):行的主键,唯一标识一行数据,也称为行键。
表中的行根据行键进行字典排序,所有对表的访问都要通过表的行键。
在创建表时,行键不用也不能预先定义,而对表数据进行操作时必须指定行键,行键在添加数据时首次被确定。 - 列族(Column Family):行中的列被分为列族。
同一个列族的所有成员具有相同的列族前缀。例如[course:math]和[course:art]都是列族[course]的成员。
一个表的列族必须在创建表时预先定义,列族名称不能包含ASCII控制字符(编号0~31+127)和冒号(:)。 - 列关键字(Column Key):也称列键。 格式为:[Family:qualifier]。
family 是列族名,用于表示列族前缀。qualifier是列修饰符,表示列族中的一个成员,列族成员可以在随后按需拓展。 - 存储单元(Cell): 在HBase中,值是作为一个单元保存在系统中的。
要定位一个单元,需要用[行键+列键+时间戳] 3个要素。 - 时间戳(Timestamp):插入单元格时间,默认为单元格的版本号。
2. 概念图
在传统数据库中,只能通过表的主键和唯一字段定位到某一条数据。
如上表所示:
主键为name,主要字段有name、grade、math、art。
由于主键唯一标识了一行记录,所以我们很容易按姓名查询某位同学的成绩。
那么思考以下几个问题:
- 如果新增一门课程,在不修改表结构的情况下,能保存成绩么?
- 如果有同学参加补考,怎么保存两次成绩。
- 如果同学只参加一门考试,其他课程都没有成绩。我们能保存只有成绩的课程来节省存储空间么?
HBase的数据模型就能完美解决以上问题。
- 可以通过[行键+时间戳+列族]来访问具体的值(单元)。
- 对表操作必须指定行键和列键,每次操作都会增加一条数据并会自动生成时间戳。从上到下倒序排列,不必由用户管理。
- 每次只针对一个列键操作。且列修饰符可以为空。
eg. 在t4时刻,客户端添加[jason] 的[grade]为[2]。
类似操作为:先找到行键[jason],然后指定列键并赋值[grade:=2]。这里的列族修饰符可以为空。前面提到过列族修饰符可以由任意字符组成。
现在基于HBase回答前面的问题:
- 如果jason新增英语科目成绩,那么指定行键[jason],列键[source:english],以及值(英语成绩)即可。
- 如果jason 参加数学补考,那么直接指定行键[jason],列键[source:math],以及值(数学补考成绩)即可。
- 前面说过HBase是稀疏的存储设计。其实概览图中空白部分是不会实际被存储的。
3. 物理结构
如图所示:
HBase 就是这样一个基于列的映射数据库,他只能表示简单的键值映射关系。
4.HBase数据特点
- 数据类型: 只有简单的字符串类型。(传统SQL有多种数据类型)
- 数据操作:只有简单的插入、查询、删除、清空等操作,表和表之间是分离的,没有复杂的表和表之间的关系。(传统SQL有多种连接操作)
- 存储模式:基于列的存储。每个列族由几个文件保存,不同列族的文件是分离的。(传统SQL是基于表格结构和行模式存储)
- 数据维护: 只是简单的插入了新数据,它的旧版本会保留(传统SQL是替换修改操作)
- 可伸缩: 分布式数据库。能够轻松的增加和减少硬件数量,并且对错误兼容性较高。(传统SQL需要中间层才能实现类似功能)
本文参考与《基于 Hadoop 与 Spark 的大数据开发实战》