HBase LSM樹存儲引擎詳解


1.前提

講LSM樹之前,需要提下三種基本的存儲引擎,這樣才能清楚LSM樹的由來:

  • 哈希存儲引擎
  • B樹存儲引擎
  • LSM樹(Log-Structured Merge Tree)存儲引擎

2. 哈希存儲引擎

哈希存儲引擎哈希表的持久化實現,支持增、刪、改以及隨機讀取操作,但不支持順序掃描,對應的存儲系統為key-value存儲系統。對於key-value的插入以及查詢,哈希表的復雜度都是O(1),明顯比樹的操作O(n)快,如果不需要有序的遍歷數據,哈希表就非常適合。代表性的數據庫有:Redis,Memcache,以及存儲系統Bitcask。

舉例Bitcask的哈希表數據結構為:

Bitcask數據文件中的數據是一條一條寫入操作,記錄包含key、value、主鍵長度、value長度、時間戳以及crc校驗值。

數據庫所在服務器在內存中采用基於哈希表的索引數據結構,哈希表的作用是通過主鍵快速地定位到value的位置。哈希表結構中的每一項包含了三個用於定位數據的信息,分別是文件編號(file id),value在文件中的位置(value_pos),value長度(value_sz),通過讀取file_id對應文件的value_pos開始的value_sz個字節,這就得到了最終的value值。寫入時首先將key-value記錄追加到活躍數據文件的末尾,接着更新內存哈希表,因此,每個寫操作總共需要進行一次順序的磁盤寫入和一次內存操作。

Bitcask在內存中存儲了主鍵和value的索引信息,磁盤文件中存儲了主鍵和value的實際內容。

3. B樹存儲引擎

相比哈希存儲引擎,B樹存儲引擎不僅支持隨機讀取,還支持范圍掃描。關系型數據庫中通過索引訪問數據,在Mysql InnoDB中,有一個稱為聚集索引的特殊索引,行的數據存於其中,組織成B+樹(B樹的一種)數據結構。

 B+樹的數據結構:

 如圖所示,MySQL InnoDB按照頁面(Page)來組織數據,每個頁面對應B+樹的一個節點。其中,葉子節點保存每行的完整數據,非葉子節點保存索引信息。數據在每個節點中有序存儲,數據庫查詢時需要從根節點開始二分查找直到葉子節點,每次讀取一個節點,如果對應的頁面不在內存中,需要從磁盤中讀取並緩存起來。B+樹的根節點是常駐內存的,因此,B+樹一次檢索最多需要h-1次磁盤IO,復雜度為O(h)=O(logdN)(N為元素個數,d為每個節點的出度,h為B+樹高度)。修改操作首先需要記錄提交日志,接着修改內存中的B+樹。如果內存中的被修改過的頁面超過一定的比率,后台線程會將這些頁面刷到磁盤中持久化。

4. LSM樹存儲引擎

4.1 LSM主題思想

LSM-Tree主題思想為划分不同等級的數。可以想象一份索引由兩棵樹組成:一個存在於內存(可以使用其他樹結構),一個存在於磁盤(如下圖)。

 

LSM樹的設計思想非常朴素:將對數據的修改增量保持在內存中,達到指定的大小限制后將這些修改操作批量寫入磁盤,不過讀取的時候稍微麻煩,需要合並磁盤中歷史數據和內存中最近修改操作,所以寫入性能大大提升,讀取時可能需要先看是否命中內存,否則需要訪問較多的磁盤文件。極端的來說,基於LSM樹實現的HBase的寫性能比Mysql高了一個數量級,讀性能低了一個數量級。

數據首先會插入到內存中的樹,為了防止數據丟失,寫內存的同時需要暫時持久化到磁盤,即輸入數據時數據會以完全有序的形式先存儲在日志文件中(對應HBase的MemStore和HLog)。當日志文件被修改時,對應的更新會被先保存在內存中來加速查詢。

當內存中樹的數據達到閥值時,會進行合並操作。合並操作會從左至右遍歷內存中的葉子節點與磁盤中樹的葉子節點進行合並,當合並的數據量達到磁盤的存儲頁的大小時,會將合並的數據持久化到磁盤。同時更新父親節點對葉子節點的指針(如下圖)。

查找通過合並的方式完成,首先搜索內存存儲結構,接下來是磁盤存儲結構。

LSM樹所有節點都是滿的並按頁存儲,經過多次的flush會創建很多數據存儲文件,后台線程會將小文件聚合成大文件,因此磁盤的尋道操作就會被限制在一定數目的數據存儲文件中,以優化讀性能。磁盤上的樹結構也可以分割成多個存儲文件,因為所有的存儲數據都是按照Key有序排列的,因此在現有節點中插入新的關鍵字不需要重新排序。

LSM-Tree屬於傳輸型,在磁盤傳輸速率上進行文件的排序和合並以及日志操作,可以更好的拓展到更大的數據規模上,因為它會使用日志文件和一個內存存儲結構把隨機寫操作轉化為順序寫,讀寫獨立,不會產生兩種操作的競爭。

4.2 LSM樹在HBase中的應用

LSM樹可以看成n層合並樹。在HBase中,它把隨機寫轉換成對MemStore和HFile的連續寫。下圖展示了LSM樹數據寫的過程。

數據寫(插入,更新):數據首先順序寫如HLog(WAL),然后寫到MemStore,在MemStore中,數據是一個2層B+樹(上圖中的C0樹)。MemStore滿了之后,數據會被刷到StoreFile(HFile),在StoreFile中,數據是3層B+樹(圖2中的C1樹),並針對順序磁盤操作進行優化。

數據讀:首先搜索MemStore,如果不在MemStore中,則到StoreFile中尋找。

數據刪除:不會去刪除磁盤上的數據,而是為數據添加一個刪除標記。在隨后的major compaction中,被刪除的數據和刪除標記才會真的被刪除。

LSM數據更新只在內存中操作,沒有磁盤訪問,因此比B+樹要快。對於數據讀來說,如果讀取的是最近訪問過的數據,LSM樹能減少磁盤訪問,提高性能。

總結

參考資料:

https://blog.csdn.net/lifuxiangcaohui/article/details/39962921

https://blog.csdn.net/a_zhenzhen/article/details/78831866

https://blog.csdn.net/liuxiao723846/article/details/52971511

https://blog.csdn.net/u014432433/article/details/51557834


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM