hbase – hadoop database,是一个高可靠性、高性能、面向列、可伸缩的分布式存储系统,利用hbase技术可在廉价pc server上搭建起大规模结构化存储集群。
hbase是google bigtable的开源实现,类似google bigtable利用gfs作为其文件存储系统,hbase利用hadoop hdfs作为其文件存储系统;google运行mapreduce来处理bigtable中的海量数据,hbase同样利用hadoop mapreduce来处理hbase中的海量数据;google bigtable利用 chubby作为协同服务,hbase利用zookeeper作为对应。

上图描述了hadoop ecosystem中的各层系统,其中hbase位于结构化存储层,hadoop hdfs为hbase提供了高可靠性的底层存储支持,hadoop mapreduce为hbase提供了高性能的计算能力,zookeeper为hbase提供了稳定服务和failover机制。
此外,pig和hive还为hbase提供了高层语言支持,使得在hbase上进行数据统计处理变的非常简单。 sqoop则为hbase提供了方便的rdbms数据导入功能,使得传统数据库数据向hbase中迁移变的非常方便。
1. native java api,最常规和高效的访问方式,适合hadoop mapreduce job并行批处理hbase表数据
2. hbase shell,hbase的命令行工具,最简单的接口,适合hbase管理使用
3. thrift gateway,利用thrift序列化技术,支持c++,php,python等多种语言,适合其他异构系统在线访问hbase表数据
4. rest gateway,支持rest 风格的http api访问hbase, 解除了语言限制
5. pig,可以使用pig latin流式编程语言来操作hbase中的数据,和hive类似,本质最终也是编译成mapreduce job来处理hbase表数据,适合做数据统计
6. hive,当前hive的release版本尚没有加入对hbase的支持,但在下一个版本hive 0.7.0中将会支持hbase,可以使用类似sql语言来访问hbase
row key
timestamp
column family
uri
parser
r1
t3
url=http://www.taobao.com
title=天天特价
t2
host=taobao.com
t1
r2
t5
url=http://www.alibaba.com
content=每天…
t4
host=alibaba.com
Ø row key: 行键,table的主键,table中的记录按照row key排序
Ø timestamp: 时间戳,每次数据操作对应的时间戳,可以看作是数据的version number
Ø column family:列簇,table在水平方向有一个或者多个column family组成,一个column family中可以由任意多个column组成,即column family支持动态扩展,无需预先定义column的数量以及类型,所有column均以二进制格式存储,用户需要自行进行类型转换。
当table随着记录数不断增加而变大后,会逐渐分裂成多份splits,成为regions,一个region由[startkey,endkey)表示,不同的region会被master分配给相应的regionserver进行管理:
hbase中有两张特殊的table,-root-和.meta.
Ø .meta.:记录了用户表的region信息,.meta.可以有多个regoin
Ø -root-:记录了.meta.表的region信息,-root-只有一个region
Ø zookeeper中记录了-root-表的location
client访问用户数据之前需要首先访问zookeeper,然后访问-root-表,接着访问.meta.表,最后才能找到用户数据的位置去访问,中间需要多次网络操作,不过client端会做cache缓存。
在hbase系统上运行批处理运算,最方便和实用的模型依然是mapreduce,如下图:
hbase table和region的关系,比较类似hdfs file和block的关系,hbase提供了配套的tableinputformat和tableoutputformat api,可以方便的将hbase table作为hadoop mapreduce的source和sink,对于mapreduce job应用开发人员来说,基本不需要关注hbase系统自身的细节。
hbase client使用hbase的rpc机制与hmaster和hregionserver进行通信,对于管理类操作,client与hmaster进行rpc;对于数据读写类操作,client与hregionserver进行rpc
zookeeper quorum中除了存储了-root-表的地址和hmaster的地址,hregionserver也会把自己以ephemeral方式注册到zookeeper中,使得hmaster可以随时感知到各个hregionserver的健康状态。此外,zookeeper也避免了hmaster的单点问题,见下文描述
hmaster没有单点问题,hbase中可以启动多个hmaster,通过zookeeper的master election机制保证总有一个master运行,hmaster在功能上主要负责table和region的管理工作:
1. 管理用户对table的增、删、改、查操作
2. 管理hregionserver的负载均衡,调整region分布
3. 在region split后,负责新region的分配
4. 在hregionserver停机后,负责失效hregionserver 上的regions迁移
hregionserver主要负责响应用户i/o请求,向hdfs文件系统中读写数据,是hbase中最核心的模块。
hregionserver内部管理了一系列hregion对象,每个hregion对应了table中的一个region,hregion中由多个hstore组成。每个hstore对应了table中的一个column family的存储,可以看出每个column family其实就是一个集中的存储单元,因此最好将具备共同io特性的column放在一个column family中,这样最高效。
hstore存储是hbase存储的核心了,其中由两部分组成,一部分是memstore,一部分是storefiles。memstore是sorted memory buffer,用户写入的数据首先会放入memstore,当memstore满了以后会flush成一个storefile(底层实现是hfile),当storefile文件数量增长到一定阈值,会触发compact合并操作,将多个storefiles合并成一个storefile,合并过程中会进行版本合并和数据删除,因此可以看出hbase其实只有增加数据,所有的更新和删除操作都是在后续的compact过程中进行的,这使得用户的写操作只要进入内存中就可以立即返回,保证了hbase
i/o的高性能。当storefiles compact后,会逐步形成越来越大的storefile,当单个storefile大小超过一定阈值后,会触发split操作,同时把当前region split成2个region,父region会下线,新split出的2个孩子region会被hmaster分配到相应的hregionserver上,使得原先1个region的压力得以分流到2个region上。下图描述了compaction和split的过程:
在理解了上述hstore的基本原理后,还必须了解一下hlog的功能,因为上述的hstore在系统正常工作的前提下是没有问题的,但是在分布式系统环境中,无法避免系统出错或者宕机,因此一旦hregionserver意外退出,memstore中的内存数据将会丢失,这就需要引入hlog了。每个hregionserver中都有一个hlog对象,hlog是一个实现write ahead log的类,在每次用户操作写入memstore的同时,也会写一份数据到hlog文件中(hlog文件格式见后续),hlog文件定期会滚动出新的,并删除旧的文件(已持久化到storefile中的数据)。当hregionserver意外终止后,hmaster会通过zookeeper感知到,hmaster首先会处理遗留的
hlog文件,将其中不同region的log数据进行拆分,分别放到相应region的目录下,然后再将失效的region重新分配,领取 到这些region的hregionserver在load region的过程中,会发现有历史hlog需要处理,因此会replay hlog中的数据到memstore中,然后flush到storefiles,完成数据恢复。
hbase中的所有数据文件都存储在hadoop hdfs文件系统上,主要包括上述提出的两种文件类型:
1. hfile, hbase中keyvalue数据的存储格式,hfile是hadoop的二进制格式文件,实际上storefile就是对hfile做了轻量级包装,即storefile底层就是hfile
2. hlog file,hbase中wal(write ahead log) 的存储格式,物理上是hadoop的sequence file
下图是hfile的存储格式:
首先hfile文件是不定长的,长度固定的只有其中的两块:trailer和fileinfo。正如图中所示的,trailer中有指针指向其他数据块的起始点。file info中记录了文件的一些meta信息,例如:avg_key_len, avg_value_len, last_key, comparator, max_seq_id_key等。data index和meta index块记录了每个data块和meta块的起始点。
data block是hbase i/o的基本单元,为了提高效率,hregionserver中有基于lru的block cache机制。每个data块的大小可以在创建一个table的时候通过参数指定,大号的block有利于顺序scan,小号block利于随机查询。每个data块除了开头的magic以外就是一个个keyvalue对拼接而成, magic内容就是一些随机数字,目的是防止数据损坏。后面会详细介绍每个keyvalue对的内部构造。
hfile里面的每个keyvalue对就是一个简单的byte数组。但是这个byte数组里面包含了很多项,并且有固定的结构。我们来看看里面的具体结构:
开始是两个固定长度的数值,分别表示key的长度和value的长度。紧接着是key,开始是固定长度的数值,表示rowkey的长度,紧接着是rowkey,然后是固定长度的数值,表示family的长度,然后是family,接着是qualifier,然后是两个固定长度的数值,表示time stamp和key type(put/delete)。value部分没有这么复杂的结构,就是纯粹的二进制数据了。
上图中示意了hlog文件的结构,其实hlog文件就是一个普通的hadoop sequence file,sequence file 的key是hlogkey对象,hlogkey中记录了写入数据的归属信息,除了table和region名字外,同时还包括 sequence number和timestamp,timestamp是“写入时间”,sequence number的起始值为0,或者是最近一次存入文件系统中sequence number。
hlog sequece file的value是hbase的keyvalue对象,即对应hfile中的keyvalue,可参见上文描述。
本文对hbase技术在功能和设计上进行了大致的介绍,由于篇幅有限,本文没有过多深入地描述hbase的一些细节技术。目前一淘的存储系统就是基于hbase技术搭建的,后续将介绍“一淘分布式存储系统”,通过实际案例来更多的介绍hbase应用。