3.2.3 HBase在交互式计算中的应用
Hive是基于Hadoop的一个数据仓库工具,可以将结构化的数据文件映射为一张数据库表,并提供简单的SQL查询功能;可以将SQL语句转换为MapReduce任务进行运行,也就是说Hive是一种类SQL的引擎,并能运行MapReduce任务,它可以帮助熟悉SQL的人简单快捷地运行MapReduce任务。由于Hive在Hadoop上运行批量操作,它需要花费很长的时间,通常是几分钟到几个小时才可以获取到查询的结果,因此Hive适合用来对一段时间内的数据进行分析查询。例如,用来计算趋势或者网站的日志。严格地讲Hive并非数据库,它主要是让开发人员能够通过SQL来计算和处理HDFS上的结构化数据,适用于离线的批量数据计算。
HBase是Hadoop DataBase的简称,是一种基于Hadoop的NoSQL数据库,主要适用于海量明细数据(十亿、百亿)的随机实时查询,如日志明细、交易清单、轨迹行为等。
HBase是一个分布式的、面向列的开源数据库,该技术来源于Fay Chang所撰写的Google论文《Bigtable:一个结构化数据的分布式存储系统》。就像Bigtable利用了Google文件系统(File System)所提供的分布式数据存储一样,HBase在Hadoop之上提供了类似于Bigtable的能力。
HBase不同于一般的关系数据库,它是一个基于列而不是基于行的适合于非结构化数据存储的数据库。也就是说,HBase是一个高可靠性、高性能、面向列、可伸缩的分布式存储系统。利用HBase技术可在廉价PC Server上搭建起大规模结构化存储集群,HBase的目标是存储并处理大型的数据,更具体来说是仅需使用普通的硬件配置,就能够处理由成千上万的行和列所组成的大型数据。HBase利用Hadoop HDFS作为其文件存储系统,利用Hadoop MapReduce来处理HBase中的海量数据。
1)HBase的特点
因为HBase存储的是松散的数据,所以如果在应用程序中,数据表每一行的结构是有差别的,那么可以考虑使用HBase。因为HBase的列可以动态增加,并且列为空就不存储数据,所以如果需要经常追加字段,且大部分字段是NULL值的,那可以考虑HBase。因为HBase可以根据Row Key提供高效的查询,所以如果数据(包括元数据、消息、二进制数据等)都有着同一个主键,或者需要通过键来访问和修改数据,使用HBase是一个很好的选择。
(1)HBase的优点
•列可以动态增加,并且列为空就不存储数据,节省存储空间。
•HBase自动切分数据,使得数据存储自动具有水平可伸缩性。
•HBase可以提供高并发读写操作的支持。
(2)HBase的缺点
•不能支持条件查询,只支持按照Row Key(行键)来查询。
•HBase并不适合传统的事务处理程序或关联分析,不支持复杂查询,一定程度上限制了它的使用,但是用它做数据存储的优势也同样非常明显。
2)HBase的数据结构
要使用HBase,首先要了解HBase的数据结构,HBase的概念视图见表3⁃8。HBase会存储系列的行记录,行记录有三个基本类型的定义:Row Key、Time Stamp、Column Family。
表3⁃8 HBase概念视图

(1)Row Key(行键)
与NoSQL数据库一样,Row Key是用来检索记录的主键。访问HBase table中的行,只有三种方式:
•通过单个Row Key访问。
•通过Row Key的range(正则)访问。
•全表扫描。
行键可以是任意字符串(最大长度是64 KB,实际应用中长度一般为10 ~ 100 bytes),在HBase内部,Row Key保存为字节数组。
在存储时,数据按照Row Key的字典序(Byte Order)排序存储。设计Key时,要充分考虑排序存储这个特性,将经常一起读取的行存储到一起(位置相关性)。
(2)Column Family(CF,列族)
HBase表中每个列都必须属于某个列族,列族必须作为表模式定义的一部分预先给出(有点像关系型数据库中的列名,定义完一般情况下就不会再去修改)。列名以列族作为前缀,每个列族都可以有多个列成员。新的列族成员(也就是列)可以随后按需增加,由于每个列族包含的列是动态加入,因此HBase表是按照稀疏表方式存储,只存储有值的列信息。
HBase把同一列族里面的数据存储在同一目录下,由几个文件保存。
(3)Cell(单元)
HBase中通过Row key和CF确定的一个存储单元称为Cell。Cell中的数据是没有类型的,全部是字节码形式存储。每个Cell都保存着同一份数据的多个版本,版本通过时间戳来索引。
(4)Time Stamp(时间戳)
在HBase每个Cell存储单元对同一份数据有多个版本,根据唯一的时间戳来区分每个版本之间的差异,不同版本的数据按照时间倒序排序,最新的数据版本排在最前面,时间戳的类型是64位整型。时间戳可以由HBase(在数据写入时自动)赋值,此时时间戳是精确到毫秒的当前系统时间。时间戳也可以由客户显示赋值。如果应用程序要避免数据版本冲突,就必须自己生成具有唯一性的时间戳。为了避免数据存在过多版本造成的管理(包括存储和索引)负担,HBase提供了两种数据版本回收方式。一种是保存数据的最后n个版本,另一种是保存最近一段时间内的版本(比如最近7天)。用户可以针对每个列族进行设置。
HBase表的通用格式见表3⁃9。
表3⁃9 HBase表格式

HBase是一个面向列的数据库,在表中它由行排序,一个表有多个列族以及每一个列族可以有任意数量的列,后续列的值连续存储在磁盘上,表中的每个单元格值都具有时间戳。HBase中包括:
•表是行的集合。(https://www.daowen.com)
•行是列族的集合。
•列族是列的集合。
•列是键值对的集合。
这里的列式存储或者说面向列,就是列族存储,HBase是根据列族来存储数据的。列族下面可以有非常多的列,列族在创建表的时候就必须指定。
HBase中的所有数据文件都存储在Hadoop HDFS文件系统上,主要有HFile和HLog File两种格式。
3)HBase的系统架构
图3⁃13为HBase各模块关系图,HBase底层依赖Hadoop的HDFS存储系统。

图3⁃13 HBase各模块组成
(1)Master
HBase Master用于协调多个Region Server,侦测各个Region Server之间的状态,并平衡Region Server之间的负载。HBase Master还有一个职责就是负责分配Region给Region Server。HBase允许多个Master节点共存,但是这需要Zookeeper的帮助。不过当多个Master节点共存时,只有一个Master是提供服务的,其他的Master节点处于待命的状态。当正在工作的Master节点宕机时,其他的Master则会接管HBase的集群。
(2)Region Server
对于一个Region Server而言,其包括了多个Region。Region Server的作用只是管理Region,以及实现读写操作。Client直接连接Region Server,并通信获取HBase中的数据。对于Region而言,则是真实存放HBase数据的地方,也就说Region是HBase可用性和分布式的基本单位。如果当一个表格很大,并由多个CF组成时,那么表的数据将存放在多个Region之间,并且在每个Region中会关联多个存储的单元。

(3)Zookeeper
Zookeeper是HBase集群的“协调器”,对于HBase而言,Zookeeper的作用是至关重要的。首先Zookeeper是作为HBase Master的HA(High Availability,高可用)解决方案。也就是说,是Zookeeper保证了至少有一个HBase Master处于运行状态,并且Zookeeper负责Region和Region Server的注册,并成为分布式大数据框架中容错性的标准框架。不光是HBase,几乎所有的分布式大数据相关的开源框架,都依赖于Zookeeper实现HA。
如图3⁃14所示,HBase的集群是通过Zookeeper来进行机器之间的协调,也就是说HBase Master(HMaster)与HBase Region Server(HRegion Server)之间的关系靠Zookeeper来维护。当一个客户(Client)需要访问HBase集群时,Client需要先和Zookeeper来通信,然后才会找到对应的HRegion Server。每一个HRegion Server管理着很多个HBase Region(HRegion)。对于HBase来说,HRegion是HBase并行化的基本单元。因此,数据也都存储在HRegion中。
4)HBase的操作
相比较Hive,HBase实现了更快地查询响应,支持行级别的事务,并支持在行级别维度上进行数据更新。HBase本身并不提供对查询语言(如SQL)的支持,但这并不是一个问题,因为Hive已经可以和HBase集成。其基本原理是借助Hive将数据加载到HBase中,等数据加载完成后,就可以利用Hive使用类SQL(HQL)语言编写程序或者交互数据处理了,这样一来,HBase也可以支持类SQL查询中的常见操作命令。HBase操作分为表操作和数据操作两种类型,表3⁃10列举了HBase常用操作命令及使用方法。
表3⁃10 HBase命令及使用方法


基于HBase的系统设计与开发中,需要考虑的因素不同于关系型数据库,HBase模式本身很简单,但赋予了更多调整空间。有一些模式写数据时性能很好,但读取数据时表现不好,或者正好相反。在实际项目中,考虑HBase设计模式时,需要从以下几方面内容着手:
•这个表应该有多少个列族。
•列族使用什么数据。
•每个列族应有多少个列。
•列名应该是什么,尽管列名不必在建表时定义,但是读写数据时是需要的。
•单元应该存放什么数据。
•每个单元存储什么时间版本。
•行键结构是什么,应该包括什么信息。