hbase keyvalue

HFile (HBase File)是HBase使用的一种文件存储格式的抽象,

目前存在两种版本的HFile: HFile V1和HFile V2

HBase 0.92之前的版本仅支持HFile V1,

HBase 0.92/0.94同时支持HFile V1和HFile V2。

以下分别是HFile V1/V2的结构图:

HFile V1

HFile V2

(注: 这两个图片在hbase 0.94的svn目录: srcsiteresourcesimages)

图中的数据块(Data block)正是实际存放应用数据的地方,

每个数据块又由一系列的KeyValue组成,并且这些KeyValue之间是按Key升序排列的,

本文将说明KeyValue到底是什么以及当KeyValue越来越多时出现大量类似的数据有哪些算法能减少重复?

首先来看一个例子:

假设需要将用户的基本信息以及正在参与的开源项目的有关信息存入HBase:

Java代码

  1. 用户基本信息参与的开源项目
  2. ————————————————-
  3. 用户Id职业性别tomcathbase
  4. ————————————————-
  5. zhh2009码农男提patch打酱油提patch打酱油
  6.  
  7. 用户Id职业性别tomcatant
  8. ————————————————-
  9. jdd1999码神男创始人创始人
  10. ———————————————————
  11. 表1.1

 

	用户基本信息                   参与的开源项目
---------------------       ----------------------------
用户Id    职业   性别          tomcat           hbase
---------------------       ----------------------------
zhh2009   码农   男            提patch打酱油    提patch打酱油

用户Id    职业   性别          tomcat           ant
---------------------       ----------------------------
jdd1999   码神   男            创始人           创始人
---------------------------------------------------------
                      表1.1

从这个例子来看,用户的基本信息比较好确定,但是参与的开源项目不确定且在开源项目中扮演的角色也不确定,

所以用关系数据库不太好建表,因为不知道具体有多少列,也无法把相关的列归成一个组。

1.1 列族

HBase是一种基于列的数据库,相关的列可以归到一个列族(Column Family),

每个列族中具体有哪些列不必事先知道,可以在需要的时候添加,比如在用户基本信息中为zhh2009加入email这样的列,

上例中”用户基本信息”和”参与的开源项目”可以作为两个列族,

不同的列族在HBase内部通常对应一个目录,这样不同的列值只会放到它所属的列族目录下。

1.2 rowKey

我们希望通过查询某个列就能把同一个列族或多个列族中的信息取出来,用户Id就是这样的列,

比如当我们要查询zhh2009的邮箱和参与的开源项目时,根据用户Id来查就不会查到jdd1999的信息,

在HBase中称这样的列为rowKey。

HBase是如何存放上例中的信息呢?

将用户Id这一列抽出来作为rowKey, 把上面的信息按如下格式扁平化:

Java代码

  1. <rowKey,列族名称,列名=>列值>
  2. —————————————————–
  3. <zhh2009,用户基本信息,职业=>码农>
  4. <zhh2009,用户基本信息,性别=>男>
  5. <zhh2009,参与的开源项目,tomcat=>提patch打酱油>
  6. <zhh2009,参与的开源项目,hbase=>提patch打酱油>
  7.  
  8. <jdd1999,用户基本信息,职业=>码神>
  9. <jdd1999,用户基本信息,性别=>男>
  10. <jdd1999,参与的开源项目,tomcat=>创始人>
  11. <jdd1999,参与的开源项目,ant=>创始人>
  12. —————————————————–
  13. 表1.2

 

<rowKey,  列族名称,       列名   => 列值>
-----------------------------------------------------
<zhh2009, 用户基本信息,   职业   => 码农>
<zhh2009, 用户基本信息,   性别   => 男>
<zhh2009, 参与的开源项目, tomcat => 提patch打酱油>
<zhh2009, 参与的开源项目, hbase  => 提patch打酱油>

<jdd1999, 用户基本信息,   职业   => 码神>
<jdd1999, 用户基本信息,   性别   => 男>
<jdd1999, 参与的开源项目, tomcat => 创始人>
<jdd1999, 参与的开源项目, ant    => 创始人>
-----------------------------------------------------
                表1.2

表1.2中的每一行在HBase中对应一个KeyValue,

“=>”左边的是KeyValue中的”Key”,”=>”右边对应KeyValue中的”Value”。

当然这只是KeyValue的一个简化格式,内部格式并非那么简单,我们接下来看看真实的KeyValue是怎样的?

2. KeyValue内部格式

KeyValue内部格式可以分成三部份: 头、Key、Value,如表2.1所示

Java代码

  1. 名称   字节数说明
  2. ——————————————————————–
  3. keyLength  4表示Key所占的总字节数
  4. valueLength4表示Value所占的总字节数
  5.  
  6. rowKeyLength2表示rowKey所占的字节数
  7. rowKeyrowKeyLengthrowKey
  8. columnFamilyLength1表示列族名称所占的字节数
  9. columnFamilycolumnFamilyLength列族名称
  10. columnNamecolumnNameLength列名
  11. timestamp8时间戳
  12. type1Key类型,比如是新增(Put),还是删除(Delete)
  13.  
  14. valuevalueLength列值
  15. ——————————————————————–
  16. 表2.1

 

名称             字节数                  说明
--------------------------------------------------------------------
keyLength           4                     表示Key所占的总字节数
valueLength           4                     表示Value所占的总字节数

rowKeyLength          2                     表示rowKey所占的字节数
rowKey                rowKeyLength          rowKey
columnFamilyLength    1                     表示列族名称所占的字节数
columnFamily          columnFamilyLength    列族名称
columnName            columnNameLength      列名
timestamp             8                     时间戳
type                  1                     Key类型,比如是新增(Put),还是删除(Delete)

value                 valueLength           列值
--------------------------------------------------------------------
                      表2.1

keyLength和valueLength组成头部,

rowKeyLength到type这7项组成Key,最后一项value代表第三部份: Value,

上面有个地方值得注意,在columnFamily前面有columnFamilyLength,

但是在columnName之前并没有columnNameLength这一项,为了节省空间,这不是必需的,

当在解析KeyValue时,通过keyLength-8(timestamp)-1(type)就可以确定columnName在此KeyValue中的结束位置。

把表1.2中的前两行按表2.1中的格式生成两个KeyValue:

KeyValue A 代表: <zhh2009, 用户基本信息, 职业 => 码农>

KeyValue B 代表: <zhh2009, 用户基本信息, 性别 => 男>

Java代码

  1. 名称   字节数KeyValueAKeyValueB
  2. —————————————————————————-
  3. keyLength  43535
  4. valueLength442
  5.  
  6. rowKeyLength277
  7. rowKeyrowKeyLengthzhh2009zhh2009
  8. columnFamilyLength11212
  9. columnFamilycolumnFamilyLength用户基本信息用户基本信息
  10. columnNamecolumnNameLength职业性别
  11. timestamp813296637873641329663787364
  12. type14(Put)4(Put)
  13.  
  14. valuevalueLength码农男
  15. —————————————————————————-
  16. 表2.2

 

名称             字节数                  KeyValue A        KeyValue B

----------------------------------------------------------------------------

keyLength           4                     35                35

valueLength           4                     4                 2

rowKeyLength 2 7 7 rowKey rowKeyLength zhh2009 zhh2009 columnFamilyLength 1 12 12 columnFamily columnFamilyLength 用户%E


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值