天天看點

HBase源碼分析之MemStore的flush發起時機、判斷條件等詳情(二)

        在HRegionServer中,有一個和合并檢查線程compactionChecker一樣的Chore--periodicFlusher,它也是類似于compactionChecker的背景工作線程,它負責周期性的檢查MemStore,檢視是否達到發起MemStore flush的條件。其定義如下:

        很簡單,構造一個PeriodicMemstoreFlusher對象,而且其工作頻率也是通過HRegionServer的threadWakeFrequency決定的。那麼這個periodicFlusher到底是什麼樣的實作類,其工作原理是什麼樣子的呢?莫慌,讓我為大家一一道來。

        首先看下PeriodicMemstoreFlusher的定義、成員變量與構造方法,代碼如下:

        通過成員變量和構造方法,我們可以看到,比較重要的就是線程中HRegionServer的執行個體server以及線程工作頻率。另外它還提供了兩個定值MIN_DELAY_TIME與RANGE_OF_DELAY,有什麼用呢。繼續看它的chore()方法:

        通過chore()方法我們知道,periodicFlusher線程周期性的對HRegionServer上所有線上Region進行檢測,調用其shouldFlush()方法進行檢測,如果該Region需要flush memstore,擷取RegionServer上的MemStoreFlusher類型的memstore記憶體重新整理管理對象,發起flush請求。

        需要注意的是,該flush請求攜帶一個固定加随機的延遲時間,其算法為:

        MIN_DELAY_TIME就是我們上面提到的固定值3秒,然後再加上一個20s内的一個随機數。為什麼要這麼做呢?試想下,如果立即送出一個flush請求,或者在3秒後立即送出一個flush請求,是不是很容易就産生一個風暴,引起系統性能瓶頸呢?

        關于如何送出一個flush請求,前面的文章已經介紹過了,不再贅述。這裡我們介紹下HRegion的shouldFlush()方法,代碼如下:

        判斷的邏輯比較清晰,概括如下:

        1、首先,上次flush之後,sequenceId的增長超過flushPerChanges,即發起一次flush:

              次數限制flushPerChanges是通過參數hbase.regionserver.flush.per.changes配置,預設為30000000(3千萬),這個sequenceId的增長該Region上資料的改動次數,無論增、删、改或者append、increment等,它是對HRegion資料變動的一個考慮,即便是MemStore不大,資料變動的頻繁了,也需要進行flush,以降低當機後拆分日志的工作量;

        2、再看參數hbase.regionserver.optionalcacheflushinterval:

              參數小于等于0,不會觸發flush,時間間隔未超過參數l配置的時間間隔的話,也不會觸發flush。這個參數預設為3600000ms,即1小時;

        3、當超過參數配置的時間間隔,再檢測每個列簇,當其中一個列簇超過flushCheckInterval沒有flush時,發起flush,也就是說它有足夠久的資料沒有被flush。

        以上就是HRegionServer内部PeriodicMemstoreFlusher工作線程periodicFlusher的全部内容。同時,在上面針對每個HRegion的循環,以及後面針對每個HStore的判斷,我們可以發現,flush還是以Region為最小機關進行的。即便是某個列簇下MemStore過大或者過舊,另外一個MemStore還比較小或者比較新的話,它還是跟着那個過大或者過舊的列簇一起flush,這也是HBase飽受诟病的列簇不能過多的原因之一。在HBase1.1.2版本中,有對于MemStore

flush的改進,改成了以HStore,即列簇為機關進行。此乃後話,我們以後再做分析。

繼續閱讀