基于KV Data Model实现Table Data Model

HBase对外暴露出来的是一个表格数据模型,以下图所示html

rowkey应用程序能够本身设计。每个Cell能够保存多个版本的数据,由timestamp标示版本。应用程序能够本身指定timestamp,若是不指定HBase会设置为当前时间。java

RegionServer是HBase对外提供数据存取的server,核心的数据结构是java.util.concurrent ConcurrentSkipListMap, 其实是一个用SkipList实现有序Map,对外是一个KV的接口。那上图中的表格数据模型是如何映射到KV接口上的?git

实际上,从表格模型能够看出,<rowkey,column family, column qualifier, timestamp>这个4元组惟一的决定一个value,从这里能够看出,KV接口的Key基本就是由上述这几项组成。具体的在HBase中,
rowkey, column family, column qualifier, timestamp,value 都存储在结构KeyValue中,结构以下图所示:github

这个结构直接存储在ConcurrentSkipListMap中,做为Key,ConcurrentSkipListMap的Value不重要,在实现中也是KeyValue。apache

ConcurrentSkipListMap在构造时,会传入一个java.util.Comparator ,实现中对普通的数据表格来讲,传入的是KVComparator,它比较两个KeyValue,比较准则是先比较按照字典序比较rowkey,若是相等则比较column family,接着是column qualifier, timestamp, type, mvcc。其中type有以下几种: 数据结构

public static enum Type {
    Minimum((byte)0),
    Put((byte)4),
    Delete((byte)8),
    DeleteFamilyVersion((byte)10),
    DeleteColumn((byte)12),
    DeleteFamily((byte)14),

    // Maximum is used when searching; you look from maximum on down.
    Maximum((byte)255);
}

因此实际上,删除某行,或者某个column family,或者某个qualifier的过程实际上都是往ConcurrentSkipListMap插入了一行,而且,一次put多个qualifier最后体如今ConcurrentSkipListMap中也是多行。那么,显然,在读一行数据的时候,须要scan这个ConcurrentSkipListMap,将rowkey相同的行都给扫描出来,将相关的qualifier组装起来,而且须要处理各类Delete相关的type,TTL以及KeyValue是否可读的问题(mvcc字段,关于MVCC,参见这篇博客),还有用户设置的一些filter等等。因为用户通常读数据都是读最新的版本,为了scan更少的数据,KeyValue的排序中有一个规则是,timestamp越大的KeyValue排在更前面。mvc

LevelDB/RocksDB实际上提供的就是KV的接口,Key和Value都是byte[]。它其实是一个LSM的系统。广泛认为它是BigTable的tablet server中的一个模块,将和NameNode打交道,上层的表格封装给去掉了。设计

实际上,国内Baidu的网页搜索部已经开源了一个叫作Tera的表格系统,其中tablet server就是基于LevelDB作的。它的格式"KeyValue"格式是这样:code

[rowkey\0|column\0|qualifier\0|type|timestamp]
[rlen+1B | clen+1B | qlen+1B | 1B | 7B ]server

参考资料

HBase 0.98

Tera

相关文章
相关标签/搜索