LSMTree -> SStable 初體驗

最近一直在聽同事們說到SST結構,因而學習一波html

1、文檔介紹java

本文寫於2019-03-03 14:26:31,初學者我的看法,若有錯誤歡迎指正git

基於LSM Tree的數據庫有不少,Hbase,RockDB,LevelDB,本人以其中一種爲例,簡單介紹github

2、 SST數據結構簡介算法

      SST全稱「Sorted String Stable」,根據這個名稱,咱們初步能夠知道這個數據結構內部的數據是排好序的(sorted),要想解釋這個術語真正的含義,最好的辦法是從他的出處找答案,咱們翻開Google BigTable的論文,在這篇論文中是這樣描述的:數據庫

      The Google SSTable file format is used internally(內部的) to store(存儲) Bigtable data. An SSTable provides a persistent(持久化的), ordered immutable(不可改變的) map from keys to values, where both keys and values are arbitrary(任意的) byte strings. Operations are provided to look up the value associated(相關的) with a specified key, and to iterate(尋找) over all key/value pairs in a specified key range. Internally, each SSTable contains a sequence of blocks (typically each block is 64KB in size, but this is configurable). A block index (stored at the end of the SSTable) is used to locate blocks; the index is loaded into memory when the SSTable is opened. 性能優化

    Google SST文件格式被用於BIgTable內部數據,SStable是一種不可變的、排序的、持久化的key_value Map,其中key和value都是任意字節的字符串。提供了找尋特定Key值對應的value的操做,以及找尋給定範圍內全部key_value的操做。每個SStale包括一系列的block(通常block大小是64Kb,這個值是能夠配置的),在SST的末尾還有一個「block index」,用於定位每個block(至關於索引),是key_offset(偏移量)的索引。數據結構

                

      前面的每個data就是一個block,後面還有一個data index,其他的部分先不作解釋,後文會詳解SST內部結構,每個block內部就是一系列的Key_value,前面的magic先忽略架構

      這個排序好的SSTable結構和普通的key_value pair的區別在於,能夠support:  1. range query 2. random w/r,可是就僅僅SStable自己沒法高效的support以上需求,還須要一整套的機制來輔助完成從memory sort、flush to disk、compaction到快速讀取的工做,這一個完整的機制和架構稱爲「The Log-Structed Merge-Tree」 LSM Tree。dom

3、LSM Tree存儲引擎

      LSM Tree的全稱是Log Structed Merge Tree,名字很形象,首先是基於Log的,不斷產生SSTree結構的Log文件,而且是不斷Merge以提升效率的,你看任何一篇介紹LSM Tree的文章都很難將它與樹聯繫起來,事實上,它是一種分層的組織數據的結構,具體到實現上就是一些按照邏輯分層的有序文件(下文介紹)

      LSM Tree的節點能夠分爲兩類,在內存中的稱之爲MemTable,保存在磁盤上的稱爲SSTable,這裏再提醒你們一點,請記得前面介紹SSTable的時候說的,SSTable是不可更改的。

      仔細來說,MemTable與SSTable仍是又不少區別的,這裏就提醒一下,不展開討論

    咱們但願LSM Tree能夠提供快速的讀與快速的隨機寫,下面介紹一下哪些機制保證了效率:

  • 磁盤內SSTable的index始終位於內存中,這一條爲快速讀提供了支持
  • 全部的寫都是直接寫在內存中的MemTable中的,這一條爲快速隨機寫提供了支持
  • 讀操做的順序是,首先在MemTable內尋找,找不到的話再在SSTable內檢索
  • MemTable會按期將自身內容寫到disk內的
  • disk內的SSTable會按期合併(原文是「collapsed together」)

      在內存中寫操做是常常發生的,寫操做是直接寫入MemTable,當MemTable達到必定的size,就flush到disk內成爲一個不可變(immutable)的SSTable。與此同時,咱們會保持(maintain)全部SSTable的index在內存中,這樣在對給定的key進行搜索的時候,咱們首先在MemTable內進行檢索,再在每一層的SSTale之間再進行搜索,到這裏就介紹了LSMTree存儲引擎是如何提升讀寫效率的了,那對於更新與刪除操做呢?

      對於更新操做,由於SSTable是不可變的,所以更新與刪除操做只發生在內存的MemTable內,若是要對SSTable內的數據進行更新只須要從新寫進去一個新的就能夠了,由於對於SSTable的訪問是順序的,因此新內容的存在會覆蓋舊內容,也就是順序訪問到須要的值的時候就會退出,如下的舊值不被訪問到。對於刪除操做,也是在MemTable內插入一個墓碑標誌加值,表明這個值被刪除了,而後訪問的時候會提早訪問到墓碑標誌而得知該值已經被刪除了

      下面來講一下LSM Tree的樹形結構,對於幾百上千個SSTable,咱們要按期進行操做,SSTale是分等級的,如圖所示 

               

      每層SSTable的文件到達必定條件以後進行合併操做,而後放置到更高層,合併操做在實現上都是策略驅動的、可插件化的。MemTable flush to disk的時候是直接到Level 0層的,每一層有不少SSTable,Level 0層的SSTable 是不一樣的MemTable flush進來的,每一個SSTable內部是排好序的,可是SSTable之間不必定是排好序的,可能兩個SSTable之間會出現重疊的部分,這由寫入操做的隨意性決定,在Level 1以及之後的層次中的SSTable,都是由上一層合併獲得的,因此內部是排好序的,外部也是排好序的,之間key range之間不會存在交集。SSTable之間的合併相似於簡單的歸併排序,根據key值肯定要合併(merge)的文件,而後進行合併。所以,合併一個文件到更高層可能須要寫多個文件,存在必定程度上的寫放大。不一樣的數據庫會採用不一樣的辦法來優化或者限制惡劣的狀況發生。

      接下來咱們引入一下Bloom Filter(布隆過濾器),咱們以前在讀操做中已經說了,首先判斷是否在MemTable中,而後根據index將覆蓋該key range的不一樣層的全部SSTale都查找一遍,簡單可是低效,優化的方式又兩種,第一種就是前面介紹的在每個SSTable尾部加入key_offset index索引,第二種就是在每個SSTable內加布隆過濾器。

 

4、Bloom Filter(布隆過濾器)

       咱們在設計一個算法的時候通常都會考慮時間效率與空間效率之間的平衡,Bloom Filter是一種佔用不多空間,而且提供常數級查詢的數據結構,可是他也有一些沒法忽略的缺點,就是會有必定的誤判率(false positive rate)。Bloom Filter常常用在大數據處理中,最經常使用來檢索元素是否是子啊集合內,在咱們上面的例子上就是判斷key range是否在SSTable內,下面介紹具體是如何實現的。

      咱們都瞭解過哈希函數,不存在一種哈希函數可以徹底區別出來全部值,也就是說不管採用怎樣的哈希函數,均可能使得兩個值哈希成同一個值,可是兩個值,採用k種哈希函數都能哈希到同一個值上的機率很是小,Bloom Filter就是利用了這一點性質。一個Bloom Filter的物理結構實際上是一個bit vector。 這個bit vector的每一位初始的時候都被設爲0。 同時, 每一個Bloom Filter 都伴隨着k個hash functions。 往Bloom Filter插入元素的過程就是用每一個hash function計算這個元素, 從而將結果所對應的比特位改成1。 若是當前比特位已經爲1, 則在插入的過程保持這一位不變。當判斷一個值是否存在的時候就是用k個hash function來哈希這個值,來和bit vector的結果位進行比較,只要有一位爲空,就能夠表明這個值不存在,反之,若是都不是空,也不能表明這個值就是存在的,詳情見下圖,由於可能別的數字將對應的結果位置成了1 

      在這個示例中, 咱們的Bloom Filter由一個30 bits的Bit Vector以及3個Hash Functions來構成。 咱們將三個元素S1S1, S2S2和S3S3分別插入這個Bloom Filter中。 而後對另外三個新元素S1S1, SxSx和SySy進行查詢。 由圖所示, S1S1和SxSx將被認爲屬於這個Bloom Filter, 由於因此相應的bit位均爲1, 而SySy則被視爲 不屬於這個Bloom Filter。 可是, 其中SxSx爲一個false positive的答案, 由於在插入的時候咱們並無插入這個元素。

5、參考連接:

https://sophiesongge.github.io/big/data/2016/09/06/bloom-filter.html  一個精緻的寶媽

中國知網《基於LASM-Tree鍵值系統讀性能優化》 做者:張月明

https://liudanking.com/arch/lsm-tree-summary/

https://www.cnblogs.com/fxjwind/archive/2012/08/14/2638371.html

http://www.blogjava.net/dlevin/archive/2015/09/25/427481.html

6、存疑

LSMTree在BigTable中是如何做用的 

相關文章
相關標籤/搜索