LevelDb

LevelDb的MemTable提供了將KV數據寫入,刪除以及讀取KV記錄的操作接口,但是事實上Memtable並不存在真正的刪除操作,刪除某個Key的Value在Memtable內是作爲插入一條記錄實施的,但是會打上一個Key的刪除標記,真正的刪除操作是Lazy的,會在以後的Compaction過程中去掉這個KV。

需要注意的是,LevelDb的Memtable中KV對是根據Key大小有序存儲的,在系統插入新的KV時,LevelDb要把這個KV插到合適的位置上以保持這種Key有序性。其實,LevelDb的Memtable類只是一個接口類,真正的操作是通過背後的SkipList來做的,包括插入操作和讀取操作等,所以Memtable的核心數據結構是一個SkipList。

SkipList不僅是維護有序數據的一個簡單實現,而且相比較平衡樹來說,在插入數據的時候可以避免頻繁的樹節點調整操作,所以寫入效率是很高的,LevelDb整體而言是個高寫入系統,SkipList在其中應該也起到了很重要的作用。Redis爲了加快插入操作,也使用了SkipList來作爲內部實現數據結構。

對於SSTable而言, 插入, 更新, 刪除, 都是通過append來實現的, 只不過delete插入的“Key:刪除標記”, 後臺Compaction的時候纔去做真正的刪除操作。

SSTable的讀操作比較複雜一些, 不過下圖還是比較好的反映出讀取的過程,
MemTable –> Immutable MemTable –> Level0 SSTable –> Level1 SSTable –> Leveln
這個順序是有很道理的, 由於SSTable所有的寫都是append, 所以同一個key的value可能有很多版本, 而我們只關心最新的那個
所以我們只要安裝這個順序區讀, 就能保證讀到最新的那個版本

怎樣從.sst文件裏面讀到數據?
levelDb一般會先在內存中的Cache中查找是否包含這個文件的緩存記錄,如果包含,則從緩存中讀取;如果不包含,則打開SSTable文件,同時將這個文件的索引部分加載到內存中並放入Cache中。 這樣Cache裏面就有了這個SSTable的緩存項,但是隻有索引部分在內存中,之後levelDb根據索引可以定位到哪個內容Block會包含這條key,從文件中讀出這個Block的內容,在根據記錄一一比較,如果找到則返回結果,如果沒有找到,那麼說明這個level的SSTable文件並不包含這個key,所以到下一級別的SSTable中去查找

可以看出對於SSTable, 相對寫操作,讀操作處理起來要複雜很多,所以寫的速度必然要遠遠高於讀數據的速度,也就是說,LevelDb比較適合寫操作多於讀操作的應用場合。而如果應用是很多讀操作類型的,那麼順序讀取效率會比較高,因爲這樣大部分內容都會在緩存中找到,儘可能避免大量的隨機讀取操作。

順序讀, 加載一個SSTable到內存, 可以讀很多kv, 因爲kv在sst文件中就是按順序存放的, 如果隨機讀, 效率就比較低, 因爲cache的命中率很低, 需要頻繁的open不同的sst文件.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章