[轉帖]一文搞懂LSM-Tree

济南小老虎發表於2024-05-27

https://www.cnblogs.com/zxporz/p/16021373.html

LSM-Tree簡介

LSM Tree(Log Structure Merge Tree)是一種資料結構

從字面意思理解,是一種基於日誌追加寫、有一定結構、並且會merge合併的樹(資料結構)

特點是:

①利用磁碟批次的順序寫要遠比隨機寫效能高出很多來支援隨機讀寫操作
②更適用於寫多讀少型別的場景
③廣泛應用在各大 NoSQL 中。比如基於 LSM 樹實現底層索引結構的 RocksDB,就是 Facebook 用 Golang 對 LevelDB 的實現,Hbase也是用LSM-Tree的資料結構實現的

LSM-Tree一種比較完善的原理圖

寫操作

write1:WAL

把操作同步到磁碟中WAL做備份(追加寫、效能極高)

write2:Memtable

完成WAL後將(k,v)資料寫入記憶體中的Memtable,Memtable的資料結構一般是跳錶或者紅黑樹
記憶體內採用這種資料結構一方面支援記憶體內高速增刪改查(時間複雜度O(logM)),另一方面可以保持有序,為寫入磁碟中的SSTable打基礎

write3:Immutable Memtable

Memtable儲存的元素達到一定數量後,就會把它複製一份出來成為Immutable Memtable (不可變的Memtable)並且不能對其修改了,新增的資料都寫入新的Memtable,這麼做的好處是當需要將Memtable轉化為Immutable Memtable時無需暫停工作,至於為什麼要複製一個Immutable Memtable ,這主要是為了後續落盤時做準備

write4:Minor Compaction

記憶體中的資料不可能無線的擴張下去,需要把記憶體裡面Immutable Memtable 定期dump到到硬碟上的SSTable level 0層中,此步驟也稱為Minor Compaction
SSTable的資料結構是LSM-Tree設計的精髓,他一方面可以保持有序,一方面又能利用磁碟追加寫的高效能

SSTable的資料結構為兩部分,前半部分是key與value成對的資料連續儲存,這部分資料的key是有序的,後半部分是前半部分的索引,值儲存的是key所對應的offset,也是有序的,每次開啟這個SSTable需要把索引載入到記憶體並利用二分搜尋可以很快查詢出要訪問的key的值

dump的過程中每個Immutable Memtable會對應一個SSTable的segment且不會對多個Immutable Memtable進行合併,而是直接將Immutable Memtable中有序的跳錶或者紅黑樹遍歷並追加寫入到segment,這個過程速度很快。由於不會合並level 0層中的SSTable可能會出現相同的key。

write5、write6:Major Compaction merge

當level 0中的segment越來越多,查詢需要遍歷的segment也就會越來越多,並且隨著時間的推移,重複的key也會越來越多,在後面的步驟就需要對level 0層的segment進行合併merge
合併的過程中是吧多個有序的segment進行歸併合併,所以效能不會很差,多個老的segment會合併成一個更長的同樣有序的segment並設定到下一層
每一層的segment的數量和大小都會有限制,每當超出限制後,就會做合併操作
雖然定期合併可以有效的清除無效資料,縮短讀取路徑提升查詢效率,提高磁碟利用空間。但Compaction操作是非常消耗CPU和磁碟IO的,尤其是在業務高峰期,如果發生了Major Compaction,則會降低整個系統的吞吐量,這也是一些NoSQL資料庫,比如Hbase裡面常常會禁用Major Compaction,並在凌晨業務低峰期進行合併的原因。

修改流程

write1:WAL
write2:找到key直接修改或新增key
write3:Immutable Memtable
write4:Minor Compaction
write5、write6…:較新的key(有序可以識別)會替代較老的key

刪除流程

write1:WAL
write2:找到key設定狀態為tombstone或新增key設定狀態為tombstone
write3:Immutable Memtable
write4:Minor Compaction
write5、write6…:因為不確定下層是否有被刪除的key,到最後一層merge時才真正刪除

讀操作

一、按照Memtable(記憶體)、Immutable Memtable(記憶體)、level 0 segments(磁碟)、level 1 segments(磁碟)、level 1 segments(磁碟)的順序查詢
二、每層先查新生成的segment
三、每個segment從後向前查

為什麼LSM不直接順序寫入磁碟,而是需要在記憶體中緩衝一下?

單條寫的效能沒有批次寫快,很多中介軟體比如elasticsearch、kafka、mysql都有類似的記憶體緩衝設計
在磁碟緩衝的另一個好處是,針對新增的資料,可以直接查詢返回,能夠避免一定的IO操作

LSM-Tree和B+Tree的比較

LSM-Tree的優點是支援高吞吐的寫O1,這個特點在分散式系統上更為看重
針對讀取普通的LSM-Tree結構,讀取是On的複雜度
在使用索引或者快取最佳化後的也可以達到O(logN)的複雜度。
適用於寫多讀少
B+tree的優點是支援高效的讀(穩定的O(logN))
但是在大規模的寫請求下(O(LogN)),效率會變得比較低,因為隨著insert的操作,為了維護B+樹結構,節點會不斷的分裂和合並。操作磁碟的隨機讀寫機率會變大,故導致效能降低。
適用於寫少讀多或寫讀平衡

相關文章