HBase 篇(六):HFile 合併過程詳解
簡單地說Compaction 合併是指一個 region 的一個 store 中的一些 HFile 合為一個 HFile 的操作。過程是先從這些待合併的資料檔案中讀出 KeyValues ,再按照由小到大排列後寫入一個新的檔案中。之後,這個新生成的檔案就會取代之前待合併的所有檔案對外提供服務。
HBase 根據合併規模將 Compaction 分為了兩類:MinorCompaction 和 MajorCompaction
Minor Compaction是指選取一些小的、相鄰的StoreFile將他們合併成一個更大的StoreFile,在這個過程中不會處理已經Deleted或Expired的Cell。一次Minor Compaction的結果是更少並且更大的StoreFile。
Major Compaction是指將所有的StoreFile合併成一個StoreFile,這個過程還會清理三類無意義資料:被刪除的資料、TTL過期資料、版本號超過設定版本號的資料。另外,一般情況下,Major Compaction時間會持續比較長,整個過程會消耗大量系統資源,對上層業務有比較大的影響。因此線上業務都會將關閉自動觸發Major Compaction功能,改為手動在業務低峰期觸發。
合併storefile的原因
資料載入到memstore,資料越來越多直到memstore佔滿,再寫入硬碟storefile中,每次寫入形成一個單獨storefile,當storefile達到一定的數量後,就會開始把小storefile合併成大storefile,因為Hadoop不擅長處理小檔案,檔案越大效能越好。
什麼時候合併
觸發compaction的方式有三種:Memstore刷盤、後臺執行緒週期性檢查、手動觸發。
1.Memstore Flush:
應該說compaction操作的源頭就來自flush操作,memstore flush會產生HFile檔案,檔案越來越多就需要compact。因此在每次執行完Flush操作之後,都會對當前Store中的檔案數進行判斷,一旦檔案數大於配置,就會觸發compaction。需要說明的是,compaction都是以Store為單位進行的,而在Flush觸發條件下,整個Region的所有Store都會執行compact,所以會在短時間內執行多次compaction。
2.後臺執行緒週期性檢查:
後臺執行緒定期觸發檢查是否需要執行compaction,檢查週期可配置。執行緒先檢查檔案數是否大於配置,一旦大於就會觸發compaction。如果不滿足,它會接著檢查是否滿足major compaction條件,簡單來說,如果當前store中hfile的最早更新時間早於某個值mcTime,就會觸發major compaction(預設7天觸發一次,可配置手動觸發),HBase預想通過這種機制定期刪除過期資料。
3.手動觸發:
一般來講,手動觸發compaction通常是為了執行major compaction,一般有這些情況需要手動觸發合併
-
是因為很多業務擔心自動major compaction影響讀寫效能,因此會選擇低峰期手動觸發;
-
也有可能是使用者在執行完alter操作之後希望立刻生效,執行手動觸發major compaction;
-
是HBase管理員發現硬碟容量不夠的情況下手動觸發major compaction刪除大量過期資料;
如何排序?
由於記憶體裡memstore是在資料插入的過程中就排序的,就是資料插入的時候按照順序插入,所以memstore裡的資料是有序的。當memstore的資料刷寫到磁碟時,生成的storefile裡的資料也是有序的,這樣的話各個storefile裡的資料就分別有序了。合併的時候需要將各個有序的storefile合併成一個大的有序的storefile。
首先將各個需要合併的storefile封裝成StoreFileScanner最後形成一個List載入到記憶體,然後再封裝成StoreScanner物件,這個物件初始化的時候會對各個StoreFileScanner進行排序放到內部的佇列裡,排序是按照各個StoreFileScanner最小的rowkey進行排序的。然後通過StoreScanner的next()方法可以拿到各個StoreFileScanner最小rowkey中的最小rowkey對應的KV對。然後就把取出的KV對追加寫入合併後的storefile。因為每次取出的都是各個storefile裡最小的資料,所以追加寫入合併後的storefile裡的資料就是按從小到大排序的有序資料。
在合併的過程中會做什麼操作?
在合併的過程中會拋棄刪除標識的行和版本過舊的行
(1)可以預先定義版本的個數,超過這個值就拋棄
(2)還可以預先定義版本的時間長短,超過這個時間就拋棄,合併完後形成更大的storefile,當達到數量再次合併,直到storefile容量超過一定閥值後會把當前的Region進行分裂為2個並由Hmaster(hbase資料庫主控節點)分配到不同的HRegionServer伺服器處理實現負載均衡。
如果在合併過程中恰好有涉及到有關storefile的查詢發生的話,我們先是把小storefile載入到記憶體中進行合併此時如有使用者訪問可以在記憶體中檢索相關資料返回給使用者,我們可以想象在記憶體中做一個獨立映象備份專門提供被查詢需求,另一個主體在另一塊記憶體空間裡進行合併,當合並完成後釋放備份的記憶體空間,返回到原來的狀態。
覺得有價值請關注 ▼