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