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

相關文章
相關標籤/搜索