LevelDB & RocksDB是兩種內嵌數據庫,從分布式開源庫中來,又常用在分布式開源庫和分布式系統中。今天主要是轉載加整理,好好梳理一下。
一、LevelDB簡介
設計思路
LevelDB的數據是存儲在磁盤上的,采用LSM-Tree的結構實現。LSM-Tree將磁盤的隨機寫轉化為順序寫,從而大大提高了寫速度。為了做到這一點LSM-Tree的思路是將索引樹結構拆成一大一小兩顆樹,較小的一個常駐內存,較大的一個持久化到磁盤,他們共同維護一個有序的key空間。寫入操作會首先操作內存中的樹,隨着內存中樹的不斷變大,會觸發與磁盤中樹的歸並操作,而歸並操作本身僅有批量順序寫。如下圖所示:
隨着數據的不斷寫入,磁盤中的樹會不斷膨脹,為了避免每次參與歸並操作的數據量過大,以及優化讀操作的考慮,LevelDB將磁盤中的數據又拆分成多層,每一層的數據達到一定容量后會觸發向下一層的歸並操作,每一層的數據量比其上一層成倍增長。這也就是LevelDB的名稱來源。
整體結構
具體到代碼實現上,LevelDB有幾個重要的角色,包括內存數據的Memtable,分層數據存儲的SST文件,版本控制的Manifest、Current文件,以及寫Memtable前的WAL。這里簡單介紹各個組件的作用和在整個結構中的位置。
-
Memtable:內存數據結構,跳表實現,新的數據會首先寫入這里;
-
Log文件:Commit Log,也稱為提交日志。寫Memtable前會先寫Log文件,Log通過append的方式順序寫入。Log的存在使得機器宕機導致的內存數據丟失得以恢復;
-
Immutable Memtable:達到Memtable設置的容量上限后,Memtable會變為Immutable為之后向SST文件的歸並做准備,顧名思義,Immutable Mumtable不再接受用戶寫入,同時會有新的Memtable生成;
-
SST文件:磁盤數據存儲文件。分為Level 0到Level N多層,每一層包含多個SST文件;單層SST文件總量隨層次增加成倍增長;文件內數據有序;其中Level0的SST文件由Immutable直接Dump產生,其他Level的SST文件由其上一層的文件和本層文件歸並產生;SST文件在歸並過程中順序寫生成,生成后僅可能在之后的歸並中被刪除,而不會有任何的修改操作。
-
Manifest文件: 清單文件。SSTable中的文件時按照記錄的主鍵排序的,每個文件有最小的主鍵和最大的主鍵。清單文件記錄這些元數據,包括屬於哪個層級、文件名稱、最小主鍵和最大主鍵。
-
Current文件: 當前文件記錄了當前的清單文件名,即當前的Manifest,而Manifest可能有多個。
總之,當寫入一個key-value的時候,首先寫入log文件中,然后才會寫入memtable中,然后當memtable到達一定程度時,然后轉變成Immutable memtable,系統此時會重新創建新的memtable用於插入數據。然后Immutable memtable通過壓縮數據存儲到磁盤SSTable中。
合並Compaction
LevelDB寫入操作簡單,但是讀取操作比較復雜,需要在內存以及各個層級文件中按照從新到老依次查找,代價很高。為了加快讀取速度, LevelDB內部執行Compaction操作來對已有的記錄進行整理壓縮,從而刪除一些不再有效的記錄,減少數據規模和文件數量。
Compaction分為兩種。
Minor Compaction是指當內存中的MemTable大小到一定值時,將內存數據轉儲dump到SSTable中。
Major Compaction是指每個層級下有多個SSTable,當某個層級下的SSTable文件數目超過一定設置后, LevelDB會從這個層級中選擇SSTable文件,將和高一級的SSTable文件進行合並。相當於執行多路歸並:按照主鍵順序依次迭代出所有SSTable文件中的記錄,如果沒有保存價值則直接丟掉,否則將其寫入到新生成的SSTable文件中。
LevelDB 特點
1) LevelDB是一個持久化存儲的KV系統,和Redis這種內存型的KV系統不同,LevelDB不會像Redis一樣狂吃內存,而是將大部分數據存儲到磁盤上。
2) LevleDB在存儲數據時,是根據記錄的key值有序存儲的,就是說相鄰的key值在存儲文件中是依次順序存儲的,而應用可以自定義key大小比較函數。
3) LevelDB支持數據快照(snapshot)功能,使得讀取操作不受寫操作影響,可以在讀操作過程中始終看到一致的數據。
4) LevelDB還支持數據壓縮等操作,這對於減小存儲空間以及增快IO效率都有直接的幫助。
二、RocksDB簡介
Levledb是Google的兩位Fellow (Jeaf Dean和Sanjay Ghemawat)設計和開發的嵌入式K-V系統,讀寫性能非常彪悍,官方網站報道其寫性能40萬/s,讀性能達到6萬/s,寫操作要遠快於讀操作。Rocksdb是Facebook公司在Leveldb基礎之上開發的一個嵌入式K-V系統,在很多方面對Leveldb做了優化和增強,更像是一個完整的產品,比如:
1)Leveldb是單線程合並文件,Rocksdb可以支持多線程合並文件,充分利用多核的特性,加快文件合並的速度,避免文件合並期間引起系統停頓;
LSM型的數據結構,最大的性能問題就出現在其合並的時間損耗上,在多CPU的環境下,多線程合並那是LevelDB所無法比擬的。不過據其官網上的介紹,似乎多線程合並還只是針對那些與下一層沒有Key重疊的文件,只是簡單的rename而已,至於在真正數據上的合並方面是否也有用到多線程,就只能看代碼了。
RocksDB增加了合並時過濾器,對一些不再符合條件的K-V進行丟棄,如根據K-V的有效期進行過濾。
2)Leveldb只有一個Memtable,若Memtable滿了還沒有來得及持久化,則會減緩Put操作引起系統停頓;RocksDB支持管道式的Memtable,也就說允許根據需要開辟多個Memtable,以解決Put與Compact速度差異的性能瓶頸問題。
3)Leveldb只能獲取單個K-V;Rocksdb支持一次獲取多個K-V,還支持Key范圍查找。
4)Levledb不支持備份;Rocksdb支持全量和增量備份。RocksDB允許將已刪除的數據備份到指定的目錄,供后續恢復。
5)壓縮方面RocksDB可采用多種壓縮算法,除了LevelDB用的snappy,還有zlib、bzip2。LevelDB里面按數據的壓縮率(壓縮后低於75%)判斷是否對數據進行壓縮存儲,而RocksDB典型的做法是Level 0-2不壓縮,最后一層使用zlib,而其它各層采用snappy。
6)RocksDB除了簡單的Put、Delete操作,還提供了一個Merge操作,說是為了對多個Put操作進行合並,優化了modify的效率。站在引擎實現者的角度來看,相比其帶來的價值,其實現的成本要昂貴很多。個人覺得有時過於追求完美不見得是好事,據筆者所測(包括測試自己編寫的引擎),性能的瓶頸其實主要在合並上,多一次少一次Put對性能的影響並無大礙。
7)RocksDB提供一些方便的工具,這些工具包含解析sst文件中的K-V記錄、解析MANIFEST文件的內容等。有了這些工具,就不用再像使用LevelDB那樣,只能在程序中才能知道sst文件K-V的具體信息了。
8)其他優化:增加了column family,這樣有利於多個不相關的數據集存儲在同一個db中,因為不同column family的數據是存儲在不同的sst和memtable中,所以一定程度上起到了隔離的作用。將flush和compaction分開不同的線程池,能有效的加快flush,防止stall拖延停頓。增加了對write ahead log(WAL)的特殊管理機制,這樣就能方便管理WAL文件,因為WAL是binlog文件。
RocksDB的典型場景(低延時訪問)
1)需要存儲用戶的查閱歷史記錄和網站用戶的應用
2)需要快速訪問數據的垃圾檢測應用
3)需要實時scan數據集的圖搜索query
4)需要實時請求Hadoop的應用
5)支持大量寫和刪除操作的消息隊列
雖然說Rocksdb底層支持HDFS,數據可以多副本存儲,但是前端沒有分片,仍然無法滿足分布式系統的可擴展要求。
實際中,可以將Levledb或者Rocksdb作為數據存儲系統引擎,在其上面實現分片和多副本,從而實現一個真正的分布式存儲系統,例如微信開源的PaxosStore,默認就是以Rocksdb作為其某個副本的存儲介質,上層通過Paxos協議來保證副本之間的數據一致性。
相比LevelDB是不是覺得RocksDB彪悍的不可思議。但是雖然RocksDB在性能上提升了不少,在文件存儲格式上跟LevelDB還是沒什么變化的, 稍微有點更新的只是RocksDB對原來LevelDB中sst文件預留下來的MetaBlock進行了具體利用。
個人(參考資料4)覺得RocksDB尚未解決的地方:
- 依然是完全依賴於MANIFEST,一當該文件丟失,則整個數據庫基本廢掉。
- 合並上依然是整個文件載入,一些沒用的Value將被多次的讀入內存,如果這些Value很大的話,那沒必要的內存占用將是一個可觀的成本。
參考資料:
1.《大規模分布式存儲系統原理解析與架構實戰》
2.http://catkang.github.io/2017/01/07/leveldb-summary.html 有四篇關於LevelDB的文檔。
3.https://www.zhihu.com/question/351366744/answer/862704911
4.https://blog.csdn.net/tzdjzs/article/details/20838945
5.https://blog.csdn.net/weixin_43618070/article/details/102317769
6.LSM簡介