Hbase 数据模型

*  介绍
*  概览
*  行
*  列簇
*  时间戳
*  簇属性
*  实例
o  源ERD
o  HBase目标模型

介绍

HBase 的数据模型是继 Bigtable 数据模型的之后的克隆版,特别适用于密集的数据系统。由于关系型数据库的架构是基于单台机器的,无法获得高的伸缩性。例如,连接两个表的JOIN操作,在内存中完成,这就无法跨越网络。关系分布式数据库的公司,需要做很多重新设计的工作,这就是他们的许可证这个贵的原因。其他的可选方法是复制,而当从机写超载时,最后的选择是分表。在这个时候,数据的正则化是你在类中唯一记住要看的,这也是为什么数据模型要在纸上写得明明白白,还不是仅仅给你看的。

概览

看简单点,HBase可以概括成一个 Map<byte[], Map<byte[], Map<byte[], Map<Long, byte[]>>>。第一个Map是映射从 row keys 到 column families。第二个Map是映射从 column families 到他们的 column keys。第三个Map是映射从 column keys 到他们的 timestamps 。 最后,最后的Map映射 timestamps 到一个单一的值。keys 一般为 字符串 strings, timestamps 是一个长整型 longs。而值则为一个不解释的字节数组。 列的 keys 总在其 families 后面,表现如:family:key。因为一个 family 映射到另一个其他的map,这在理论上允许一个 family 包含无限个 column keys。因此,为了获取一个值,用户需要使用三个 keys 来 get :

row key+column key+timestamp -> value

行键+列键+时间戳 -> 值

HBase 以数组格式来处理 row key,但 row key 本身是有字符串的形式表现。row key Map 一个特性就是以一个词典顺序来保存。例如,从1到100的数字,就是按照 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 这样的方式来保存。

要想以自然顺序来保存整型数,row keys 必须在左边以0填充。利用这一点,row key Map 的功能可以通过提供一个 scaner 来增强, scaner 带有一个 start row key 和 一个 stop row key。例如,如果 row keys 是日期格式 YYYYMMDD,获取 2008年7月整个月的内容,就是打开一个 scaner (20080700到20080800)。它并不关心指定的 row keys 存在与否,唯一要关心的,就是这个调用不会返回 stop row key,因此,stop row key 必须给 scaner 指定好。

列簇

在 Hbase中,列成员重组具有同一性质的数据,并不限制数据类型。簇是表模式的一部分,为每行保存同种数据。与 froms rows to forws 不同的是 column keys 可以是稀少的。例如,row “20080702” 可以拥有自己的“info:”成员,该成员下有如下几个 column keys:
info:aaa
info:bbb
info:ccc

同样,row “20080703”仅有:
info:12342
在使用 column keys 的时候,开发者必须要非常小心。因为长度为0 的 key是允许的,这说明,在前面的例子中,数据可以被插入到 column key “info:” 中。我们强烈推荐,仅仅在没有其他的 keys 指定时使用空的 key。同样,由于一个成员中的数据是同一种类的,参考性能与时间戳 ,很多属性可以指定。

时间戳

根据成员的配置情况,HBase的值可以是以多版本的方式保存。缺省情况下,HBase将每个新值的时间戳设置为当前时间 milliseconds,并且当一个 cell 被请求时,返回最新的版本。开发者可以在插入数据时自定义时间戳,然后再通过指定这个时间戳来重新获取该值。

Family Attributes成员属性

可以为每一个簇指定下面的属性:

已实现的

*压缩
o record:准确到由rowkey+columnkey+timestamp 获得的每一个值都会在单独压缩。

o block:HDFS中的 block 被压缩。一个block可能包含多条record(block size > record size),或者一条记录的一部分(block size < record size)。
*时间戳
o 最大编号:一个值拥有不同版本的最大编号。
o 生存期: 比指定版本旧的内容将被当做垃圾被收集。

* 块缓存:在HDFS中,通过LRU排序算法获得缓存块。当等待全内存的存储时,改良随机读的性能,是一个很好的特性。

还没有实现的

* 内存保存:成员的所有值都保存在内存中。
* 长度:写入的值的长度不能超过指定的字节数。参考 [WWW] HBASE-742

实例

一个好的例子,演示Hbase的数据模型,就是 一个 blog。因为它具有简单和范围小的特点。

* blog条目,由标题,副标题,日期,作者,类型(或者标签),文本和评论组成,可以被登录后的用户进行创建和更新。
* 用户,由用户名,密码,和一个名称,可以登录或者登出。
* 评论,由标题,作者,文本组成,可以被游客匿名写入。

原ERD

HBase 目标模式

优先的解决方案 :

Table Row Key Family Attributs
blogtable TTYYYYMMDDHHmmss info: Always contains the column keys author,title,under_title. Should be IN-MEMORY and have a 1 version
text: No column key. 3 versions
comment_title: Column keys are written like YYYMMDDHHmmss. Should be IN-MEMORY and have a 1 version
comment_author: Same keys. 1 version
comment_text: Same keys. 1 version
usertable login_name info: Always contains the column keys password and name. 1 version

blogtable 的 row key 是连续的,由type(两个缩写字母)和时间戳组成。按照这样的方式,行首先是根据 type 来集成,然后时间日期。这表示能有更多的机会在同一个 region 内获得所需的数据。如你所见,在BLOGENTITY和COMMENT之间的1:*的关系,将 comments 的每一个属性放在 blogentery 中,作为的一个 family 。用日期作为column key,所有的 comments 已经被排序过。

这样设计的好处就是当你显示blog的“首页”,你仅仅需要获取从 blogtable 中 family “info:” 。当你展示一个实际的blog条目,你可以获取整行。另外一个好处就是用时间戳作为 row key,需要显示时,scanner可以获取连续的 rows ,例如, 最近你一个月的 条目。

This entry was posted in HBase. Bookmark the permalink.

Leave a Reply