Sorry!Hbase的LSM Tree就是能夠隨心所欲!

咱們先拋出一個問題:算法

file

LSM樹是HBase裏使用的很是有創意的一種數據結構。在有表明性的關係型數據庫如MySQL、SQL Server、Oracle中,數據存儲與索引的基本結構就是咱們耳熟能詳的B樹和B+樹。而在一些主流的NoSQL數據庫如HBase、Cassandra、LevelDB、RocksDB中,則是使用日誌結構合併樹(Log-structured Merge Tree,LSM Tree)來組織數據。數據庫

首先,咱們從B+樹講起

爲何在RDBMS中咱們須要B+樹(或者廣義地說,索引)?一句話:減小尋道時間。在存儲系統中普遍使用的HDD是磁性介質+機械旋轉的,這就使得其順序訪問較快而隨機訪問較慢。使用B+樹組織數據能夠較好地利用HDD的這種特色,其本質是多路平衡查找樹。一個典型的B+樹以下圖所示:性能優化

file

  • B+樹的磁盤讀寫代價更低:B+樹的內部節點並無指向關鍵字具體信息的指針,所以其內部節點相對B樹更小,若是把全部同一內部節點的關鍵字存放在同一盤塊中,那麼盤塊所能容納的關鍵字數量也越多,一次性讀入內存的須要查找的關鍵字也就越多,相對IO讀寫次數就下降了。數據結構

  • B+樹的查詢效率更加穩定:因爲非終結點並非最終指向文件內容的結點,而只是葉子結點中關鍵字的索引。因此任何關鍵字的查找必須走一條從根結點到葉子結點的路。全部關鍵字查詢的路徑長度相同,致使每個數據的查詢效率至關。性能

  • 因爲B+樹的數據都存儲在葉子結點中,分支結點均爲索引,方便掃庫,只須要掃一遍葉子結點便可,可是B樹由於其分支結點一樣存儲着數據,咱們要找到具體的數據,須要進行一次中序遍歷按序來掃,因此B+樹更加適合在區間查詢的狀況,因此一般B+樹用於數據庫索引。大數據

若是你對B+樹不夠熟悉,能夠參考這裏:http://www.javashuo.com/article/p-dgncxeef-cp.html優化

那麼,B+樹有什麼缺點呢?

B+樹最大的性能問題是會產生大量的隨機IO,隨着新數據的插入,葉子節點會慢慢分裂,邏輯上連續的葉子節點在物理上每每不連續,甚至分離的很遠,但作範圍查詢時,會產生大量讀隨機IO。.net

LSM Tree

爲了克服B+樹的弱點,HBase引入了LSM樹的概念,即Log-Structured Merge-Trees。設計

LSM Tree(Log-structured merge-tree)起源於1996年的一篇論文:The log-structured merge-tree (LSM-tree)。當時的背景是:爲一張數據增加很快的歷史數據表設計一種存儲結構,使得它可以解決:在內存不足,磁盤隨機IO太慢下的嚴重寫入性能問題。指針

LSM Tree(Log-structured merge-tree)普遍應用在HBase,TiDB等諸多數據庫和存儲引擎上:

file

咱們來看看大佬設計這個數據結構:

file

Ck tree是一個有序的樹狀結構,數據的寫入流轉從C0 tree 內存開始,不斷被合併到磁盤上的更大容量的Ck tree上。因爲內存的讀寫速率都比外存要快很是多,所以數據寫入的效率很高。而且數據從內存刷入磁盤時是預排序的,也就是說,LSM樹將本來的隨機寫操做轉化成了順序寫操做,寫性能大幅提高。不過它犧牲了一部分讀性能,由於讀取時須要將內存中的數據和磁盤中的數據合併。

回到Hbase來,咱們在以前的文章中《Hbase性能優化手冊》中提到過Hbase的讀寫流程:

file

MemStore是HBase中C0的實現,向HBase中寫數據的時候,首先會寫到內存中的MemStore,當達到必定閥值以後,flush(順序寫)到磁盤,造成新的StoreFile(HFile),最後多個StoreFile(HFile)又會進行Compact。

memstore內部維護了一個數據結構:ConcurrentSkipListMap,數據存儲是按照RowKey排好序的跳躍列表。跳躍列表的算法有同平衡樹同樣的漸進的預期時間邊界,而且更簡單、更快速和使用更少的空間。

file

HBase爲了提高LSM結構下的隨機讀性能,還引入了布隆過濾器(建表語句中能夠指定),對應HFile中的Bloom index block,其結構圖以下所示。

file

經過布隆過濾器,HBase就能以少許的空間代價,換來在讀取數據時很是快速地肯定是否存在某條數據,效率進一步提高。

歡迎關注,《大數據成神之路》系列文章

歡迎關注,《大數據成神之路》系列文章

歡迎關注,《大數據成神之路》系列文章

相關文章
相關標籤/搜索