原創文章,轉載請注明原作地址:http://www.lxweimin.com/p/895ab6511819
在介紹HBase Compaction之前,我們先來看一下HBase是如何存儲和操作數據。
如上圖所示,HRegionServer負責打開region,并創建對應的HRegion實例。當HRegion打開之后,它會為每個表的HColumnFamily創建一Store實例,ColumnFamily是用戶在創建表時定義好的,ColumnFamily在每個region中和Store實例一一對應。每個Store實例包含一個或者多個StoreFile實例,StoreFile是對實際存儲數據文件HFile的輕量級封裝。每個Store對應一個MemStore(也就是寫內存)。一個HRegionServer共享一個HLog實例。
當我們不停地往HBase中寫入數據,也就是往MemStore寫入數據,HBase會檢查MemStore是否達到了需要刷寫到磁盤的閾值(更多關于MemStore刷寫的信息,可以參考HBase Reference Guide關于MemStore的介紹)。如果達到刷寫的條件,MemStore中的記錄就會被刷寫到磁盤,形成一個新的StoreFile。可想而知,隨著MemStore的不斷刷寫,會形成越來越多的磁盤文件。然而,對于HBase來說,當每個HStore僅包含一個文件時,才會達到最佳的讀效率。因此HBase會通過合并已有的HFile來減少每次讀數據的磁盤尋道時間,從而提高讀速度,這個文件合并過程就稱為Compaction。在這里需要說明的是,顯然磁盤IO也是有代價的,如果使用不慎的話,不停地重寫數據可能會導致網絡和磁盤過載。換句話說,compaction其實就是用當前更高的磁盤IO來換取將來更低的磁盤尋道時間。因此,何時執行compaction,其實是一個相當復雜的決策。
HBase的compaction分為minor和major兩種。minor合并負責將幾個小文件合并成一個較大的文件;major合并是將一個HStore中的所有文件合并成一個文件。每次觸發compact檢查。系統會自動決定執行哪一種compaction(合并)。有三種情況會觸發compact檢查:
- MemStore被刷寫到磁盤;
- 用戶執行shell命令compact、major_compact或者調用了相應的API;
- HBase后臺線程周期性觸發檢查。
除非是用戶使用shell命令major_compact
或者調用了majorCompact()
API(這種情況會強制HBase執行major合并),在其他的觸發情況下,HBase服務器會首先檢查上次運行到現在是否達到一個指定的時限。如果沒有達到這個時限,系統會選擇執行minor合并,接著檢查是否滿足minor合并的條件。
major合并中會刪除那些被標記為刪除的數據、超過TTL(time-to-live)時限的數據,以及超過了版本數量限制的數據,將HStore中所有的HFile重寫成一個HFile。如此多的工作量,理所當然地,major合并會耗費更多的資源,合并進行時也會影響HBase的響應時間。在HBase 0.96之前,默認每天對region做一次major compact,現在這個周期被改成了7天。然而,因為major compact可能導致某臺server短時間內無法響應客戶端的請求,如果無法容忍這種情況的話,可以關閉自動major compact,改成在請求低谷期手動觸發這一操作。
minor合并的關鍵是,要如何挑選那些被合并的小文件?0.96版本之前,HBase的合并策略只有一個RatioBasedCompactionPolicy。這個策略中有三個重要參數:首先是hbase.hstore. compaction.min. size
和hbase.hstore. compaction.max. size
,在minor合并中,所有大小超過max. size的文件都會被排除在外,而min. size其實是一個閾值,minor合并會盡可能多地包括那些文件大小低于min. size的文件;在一次minor合并中,合并的文件數量最多不能超過hbase.hstore. compaction.max
。另外,這個策略選擇需要合并的文件時,總是優先選擇較老的文件,也就意味著,沿著時間軸從最老的文件開始掃描,HBase會選擇合并它掃描到的第一個滿足合并策略的文件集合。
然而,實際操作中發現RatioBasedCompactionPolicy的表現并不好,因為這個策略假設越老的文件大小越大,而實際情況并不是這樣,比如bulkLoad導入的新文件大小就很可能大于舊文件。于是,之后HBase加入了一個新策略ExploringCompactionPolicy。在這個策略中,HBase不是選擇第一個符合合并策略的文件集合,而是考慮了所有符合要求的文件集合,并從中選擇文件數量最多的集合(當有多個這樣的文件集合時,選擇總文件大小最小的那個集合)。這樣導致的影響是,HBase總是選擇合并會為IO帶來最佳改善的文件集合。
隨著compaction的進行,當所有文件中最大的那個超過了配置的最大存儲文件大小,又會觸發region拆分(如果region拆分沒有被禁止的話)。
參考鏈接:
http://blog.cloudera.com/blog/2013/12/what-are-hbase-compactions/
https://hbase.apache.org/book.html#compaction
《HBase權威指南》