LSM樹是HBase裡非常有創意的一種資料結構,它和傳統的B+樹不太一樣,下面先說說B+樹。 1 B+樹
相信大家對B+樹已經非常的熟悉,比如Oracle的普通索引就是採用B+樹的方式,下面是一個B+樹的例子:
根節點和枝節點很簡單,分別記錄每個葉子節點的最小值,並用一個指標指向葉子節點。
葉子節點裡每個索引值都指向真正的資料區塊(如Oracle裡的RowID),每個葉子節點都有前指標和後指標,這是為了做範圍查詢時,葉子節點間可以直接跳轉,從而避免再去回溯至枝和跟節點。
B+樹最大的效能問題是會產生大量的隨機IO,隨著新資料的插入,葉子節點會慢慢分裂,邏輯上連續的葉子節點在物理上往往不連續,甚至分離的很遠,但做範圍查詢時,會產生大量讀隨機IO。
對於大量的隨機寫也一樣,舉一個插入key跨度很大的例子,如7->1000->3->2000 ... 新插入的資料存放區在磁碟上相隔很遠,會產生大量的隨機寫IO.
從上面可以看出,低下的磁碟尋道速度嚴重影響效能(近些年來,磁碟尋道速度的發展幾乎處於停滯的狀態)。 2 LSM樹
為了克服B+樹的弱點,HBase引入了LSM樹的概念,即Log-Structured Merge-Trees。
為了更好的說明LSM樹的原理,下面舉個比較極端的例子:
現在假設有1000個節點的隨機key,對於磁碟來說,肯定是把這1000個節點順序寫入磁碟最快,但是這樣一來,讀就悲劇了,因為key在磁碟中完全無序,每次讀取都要全掃描;
那麼,為了讓讀效能盡量高,資料在磁碟中必須得有序,這就是B+樹的原理,但是寫就悲劇了,因為會產生大量的隨機IO,磁碟尋道速度跟不上。
LSM樹本質上就是在讀寫之間取得平衡,和B+樹相比,它犧牲了部分讀效能,用來大幅提高寫效能。
它的原理是把一顆大樹拆分成N棵小樹, 它首先寫入到記憶體中(記憶體沒有尋道速度的問題,隨機寫的效能得到大幅提升),在記憶體中構建一顆有序小樹,隨著小樹越來越大,記憶體的小樹會flush到磁碟上。當讀時,由於不知道資料在哪棵小樹上,因此必須遍曆所有的小樹,但在每顆小樹內部資料是有序的。
以上就是LSM樹最本質的原理,有了原理,再看具體的技術就很簡單了。
1)首先說說為什麼要有WAL(Write Ahead Log),很簡單,因為資料是先寫到記憶體中,如果斷電,記憶體中的資料會丟失,因此為了保護記憶體中的資料,需要在磁碟上先記錄logfile,當記憶體中的資料flush到磁碟上時,就可以拋棄相應的Logfile。
2)什麼是memstore, storefile。很簡單,上面說過,LSM樹就是一堆小樹,在記憶體中的小樹即memstore,每次flush,記憶體中的memstore變成磁碟上一個新的storefile。
3)為什麼會有compact。很簡單,隨著小樹越來越多,讀的效能會越來越差,因此需要在適當的時候,對磁碟中的小樹進行merge,多棵小樹變成一顆大樹。