regionserver初始化的時候會初始化兩個與compact相關的線程它們分别是:compactionChecker和compactSplitThread。其中compactionChecker用于周期性地檢查目前是否有compact請求,實作類是ScheduledChore檢查周期由參數threadWakeFrequency控制,預設值是10s,也可以在參數hbase.server.thread.frequency中配置。
另一個成員變量compactSplitThread負責該region server上的compact/split請求具體執行。
其包含了四個線程池分别用于major compact,minor compact split和merge。
compact的大體步驟是:compactionChecker周期性地檢查是否有compact請求,如果出現了compact請求,那麼将請求以及請求的周邊資訊一起包裝成CompactionContext,将CompactionContext傳遞給regionserver的compactSplitThread,compactSplitThread會根據compact的類型為它配置設定合适的線程池,并包裝成compactSplitThread内部類CompactionRunner交給對應線程池,線程池排程CompactionRunner,執行它的run方法,完成compact操作。
compactionChecker實作類是CompactionChecker,其繼承了ScheduledChore,在之前已經分析過,這個類通過實作chore方法而實作周期性的調用,其初始化是在initializeThreads中:
我們直接看其Chore方法:
這個方法比較簡單,取出所有線上的region,周遊region上的所有store(HStore)判斷是否需要compact,這裡判斷是
可以看到最終條件為:HStore中StoreFIles的個數 – 正在執行Compacting的檔案個數 > minFilesToCompact。
我們都知道compact分成了兩種,monor和major,其差別在官方文檔中有說明:
1.Minor操作隻用來做部分檔案的合并操作以及包括minVersion=0并且設定ttl的過期版本清理,不做任何删除資料、多版本資料的清理工作。也即是說選取一些小的、相鄰的StoreFile将他們合并成一個更大的StoreFile,在這個過程中不會處理已經Deleted或Expired的Cell。一次Minor Compaction的結果是更少并且更大的StoreFile。
2.Major操作是對Region下的HStore下的所有StoreFile執行合并操作,最終的結果是整理合并出一個檔案。這個過程還會清理三類無意義資料:被删除的資料、TTL過期資料、版本号超過設定版本号的資料。另外,一般情況下,Major Compaction時間會持續比較長,整個過程會消耗大量系統資源,對上層業務有比較大的影響。是以線上業務都會将關閉自動觸發Major Compaction功能,改為手動在業務低峰期觸發。
chore方法中needsCompaction判斷的是minor compact是否需要執行。從chore方法中可以直覺的看到major compact是通過isMajorCompaction()方法判斷的這是很多判斷條件的合成,其中最為重要的一個是hbase.hregion.majorcompaction設定的值,也就是判斷上次進行majorCompaction到目前的時間間隔,如果超過設定值,則滿足一個條件,同時另外一個條件是compactSelection.getFilesToCompact().size() < this.maxFilesToCompact。
是以,通過設定hbase.hregion.majorcompaction = 0可以關閉CompactionChecke觸發的major compaction,但是無法關閉使用者調用級别的majorcompact。isMajorCompaction,最終實作的判斷是來自RatioBasedCompactionPolicyd的isMajorCompaction方法: