levelDB-源碼解讀日誌一

參考博客:https://www.cnblogs.com/haippy/archive/2011/12/04/2276064.html

講的思路非常清晰,我這裏截取了很大部分,加上了自己的一些理解。

對於levelDB,我們首先要對整個系統的總體結構有一個基礎的認識。然後再逐個對系統中的各個部分進行剖析。

系統特點:

1.leveldb是一個支持持久化存儲kv數據庫,大部分數據都存儲在硬盤上。

2.leveldb存儲數據時,會按key值或者一定順序(用戶可以自定義key值比較方式)有序存儲,所以leveldb推薦用戶將經常一起被範文的數據用相鄰的key值存儲,不經常訪問的數據取一些key值相對較分割的。(因爲不經常訪問的數據取key較邊緣的話,會給其他相對訪問頻繁的數據留下了key值空間裏較大,較連續的區域,所以在檢索性能上會有提升)。這也是leveldb順序讀寫操作大大快於隨機讀寫操作的原因。

3.像大多數KV系統一樣,LevelDb的操作接口很簡單,基本操作包括寫記錄,讀記錄以及刪除記錄。也支持針對多條操作的原子批量操作。

4.LevelDb支持數據快照(snapshot)功能,使得讀取操作不受寫操作影響,可以在讀操作過程中始終看到一致的數據。數據快照是什麼呢?快照時拷貝包括相應數據在某個時間點(拷貝開始的時間點)的映像。快照可以是其所表示的數據的一個副本,也可以是數據的一個複製品。

5.Leveldb還有對數據的壓縮,以及對經常被訪問的數據用cache進行儲存。

6.LevelDb上對文件的所有操作都在Env上進行實現,相當於在操作系統上操作的進一步封裝,所以每個操作系統可以針對各自特點,編寫各自env的實現方式。某種程度上,體現了leveldb的平臺無關性。

整個leveldb在系統中的主要靜態結構如圖。

 

 從圖中可以看出,構成LevelDb靜態結構的包括六個主要部分:內存中的MemTable和Immutable MemTable以及磁盤上的幾種主要文件:Current文件,Manifest文件,log文件以及SSTable文件。當然,LevelDb除了這六個主要部分還有一些輔助的文件,但是以上六個文件和數據結構是LevelDb的主體構成元素。

LevelDb的Log文件和Memtable與Bigtable論文中介紹的是一致的,當應用寫入一條Key:Value記錄的時候,LevelDb會先往log文件裏寫入,成功後將記錄插進Memtable中,這樣基本就算完成了寫入操作,因爲一次寫入操作只涉及一次磁盤順序寫和一次內存寫入,所以這是爲何說LevelDb寫入速度極快的主要原因。

Log文件在系統中的作用主要是用於系統崩潰恢復而不丟失數據,假如沒有Log文件,因爲寫入的記錄剛開始是保存在內存中的,此時如果系統崩潰,內存中的數據還沒有來得及Dump到磁盤,所以會丟失數據(Redis就存在這個問題)。爲了避免這種情況,LevelDb在寫入內存前先將操作記錄到Log文件中,然後再記入內存中,這樣即使系統崩潰,也可以從Log文件中恢復內存中的Memtable,不會造成數據的丟失。

當Memtable插入的數據佔用內存到了一個界限後,需要將內存的記錄導出到外存文件中,LevleDb會生成新的Log文件和Memtable,原先的Memtable就成爲Immutable Memtable,顧名思義,就是說這個Memtable的內容是不可更改的,只能讀不能寫入或者刪除。新到來的數據被記入新的Log文件和Memtable,LevelDb後臺調度會將Immutable Memtable的數據導出到磁盤,形成一個新的SSTable文件。SSTable就是由內存中的數據不斷導出並進行Compaction操作後形成的,而且SSTable的所有文件是一種層級結構,第一層爲Level 0,第二層爲Level 1,依次類推,層級逐漸增高,這也是爲何稱之爲LevelDb的原因。

SSTable中的文件是Key有序的,就是說在文件中小key記錄排在大Key記錄之前,各個Level的SSTable都是如此,但是這裏需要注意的一點是:Level 0的SSTable文件(後綴爲.sst)和其它Level的文件相比有特殊性:這個層級內的.sst文件,兩個文件可能存在key重疊,比如有兩個level 0的sst文件,文件A和文件B,文件A的key範圍是:{bar, car},文件B的Key範圍是{blue,samecity},那麼很可能兩個文件都存在key=”blood”的記錄。對於其它Level的SSTable文件來說,則不會出現同一層級內.sst文件的key重疊現象,就是說Level L中任意兩個.sst文件,那麼可以保證它們的key值是不會重疊的。這點需要特別注意,後面您會看到很多操作的差異都是由於這個原因造成的。

    SSTable中的某個文件屬於特定層級,而且其存儲的記錄是key有序的,那麼必然有文件中的最小key和最大key,這是非常重要的信息,LevelDb應該記下這些信息。Manifest就是幹這個的,它記載了SSTable各個文件的管理信息,比如屬於哪個Level,文件名稱叫啥,最小key和最大key各自是多少。下圖是Manifest所存儲內容的示意:

圖中只顯示了兩個文件(manifest會記載所有SSTable文件的這些信息),即Level 0的test.sst1和test.sst2文件,同時記載了這些文件各自對應的key範圍,比如test.sstt1的key範圍是“an”到 “banana”,而文件test.sst2的key範圍是“baby”到“samecity”,可以看出兩者的key範圍是有重疊的。

Current文件是幹什麼的呢?這個文件的內容只有一個信息,就是記載當前的manifest文件名。因爲在LevleDb的運行過程中,隨着Compaction的進行,SSTable文件會發生變化,會有新的文件產生,老的文件被廢棄,Manifest也會跟着反映這種變化,此時往往會新生成Manifest文件來記載這種變化,而Current則用來指出哪個Manifest文件纔是我們關心的那個Manifest文件。

以上介紹的內容就構成了LevelDb的整體靜態結構,在LevelDb日知錄接下來的內容中,我們會首先介紹重要文件或者內存數據的具體數據佈局與結構。

所以綜上就是leveldb的總體介紹和靜態結構。下一章具體對leveldb的類和組件進行解讀。

 

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