????????HBase是采用Log-Structured Merge Tree的架構(gòu),隨著Flush階段的不斷觸發(fā),生成許多的HFile(默認(rèn)128M),而不管是對(duì)于HDFS還是現(xiàn)有的HDD磁盤,大量的文件都會(huì)產(chǎn)生許多的問題:
1、增加HDFS NameNode的負(fù)載
2、查詢數(shù)據(jù)會(huì)增加磁盤尋址次數(shù),增加io
????????但是隨著SDD磁盤的成本下降,磁盤尋址的問題也將不是影響性能的主要因素,同時(shí)hdfs小文件利器Ozone的提出,未來HBase是否會(huì)考慮廢棄Compaction,采用更加優(yōu)雅的方式來完成過期/被刪除 數(shù)據(jù)的清除,這些都將會(huì)是社區(qū)會(huì)討論的問題。
????????Compaction根據(jù)合并的規(guī)模,分為了Minor Compaction和Major Compaction:
1、Major Compaction,是將一個(gè)Store下的所有StoreFile合并成一個(gè)StoreFile,同時(shí)清理無效數(shù)據(jù):被刪除的數(shù)據(jù)、過期的數(shù)據(jù)、超過Version設(shè)置的數(shù)據(jù)。對(duì)于Major Compaction的優(yōu)化就是選擇在合適的時(shí)間觸發(fā),并避免過于占用集群io資源。許多的大佬都建議關(guān)閉自動(dòng)定期的Major Compaction,而采用手動(dòng)在集群業(yè)務(wù)低峰期觸發(fā),但是當(dāng)集群未存在明顯的業(yè)務(wù)低峰期時(shí),可保留自動(dòng)觸發(fā),同時(shí)設(shè)置限流,目前筆者是這樣實(shí)現(xiàn)。
2、Minor Compaction,是根據(jù)特定的策略選取一些符合策略的StoreFile進(jìn)行合并。
HBase提供了很多Minor Compaction的StoreFile選取策略,包括:StripeCompactionPolicy、RatioBasedCompactionPolicy、ExploringCompactionPolicy、FIFOCompactionPolicy、以及本文主角DateTieredCompactionPolicy。其他的壓縮策略可參照范神的兩篇博客:HBase Compaction身世之旅、HBase Compaction改造之路。需要根據(jù)業(yè)務(wù)的特定選擇合適的壓縮策略,本文介紹日期分層壓測(cè)策略DateTieredCompactionPolicy,并介紹筆者的業(yè)務(wù)場(chǎng)景。
業(yè)務(wù)特點(diǎn)
? ? ? ? 本司主營(yíng)業(yè)務(wù)為IOT智能家居,HBase中主要存儲(chǔ)智能設(shè)備采集上來的數(shù)據(jù)。
數(shù)據(jù)及業(yè)務(wù)特點(diǎn):
????1、跟時(shí)間強(qiáng)相關(guān)
????2、沒有刪除操作
? ? 3、最近兩天的數(shù)據(jù)被查詢的概率非常高
????4、查詢大多根據(jù)TimeRange和
? ? ? ? 由于上面的特點(diǎn),在Compaction時(shí),希望:
????1、較為古老的StoreFile不參與到壓縮中來增加不必要的IO
????2、Scan時(shí)可以根據(jù)TimeRange過濾掉更多不存在目標(biāo)數(shù)據(jù)的StoreFile
? ? 3、同時(shí)由于設(shè)置了TTL,對(duì)于老的StoreFile可以實(shí)現(xiàn)整個(gè)文件直接刪除
由于使用的HBase1.2.0-cdh5.7.2并不存在日期分層壓縮策略,需要打入對(duì)應(yīng)的patch: HBASE-15181
DateTieredCompactionPolicy
? ??????DateTieredCompactionPolicy采用時(shí)間窗口的概念,時(shí)間窗口越來越大,先介紹主要的配置參數(shù):
????1、hbase.hstore.compaction.date.tiered.base.window.millis?
? ? ? ? 初始窗口大小,默認(rèn)為6h。最近6h生成的HFile會(huì)在一個(gè)Window中,這里的最近6小時(shí)是指:[now/6h, (now/6h) + 1),相當(dāng)于UTC時(shí)間的每日[0,6),[6,12),[12,18),[18,24)。并不是真正意義上的最近的6小時(shí)。
? ? 2、hbase.hstore.compaction.date.tiered.windows.per.tier
? ? ? ? 窗口增加倍數(shù),假如為2,那么窗口的大小依次為:6h,12h,24h以此類推。當(dāng)一個(gè)窗口中StoreFile的數(shù)量達(dá)到設(shè)置的文件數(shù)后會(huì)就會(huì)壓縮成一個(gè)。同一個(gè)窗口內(nèi)默認(rèn)采用ExploringCompactionPolicy壓縮策略。
? ? 3、hbase.hstore.compaction.date.tiered.max.tier.age.millis
? ? ? ? 最老的窗口,超過這個(gè)時(shí)間的StoreFile將不會(huì)進(jìn)行Minor Compaction,默認(rèn)為L(zhǎng)ong.MAX_VALUE。

? ? 那如何判斷一個(gè)StoreFile在不在一個(gè)Window中呢?
? ? ? ? 在hbase1.2中每一個(gè)HStore維護(hù)了一個(gè)TimeRangeTracker,這會(huì)記錄寫到當(dāng)前MemStore的Cell的timestamp的范圍。客戶端構(gòu)建Put時(shí),可以指定當(dāng)前Put的timeStamp,默認(rèn)當(dāng)Server的當(dāng)前系統(tǒng)時(shí)間(ms)。在TimeRangeTracker中存在minimumTimestamp和maximumTimestamp兩個(gè)字段,用來表示當(dāng)前Memstore的TimeRange,當(dāng)觸發(fā)Flush時(shí),這將寫到HFile中,用來標(biāo)識(shí)HFile的TimeRange。如果HFile的maximumTimestamp<窗口的開始時(shí)間時(shí),當(dāng)前HFile肯定不屬于當(dāng)前窗口。
? ? ? ?應(yīng)用DateTieredCompactionPolicy,也是因?yàn)楣P者還存在另外一層業(yè)務(wù)。需要每日凌晨將昨天所有設(shè)備產(chǎn)生的數(shù)據(jù)拉取到hive中,為統(tǒng)計(jì)分析業(yè)務(wù)提供數(shù)據(jù)。起初使用Spark on HBase SnapshotScan時(shí),由于無法通過設(shè)置TimeRange過濾掉更多無用的HFile,導(dǎo)致數(shù)據(jù)抽取項(xiàng)目對(duì)集群的IO影響非常大,在應(yīng)用了該壓縮策略后,數(shù)據(jù)抽取時(shí),不論是集群的IO還是抽取的速度都有很好的提升。