天天看點

Hbase的flush以及compaction的一些了解

  最近自己看了一些關于flush和compaction的部落格,其中也有一些總結和感悟,于是想寫下來,以供後續參考,如果有了解的不對的地方,我們可以一起讨論~

什麼是Flush和Compaction?它們是在什麼情況下進行的呢?他們的作用是什麼?

Flush我了解的就是将memstore中緩存的寫入資料溢寫到hdfs上,之前看部落格一直了解它是當memstore中的資料達到一定門檻值的時候就觸發flush,但是它并不是我想的這麼簡單(見文章後半部分)。Compaction我了解的就是合并hdfs上多個小的hfile,将其合并成一個大的hfile,減少擷取資料時的讀取消耗,畢竟檔案那麼多一個個去找應該是比找一個大的要費時間,而且我認為hdfs上存取多個小的hfile可能有小檔案問題?

Compaction分minor Compaction和major Compation,小範圍的HFile檔案合并,是minor Compaction,一個列族中将所有的HFile檔案合并,是major Compaction,并且major Compaction可以删除過期資料,被标記删除的資料,版本數溢出的資料。通俗的說一下,就是minor Compation隻是對某一個Region下面的部分hfile進行合并,而major Compaction是對整個region下的hfile進行合并,并且還有清除資料的功能。

Memstore的資料結構  

memstore中的資料結構是CellSet,而CellSet是由ConcurrentSkipListMap實作的(具體見這篇博文:博文),然後更加細緻的就是memstore将自己分為一個可寫的Segment,以及一個或多個不可寫的Segments構成(具體見這篇博文:博文),來的資料先寫在Active Segment,然後到達門檻值時就flush成一個Immutable Segment,然後後來的資料再往Active Segment裡面寫,等到immutable Segment越來越多,就會觸發Immutable Segment的compation,合并成一個大的immutable Segment,等它達到一定門檻值的時候,就持久化成hfile到hdfs上面(這些是我看文章的了解和猜想)。為什麼要這麼做呢?文章裡面解釋的是:"如果MemStore中的資料被直接Flush成HFile,而多個HFile又被Compaction合并成了一個大HFile,随着一次次Compaction發生以後,一條資料往往被重寫了多次,這帶來顯著的IO放大問題,另外,頻繁的Compaction對IO資源的搶占,其實也是導緻HBase查詢時延大毛刺的罪魁禍首之一"。

我當時想的是,反正也是在記憶體裡面對immutable Segment要進行合并,持久化成hfile之後在hdfs上到達一定數量也得觸發compaction,其實感覺發生compaction的次數應該是差不多的。後來想明白了,應該是在記憶體裡面進行合并比在磁盤上進行合并消耗的資源和IO要少很多,并且速度也相對較快。并且此時的compaction的資料是在記憶體中,它不像hfile在hdfs上會有副本,這樣的話,隻需要對一份資料進行compaction就可以了,不需要對三份副本也進行同樣的操作。

另外為什麼不把memstore設定的大一些呢?也是有原因的,因為它的特定的資料結構決定了當它的容量達到一定大小的時候,memstore的寫入性能會受到極大的影響。

到這裡,我有一個問題,并且針對這個問題我有個猜想(具體怎麼樣需要在多看一些部落格或者看源碼解決):我們知道hbase的資料是按照rowkey排序的,我們寫資料的時候是随即寫,并且寫到的最終目的地是放到了hdfs上,而hdfs不允許修改資料,那麼它是怎麼有序的呢?我查了一些資料是說在memstore中進行了排序,然後flush到磁盤的時候,此時其中的hfile已經是有序的了,那麼當我再對同一個rowkey,同一個列族,同一個列的值進行修改的時候,我肯定是重新先去找這個rowkey在哪個region裡面,然後将這條新的記錄寫到對應region中,最後落地到hfile中,最後交到compaction去做資料合并,将老版本的資料去除,這樣就達到了資料更新的目的。

繼續閱讀