【從零單排HBase 04】HBase高性能查詢揭祕

先給結論吧:HBase利用compaction機制,通過大量的讀延遲毛刺和一定的寫阻塞,來換取整體上的讀取延遲的平穩。

1.爲什麼要compaction

在上一篇 HBase讀寫 中我們提到了,HBase在讀取過程中,會創建多個scanner去抓去數據。

其中,會創建多個storefilescanner去load HFile中的指定data block。所以,我們很容易就想到,如果說HFile太多的話,那麼就會涉及到很多磁盤IO,這個就是常說的“讀放大”現象。
HBase高性能查詢揭祕
因此,就有了今天的主題,HBase的核心特性——compaction。

通過執行compaction,可以使得HFile的數量基本穩定,使得IO seek次數穩定,然後每次的查詢rt才能穩定在一定範圍內。

2.compaction的分類

compaction分爲兩種,minor compaction和major compaction。

Minor compaction主要是將一些相鄰的小文件合併爲大文件,這個過程僅僅做文件的合併,並不會刪除deleted type的數據和ttl過期的數據。
在這裏插入圖片描述
Major compaction是指將一個HStore下的所有文件合併爲一個HFile,這個過程會消耗大量系統資源,一般線上會關閉自動定期major compaction的功能(將參數hbase.hregion.majorcompaction設爲0即可關閉,但是flush的觸發還是會進行),改爲手動低峯執行。這個過程會刪除三類數據:標記爲刪除的數據、TTL過期的數據、版本號不滿足要求的數據。
在這裏插入圖片描述
具體什麼時候觸發哪種類型的compaction呢?

滿足以下任意條件會觸發major compaction,否則就是minor compaction:

  • 用戶強制執行major compaction
  • 長時間沒有compact,且候選文件小於閾值(hbase.hstore.compaction.max)
    Store中含有reference文件(split產生的臨時文件),需要通過 major compact進行數據遷移,刪除臨時文件

3.compaction的觸發時機

compaction的觸發時機一共有三種:

1)MemStore flush:

這個在一開始就提到了,相信也很容易理解。因爲每次MemStore flush會產生新的HFile文件,而文件數量超過限制,自然就觸發了compaction。這裏需要注意的是,我們在 深入HBase架構 一文中已經提到,memstore是以region爲單位進行flush的,也就是說,一個region內的任意一個HStore下面的memstore滿了,這個region下的所有HStore的memstore都會觸發flush。然後每個HStore都有可能觸發compaction。

2)後臺線程週期性檢查

HBase有一個後臺線程CompactionChecker,會定期巡檢觸發檢查,是否進行compaction。

這裏和flush觸發的compaction有所不同,這裏先檢查文件樹是否大於閾值,大於就觸發compaction。如果沒有大於閾值,還會檢查下HFile裏面的最早更新時間,是否早於某個閾值(hbase.hregion.majorcompaction),如果早於,就觸發major compaction來達到清理無用數據的目的。

3)手動觸發:

由於我們擔心major compaction會影響業務,因此會選擇業務低峯期進行手動觸發。

還有一部分原因,是用戶執行ddl後,希望理解生效,也會執行手動觸發major compaction。

最後,可能是因爲磁盤容量不夠了,需要major compaction來手動清理無效數據,合併文件。

4.HFile合併過程

1)讀取待合併的HFile的key value,寫入臨時文件中

2)將臨時文件移動到對應的region的數據目錄

3) 將compaction的輸入文件路徑和輸出文件路徑寫入WAL日誌,然後強行執行sync

4)將對應region數據目錄下的輸入文件全部刪除

5.compaction的副作用分析

當然,compaction本身也要涉及到大量文件的讀寫,在表現上就是會有一定的讀延遲毛刺。因此,我們可以認爲,compaction過程是使用短時間的大量IO消耗來換取後續查詢的低延遲。

另一方面,假設處於長時間的高寫入量,HFile的數量一直增長,compaction的速度趕不上HFile增長的速度,那麼,HBase會暫時阻塞寫請求。當每次memstore進行flush的時候,如果一個HStore中的HFile的數量超過了hbase.hstore.blockingStoreFIles(默認爲7),那麼就會暫時阻塞flush的動作,阻塞時間爲abase.hstore.blockingWaitTime。當阻塞時間過去後,觀察HFile的數量下降到上述值,那麼就會繼續flush的操作。這樣,就保證了HFile數量的穩定,但是對寫入會有一定的速度影響。

看到這裏了,原創不易,點個贊吧,你最好看了~

知識碎片重新梳理,構建Java知識圖譜:https://github.com/saigu/JavaKnowledgeGraph (歷史文章查閱非常方便)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章