前言:2007年Powerset的工作人员,通过google的论文开发出了BigTable的java版本,即HBASE。2008年HBASE贡献给了Apache。HBase 需要依赖 JDK 环境。
要想明白为什么产生 HBase,就需要先了解一下 Hadoop 存在的限制?Hadoop 可以通过 HDFS 来存储结构化、半结构甚至非结构化的数据,它是传统数据库的补充,是海量数据存储的最佳方法,它针对 大文件的存储,批量访问和流式访问都做了优化,同时也通过多副本解决了容灾问题。
但是 Hadoop 的缺陷在于它只能执行批处理,并且只能以顺序方式访问数据,这意味着即使是最简单的 工作,也必须搜索整个数据集,无法实现对数据的随机访问。实现数据的随机访问是传统的关系型数据 库所擅长的,但它们却不能用于海量数据的存储。在这种情况下,必须有一种新的方案来解决海量数据存储和随机访问的问题,HBase 就是其中之一 (HBase,Cassandra,couchDB,Dynamo 和 MongoDB 都能存储海量数据并支持随机访问)。
注:数据结构分类:
结构化数据:即以关系型数据库表形式管理的数据;
半结构化数据:非关系模型的,有基本固定结构模式的数据,例如日志文件、XML 文档、 JSON 文档、Email 等;
非结构化数据:没有固定模式的数据,如 WORD、PDF、PPT、EXL,各种格式的图片、视 频等。
HBase 是一种类似于 Google’s Big Table 的数据模型,它是 Hadoop 生态系统的一部分,它将数据 储在 HDFS 上,客户端可以通过 HBase 实现对 HDFS 上数据的随机访问。它具有以下特性:
不支持复杂的事务,只支持行级事务,即单行数据的读写都是原子性的;
由于是采用 HDFS 作为底层存储,所以和 HDFS 一样,支持结构化、半结构化和非结构化的存储;
支持通过增加机器进行横向扩展;
支持数据分片;
支持 RegionServers 之间的自动故障转移;
易于使用的 Java 客户端 API;
支持 BlockCache 和布隆过滤器;
过滤器支持谓词下推。
HBase 是一个面向 列 的数据库管理系统,这里更为确切的而说,HBase 是一个面向列族的数据库管 理系统。表 schema 仅定义列族,表具有多个列族,每个列族可以包含任意数量的列,列由多个单元格 (cell )组成,单元格可以存储多个版本的数据,多个版本数据以时间戳进行区分。
下图为 HBase 中一张表的:
RowKey 为行的唯一标识,所有行按照 RowKey 的字典序进行排序;
该表具有两个列族,分别是 personal 和 office;
其中列族 personal 拥有 name、city、phone 三个列,列族 office 拥有 tel、addres 两个列。
Hbase 的表具有以下特点:
容量大:一个表可以有数十亿行,上百万列;
面向列:数据是按照列存储,每一列都单独存放,数据即索引,在查询时可以只访问指定列的数据,有效地降低了系统的 I/O 负担;
稀疏性:空 (null) 列并不占用存储空间,表可以设计的非常稀疏 ;
数据多版本:每个单元中的数据可以有多个版本,按照时间戳排序,新的数据在最上面;
存储类型:所有数据的底层存储格式都是字节数组 (byte[])。
Phoenix 是 HBase 的开源 SQL 中间层,它允许你使用标准 JDBC 的方式来操作 HBase 上的数据。在 Phoenix 之前,如果你要访问 HBase,只能调用它的 Java API,但相比于使用一行 SQL 就能实现数据 查询,HBase 的 API 还是过于复杂。 Phoenix 的理念是 we put sql SQL back in NOSQL ,即你可 以使用标准的 SQL 就能完成对 HBase 上数据的操作。同时这也意味着你可以通过集成 Spring Data JPA 或 Mybatis 等常用的持久层框架来操作 HBase。
其次 Phoenix 的性能表现也非常优异, Phoenix 查询引擎会将 SQL 查询转换为一个或多个 HBase Scan,通过并行执行来生成标准的 JDBC 结果集。它通过直接使用 HBase API 以及协处理器和自定义过 滤器,可以为小型数据查询提供毫秒级的性能,为千万行数据的查询提供秒级的性能。同时 Phoenix 还 拥有二级索引等 HBase 不具备的特性,因为以上的优点,所以 Phoenix 成为了 HBase 最优秀的 SQL 中间层。
5.1 Row Key (行键)
Row Key 是用来检索记录的主键。想要访问 HBase Table 中的数据,只有以下三种方式:
通过指定的 Row Key 进行访问;
通过 Row Key 的 range 进行访问,即访问指定范围内的行;
进行全表扫描。
Row Key 可以是任意字符串,存储时数据按照 Row Key 的字典序进行排序。这里需要注意以下两点:
因为字典序对 Int 排序的结果是 1,10,100,11,12,13,14,15,16,17,18,19,2,20,21, …,9,91,92,93,94,95,96,97,98,99。如果你使用整型的字符串作为行键,那么为了保持整型的自然序,行键必须用 0 作左填充。
行的一次读写操作时原子性的 (不论一次读写多少列)。
5.2 Column Family(列族)
HBase 表中的每个列,都归属于某个列族。列族是表的 Schema 的一部分,所以列族需要在创建表时进行定义。列族的所有列都以列族名作为前缀,例如 courses:history , courses:math 都属于
courses 这个列族。
5.3 Column Qualifier (列限定符)
列限定符,你可以理解为是具体的列名,例如 courses:history , courses:math 都属于 courses
这个列族,它们的列限定符分别是 history 和 math 。需要注意的是列限定符不是表 Schema 的一部 分,你可以在插入数据的过程中动态创建列。
5.4 Column(列)
HBase 中的列由列族和列限定符组成,它们由 : (冒号) 进行分隔,即一个完整的列名应该表述为 列族名 :列限定符 。
5.5 Cell
Cell 是行,列族和列限定符的组合,并包含值和时间戳。你可以等价理解为关系型数据库中由指定行 和指定列确定的一个单元格,但不同的是 HBase 中的一个单元格是由多个版本的数据组成的,每个版 本的数据用时间戳进行区分。
1.6 Timestamp(时间戳)
HBase 中通过 row key 和 column 确定的为一个存储单元称为 Cell 。每个 Cell 都保存着同一份数
据的多个版本。版本通过时间戳来索引,时间戳的类型是 64 位整型,时间戳可以由 HBase 在数据写入 时自动赋值,也可以由客户显式指定。每个 Cell 中,不同版本的数据按照时间戳倒序排列,即最新的数据排在最前面。