HBase 权威指南
列式存储数据库以列为单位聚合数据,然后将列值顺序地存入磁盘,这种存储方式不同于行式存储的传统数据库,行式存储数据库连续地存储整行。
列式存储的出现主要基于这样一种假设:对于特定的查询,不是所有的值都是必需的。尤其是在分析型数据库里,这种情形很常见,因此需要选择一种更为合适的存储模式。

HBase结构
2006年,Google 发布论文“BigTable: A Distributed Storage System for Structured Data“。HBase 实现了 BigTable 存储结构。
表、行、列和单元格
最基本的单元是列(column)。一列或多列形成一行(row),并由唯一的行键(row key)来确定存储。反过来,一个表(table)中有若干行,其中每列可能有多个版本,在每一个单元格(cell)中存储不同的值。
所有的行按照行键字典序进行排列存储。
一行由若干列组成,若干列又构成一个列族(column family)。一个列族的所有列存储在同一个底层的存储文件里,这个存储文件叫做 HFile。
列族需要在表创建时就定义好。一个列族里可以有数百万个列。
常见的引用列的格式为 family:qualifier,qualifier 是任意的字节数组。

所有列和行的信息都会通过列族在表中定义。
每一列的值或单元格的值都具有时间戳,默认由系统指定,也可以由用户显示设置。时间戳可以被使用,例如通过不同的时间戳来区分不同版本的值。一个单元格的不同版本的值按照降序排列在一起,访问的时候优先读取最新的值。
HBase 是按照 BigTable 模型实现的,是一个稀疏的、分布式的、持久化的、多维的映射。数据存储模式如下:
(Table, RowKey, Family, Column, Timestamp) → Value
用一种编程语言的风格表示如下:
SortedMap<RowKey, List<SortedMap<Column, List<Value, Timestamp>>>>
第一个 SortedMap 代表那个表,包含一个列族的 List。列族中包含了另一个 SortedMap 存储列和相应的值。这些值在最后的 List 中,存储了值和该值被设置的时间戳。
这个数据存储模型的一个有趣的特性是单元格可以存在多个版本,不同的列被写入的次数不同。

行数据的存取操作是原子的(atomic),可以读写任意数目的列。目前还不支持跨行事务和跨表事务。
自动分区
HBase 中扩展和负载均衡的基本单元称为 region。region 本质上是以行键排序的连续存储的区间。
一张表初始的时候只有一个 region,用户开始向表里插入数据时,系统会检查这个 region 的大小,确保其不会超过配置的最大值,如果超过了限制,系统会在中间键(middle key,region 中间的那个行键)处将这个 region 拆分成两个大致相等的子 region。
每一个 region 只能由一台 region 服务器加载,每一台 region 服务器可以同时加载多个 region。

每台服务器中 region 的最佳加载数量是 10~1000,每个 region 的最佳大小事 1GB~2GB。
存储 API
系统支持单行事务,系统实现了对单个行键下存储的数据的原子读-修改-写(read-modify-write)序列。
实现
数据存储在存储文件中,称为 HFile,HFile 中存储的是经过排序的键值映射结构。文件内部由连续的块组成,块的索引信息存储在文件的尾部。当把 HFile 打开并加载都内存中时,索引信息会优先加载到内存中,每个块的默认大小是 64KB。存储文件提供了一个设定起始和终止行键范围的 API 用于扫描特定的值。
存储文件通常保存在 Hadoop 分布式文件系统中,HDFS 提供了一个可扩展的、持续的、冗余的 HBase 存储层。存储文件通过将更改写入到可配置数目的物理服务器中,以保证不丢失数据。
每次更新数据时,都会先将数据记录在提交日志(commit log)中,在 HBase 中这叫做预写日志(write-ahead log,WAL),然后才会将这些数据写入内存中的 memstore 中。一旦内存保存的写入数据的大小超过了一个给定的最大值,系统就会将这些数据移出内存作为 HFile 文件刷写到磁盘中。数据移出内存之后,系统会丢弃对应的提交日志,并保留未持久化到磁盘中的提交日志。在系统将数据移出 memstore 写入磁盘的过程中,可以不必阻塞系统的读写,通过滚动内存中的 memstore 就能达到这个目的,即用空的新 memstore 获取更新数据,将满的旧 memstore 转换成一个文件。
因为存储文件是不可被改变的,所以无法通过移除某个键值对来简单的删除值。可行的解决办法是,做个删除标记(delete marker,又称墓碑标记)。
读回的数据是两部分数据合并的结果,一部分是 memstore 中还没有写入磁盘的数据,另一部分是磁盘上的存储文件。数据检索时用不着 WAL,只有服务器内存中的数据在服务器崩溃前没有写入到磁盘,而后进行恢复数据时才会用到 WAL。
HBase 中有3个主要组件:客户端库、一台主服务器、多台 region 服务器。主服务器负责利用 Zookeeper 为 region 服务器分配 region。每台 region 服务器在 Zookeeper 中注册一个自己的临时节点,主服务器利用这些临时节点来发现可用服务器。

master 服务器负责跨 region 服务器的全局 region 的负载均衡。主服务器不是实际数据存储或者检索路径的组成部分,它仅提供了负载均衡和集群管理,不为 region 服务器或者客户端提供任何的数据服务。主服务器还提供了元数据的管理操作。
region 服务器负责为它们服务的 region 提供读写请求,也提供了拆分超过配置大小的 region 接口。
HBase 的主要客户端接口是由 org.apache.hadoop.hbase.client 包中的 HTable 类提供的。
创建 HTable 实例是有代价的。每个实例都需要扫描 .META. 表,以检查该表是否存在、是否可用,此外还要执行一些其他操作,这些检查和操作导致实例调动非常耗时。因此,建议用户只创建一次 HTable 实例,而且是每个线程只创建一个,然后在客户端应用的生存期内复用这个对象。
This chapter requires login to view full content. You are viewing a preview.
Login to View Full Content