LSM Tree存儲組織結構介紹


LSM Tree(Log Structured Merge Trees)數據組織方式被應用於多種數據庫,如LevelDB、HBase、Cassandra等,下面我們從為什么使用LSM tree、LSM tree的實現思路兩方面介紹這種存儲組織結構,完成對LSM tree的初步了解。

 

存儲背景回顧

LSM tree相較B+樹或其他索引存儲實現方式,提供了更好的寫性能。究其原因,我們先回顧磁盤相關的一點背景知識。

 

順序操作磁盤的性能,較隨機讀寫磁盤的性能高很多,我們實現數據庫時,也是圍繞磁盤的這點特性進行設計與優化。如果讓寫性能最優,最佳的實現方式就是日志型(Log/Journal)數據庫,其以追加(Append)的方式寫磁盤文件。

 

有得即有舍,萬事萬物存在權衡,帶來最優寫性能的同時,單純的日志數據庫讀性能很差,為找到一條數據,不得不遍歷數據記錄,要實現范圍查詢(range)幾乎不可能。為優化日志型數據庫的讀性能,實際應用中通常結合以下幾種優化措施:

二分查找(Binary Search): 在一個數據文件中使用二分查找加速數據查找

哈希(Hash): 寫入時通過哈希函數將數據放入不同的桶中,讀取時通過哈希索引直接讀取

B+樹: 使用B+樹作為數據組織存儲形式,保持數據穩定有序

外部索引文件: 除數據本身按日志形式存儲外,另對其單獨建立索引加速讀取

 

以上措施都很大程度提升了讀性能(如二分查找將時間復雜度提升至O(log(N))),但相應寫性能也有折損,第一寫數據時需要維護索引,這視索引的實現方式,最差情況下可能涉及隨機的IO操作;第二如果用B+樹等結構組織數據,寫入涉及兩次IO操作,先要將數據讀出來再寫入。

 

LSM Tree存儲結構

LSM tree存儲實現思路與以上四種措施不太相同,其將隨機寫轉化為順序寫,盡量保持日志型數據庫的寫性能優勢,並提供相對較好的讀性能。具體實現方式如下:

1. 當有寫操作(或update操作)時,寫入位於內存的buffer,內存中通過某種數據結構(如skiplist)保持key有序

2. 一般的實現也會將數據追加寫到磁盤Log文件,以備必要時恢復

3. 內存中的數據定時或按固定大小地刷到磁盤,更新操作只不斷地寫到內存,並不更新磁盤上已有文件

4. 隨着越來越多寫操作,磁盤上積累的文件也越來越多,這些文件不可寫且有序

5. 定時對文件進行合並操作(compaction),消除冗余數據,減少文件數量

 

以上過程用圖表示如下:

LSM Tree存儲結構的寫操作,只需更新內存,內存中的數據以塊數據形式刷到磁盤,是順序的IO操作,另外磁盤文件定期的合並操作,也將帶來磁盤IO操作。

LSM tree存儲結構的讀操作,先從內存數據開始訪問,如果在內存中訪問不到,再順序從一個個磁盤文件中查找,由於文件本身有序,並且定期的合並減少了磁盤文件個數,因而查找過程相對較快速。

 

合並操作是LSM tree實現中重要的一環,LevelDB、Cassandra中,使用基於層級的合並方式(Levelled compaction),生成第N層的時候,對N-1層的數據進行排序,使得每層內的數據文件之間都是有序的,但最高層除外,因為該層不斷有數據文件產生,因而只是數據文件內部按key有序。

 

除最高層外,其他層文件間數據有序,這也加速了讀過程,因為一個key對應的value只存在一個文件中。假設總共有N層,每層最多K個數據文件,最差的情況下,讀操作先遍歷K個文件,再遍歷每層,共需要K+(N-1)次讀盤操作。

 

總結

LSM tree存儲框架實現的思路較簡單,其先在內存中保存數據,再定時刷到磁盤,實現順序IO操作,通過定期合並文件減少數據冗余;文件有序,保證讀取操作相對快速。

我們需要結合實際的業務場景選擇合適的存儲實現,不存在萬金油式的通用存儲框架。LSM tree適用於寫多、讀相對少(或較多讀取最新寫入的數據,該部分數據存在內存中,不需要磁盤IO操作)的業務場景。

 

參考文章: Log Structured Merge Trees


免責聲明!

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



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