LSM(Log Structured Merge Trees ) 筆記

1、大幅度制約存儲介質吞吐量的緣由

首先拋出結論。不管任何存儲介質(不論是機械硬盤仍是SSD,抑或是內存)的順序訪問速度都遠遠高出隨機訪問的速度。
filehtml

2、傳統數據庫的實現機制

傳統數據庫,好比Mysql使用的b+樹索引,對讀友好。但容易形成隨機寫。好比新插入一個值到數據庫,首先咱們要讀取b+樹,判斷新插入的值放在樹的什麼位置,其次在特定的位置寫入新值,並作一系列調整,分裂,使之知足b+樹的特性。這不可避免的形成了磁盤的隨機訪問,大數據量的插入速度很慢。固然這也符合歷史發展趨勢,早起的IT行業,數據量和數據增加速度有限,只要擁有良好的查詢性能,便可知足需求。算法

但隨着硬件性能的提高,業務形態的變化,現今的互聯網系統,每每面臨着數據的大量、高速產生。如何加快存儲速度,成了關鍵。因而LSM Tree應運而生。sql

3、LSM Tree的歷史由來

LSM Tree的最先概念,誕生於1996年google的「BigTable」論文。後世多種數據庫產品對LSM Tree的具體實現,都有一些小的差別。採用LSM Tree做爲存儲結構的數據庫有,Google的LevelDB, Facebook的RockDB(RockDB來源於LevelDB), Cassandra,HBase等。數據庫

4、提升寫吞吐量的思路

既然順序寫比起隨機寫速度更快。那得想辦法將數據順序寫。緩存

4.1 一種方式是數據來後,直接順序落盤

這擁有很高的寫速度。可是當咱們想要查尋一個數據的時候,因爲存儲下的數據自己是無序的(寫的值自己沒法控制順序),沒法使用任何算法進行優化,只能挨個查詢,讀取速度是很慢的。數據結構

4.2 另外一種方式,是保證落盤的數據是順序寫入的同時,還保證這些數據是有序的

而請求寫入的數據自己是無序且不可預測的,如何保證落盤的數據是有序的呢?這就須要利用內存訪問速度比硬盤快的原理。將寫入的請求,先在內存中緩存起來,按必定的有序結構組織,達到必定量後,再寫入硬盤,從而使得硬盤順序寫入了有序的數據。提升數據的寫入速度同時,方便了後續基於有序數據的查找(有序的數據結構,能夠經過二分查找等算法進行進行快速查詢,具體查找算法,得看是哪一種有序結構)性能

5、 LSM Tree結構圖

LSM tree即利用了上述第二種方式。具體結構圖以下:
file大數據

5.1 寫入時,爲何要先寫一份log

爲了防止寫入的數據,在斷電時丟失。因此先順序寫一份log到硬盤,方便數據恢復。優化

5.2 什麼是MemTable

寫入數據的內存緩存,MemTable中存儲的是有序的數據。什麼纔是有序的數據結構?不一樣的實現可能不相同。LevelDB使用的是SkipList。Hbase使用的是B Tree。google

5.3 什麼是ImmutableMemTable

MemTable中的數據隨時在增長,當其增長到必定量後,將其變爲不可變數據,ImmutableMemTable。新生成一份MemTable用於後續的數據寫入。ImmutableMemTable中的數據,將被寫入到硬盤中的SSTable.

5.4 什麼是SSTable

SSTable 全稱Sorted String Table。實際上就是被寫入數據的有序存儲文件,因此叫sorted.
file

SSTable文件有DataBlock,IndexBlock,BitSet(不一樣的實現,有可能沒有)

  • DataBlock 一個SSTable包含多個數據塊,數據按KeyValue的形式有序組織。
  • IndexBlock 記錄每一個數據塊中最大的那個Key的Offset
  • BitSet 使用Bloom Filter來將一個Key映射到BitSet中

數據的有序組織、IndexBlock、BitSet。這些數據結構,都是爲了提升數據讀取時的速度。那數據是如何進行讀取的呢?

5.5 如何進行數據讀取

讀取的大概流程以下
file
因爲SSTable是順序建立,因此最新的SSTable中包含了最新的值。再查找SSTable時,依次查找最新的SSTable。

每個SSTable的查詢流程以下
file
布隆表達式的原理是以極小的數據容量,去存儲大量數據存在的可能性。因此若是經過BitSet的布隆表達式查詢該Key存在時,只是一個理論存在可能,接下來要經過IndexBlock真正進行查詢。而若是布隆表達式在BitSet中沒有找到,那就是真的沒有,能夠快速跳過,進入下一個SSTable查找。布隆表達式的運用,可以大大提升查找效率。

5.6 如何進行數據的刪除和更新

爲了保證數據的順序寫,全部SSTable都不會由於刪除和更新而在原數據所在位置進行更改。在更新時,僅僅插入一個最新的值去寫到新的SSTable中。在刪除時,依然是插入一個基於該Key的刪除標記,寫入最新的SSTable中。因爲查找某個Key是基於時間新鮮度,反向依次查找SSTable,因此讀取某個Key始終讀的是最新的值。

5.7 SSTable的合併

隨着日積月累,SSTable的文件數會增多,致使查找時性能降低。同時因爲數據的更新或刪除。讓老的SSTable中數據的有效性下降,太多的過時數據佔用SSTable,一樣會下降查詢效率。因此通常數據庫引擎,按期都會有一個SSTable的合併操做。移除過期數據,將多個小SSTable合併成大的SSTable。

5.8 最近讀取的SSTable IndexBlock緩存

在大內存的條件下,部分數據庫還會將最近讀取的SSTable 索引,緩存至內存。這進一步加速了查找的過程。

6、參考文獻

http://www.benstopford.com/2015/02/14/log-structured-merge-trees/
http://www.cnblogs.com/haippy/archive/2011/12/04/2276064.html
https://blog.csdn.net/u014774781/article/details/52105708
https://en.wikipedia.org/wiki/Log-structured_merge-tree
https://www.igvita.com/2012/02/06/sstable-and-log-structured-storage-leveldb/

歡迎關注個人我的公衆號"西北偏北UP",記錄代碼人生,行業思考,科技評論

相關文章
相關標籤/搜索