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
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