HBase 刷寫與合併機制介紹

             HBase 是目前主流的 NoSQL 數據庫,是一個高可靠、高性能、高伸縮的分佈式 KV 存儲系統,本文講解 HBase 兩個核心機制——刷寫(Flush)與合併(Compaction),重點介紹其原理及參數配置建議。

1、爲什麼要進行刷寫和合並

         HBase 是 Google BigTable 的開源實現,底層存儲引擎是基於 LSM 樹(Log-Structured Merge Tree)數據結構設計的。寫入數據時會先寫 WAL 日誌,再將數據寫到寫緩存 MemStore 中,等寫緩存達到一定規模或其他觸發條件時會 Flush 刷寫到磁盤,生成一個 HFile 文件,這樣就將磁盤隨機寫變成了順序寫,提高了寫性能。基本拓撲圖:

       隨着時間推移,寫入的 HFile 會越來越多,讀取數據時就會因爲要進行多次io導致性能降低,因此 HBase 會定期執行 Compaction 操作以合併減少 HFile 數量,提升讀性能。

2、Flush 觸發條件和參數

      理解 Flush 的觸發條件非常重要,從中我們也可以看出何時會阻塞寫請求,總結有 7 種情況會觸發 Flush:

  1. 當一個 MemStore 大小達到閾值 hbase.hregion.memstore.flush.size(默認128M)時,會觸發 MemStore 的刷寫。這個時候不會阻塞寫請求。
  2. 當一個 Region 中所有 MemStore 總大小達到 hbase.hregion.memstore.block.multiplier * hbase.hregion.memstore.flush.size(默認4*128M=512M)時,會觸發 MemStore 的刷寫,並阻塞 Region 所有的寫請求,此時寫數據會出現 RegionTooBusyException異常。
  3. 當一個 RegionServer 中所有 MemStore 總大小達到 hbase.regionserver.global.memstore.size.lower.limit* hbase.regionserver.global.memstore.size * hbase_heapsize(低水位閾值,默認0.95 * 0.4 * RS 堆大小)時,會觸發 RegionServer 中內存佔用大的 MemStore 的刷寫;達到 hbase.regionserver.global.memstore.size * hbase_heapsize(高水位閾值,默認0.4 * RS堆大小)時,不僅會觸發 Memstore 的刷寫,還會阻塞 RegionServer 所有的寫請求,直到 Memstore 總大小降到低水位閾值以下。
  4. 當一個 RegionServer 的 HLog 即WAL文件數量達到上限(可通過參數hbase.regionserver.maxlogs 配置,默認32)時,也會觸發 MemStore 的刷寫,HBase 會找到最舊的 HLog 文件對應的 Region 進行刷寫 。
  5. 當一個 Region 的更新次數達到 hbase.regionserver.flush.per.changes(默認30000000即3千萬)時,也會觸發 MemStore 的刷寫。
  6. 定期 hbase.regionserver.optionalcacheflushinterval(默認3600000即一個小時)進行 MemStore 的刷寫,確保 MemStore 不會長時間沒有持久化。爲避免所有的 MemStore 在同一時間進行 flush 而導致問題,定期的 flush 操作會有一定時間的隨機延時。
  7. 手動執行 flush 操作,我們可以通過 hbase shell 或 API 對一張表或一個 Region 進行 flush。

 上面是 Flush 的幾個觸發條件,從中我們拿到 5 個和 Flush 有關的重要參數,並給出調整建議:

1、hbase.hregion.memstore.flush.size

默認值 128M,單個 MemStore 大小超過該閾值就會觸發 Flush。如果當前集羣 Flush 比較頻繁,並且內存資源比較充裕,建議適當調整爲 256M。調大的副作用可能是造成宕機時需要分裂的 HLog 數量變多,從而延長故障恢復時間。

2、hbase.hregion.memstore.block.multiplier

默認值 4,Region 中所有 MemStore 超過單個 MemStore 大小的倍數達到該參數值時,就會阻塞寫請求並強制 Flush。一般不建議調整,但對於寫入過快且內存充裕的場景,爲避免寫阻塞,可以適當調整到5~8。

3、hbase.regionserver.global.memstore.size

默認值 0.4,RegionServer 中所有 MemStore 大小總和最多佔 RegionServer 堆內存的 40%。這是寫緩存的總比例,可以根據實際場景適當調整,且要與 HBase 讀緩存參數 hfile.block.cache.size(默認也是0.4)配合調整。舊版本參數名稱爲 hbase.regionserver.global.memstore.upperLimit。

4、hbase.regionserver.global.memstore.size.lower.limit

默認值 0.95,表示 RegionServer 中所有 MemStore 大小的低水位是 hbase.regionserver.global.memstore.size 的 95%,超過該比例就會強制 Flush。一般不建議調整。舊版本參數名稱爲 hbase.regionserver.global.memstore.lowerLimit。

5、hbase.regionserver.optionalcacheflushinterval

默認值 3600000(即 1 小時),HBase 定期 Flush 所有 MemStore 的時間間隔。一般建議調大,比如 10 小時,因爲很多場景下 1 小時 Flush 一次會產生很多小文件,一方面導致 Flush 比較頻繁,另一方面導致小文件很多,影響隨機讀性能,因此建議設置較大值。

上面就是 Flush 的觸發條件及核心參數,理解並適當調整參數有利於維護 HBase 集羣的穩定性。

 

3、Compaction 類型、觸發時機和參數

      從上面分析我們知道,HBase 會定期執行 Compaction 合併 HFile,提升讀性能,其實就是以短時間內的io消耗,換取相對穩定的讀取性能。

Compaction 類型

   Compaction 分爲兩種:Minor Compaction 與 Major Compaction,可以稱爲小合併、大合併,簡單示意圖 

     Minor Compaction 是指選取一些小的、相鄰的 HFile 將他們合併成一個更大的 HFile。默認情況下,Minor Compaction 會刪除選取 HFile 中的 TTL 過期數據。

     Major Compaction 是指將一個 Store 中所有的 HFile 合併成一個 HFile,這個過程會清理三類沒有意義的數據:被刪除的數據(打了 Delete 標記的數據)、TTL 過期數據、版本號超過設定版本號的數據。另外,一般情況下,Major Compaction 時間會持續比較長,整個過程會消耗大量系統資源,對上層業務有比較大的影響。因此,生產環境下通常關閉自動觸發 Major Compaction 功能,改爲手動在業務低峯期觸發。

 

Compaction 觸發時機

       概括的說,HBase 會在三種情況下檢查是否要觸發 Compaction,分別是 MemStore Flush、後臺線程週期性檢查、手動觸發。

  1. MemStore Flush:可以說 Compaction 的根源就在於Flush,MemStore 達到一定閾值或觸發條件就會執行 Flush 操作,在磁盤上生成 HFile 文件,正是因爲 HFile 文件越來越多才需要 Compact。HBase 每次Flush 之後,都會判斷是否要進行 Compaction,一旦滿足 Minor Compaction 或 Major Compaction 的條件便會觸發執行。
  2. 後臺線程週期性檢查: 後臺線程 CompactionChecker 會定期檢查是否需要執行 Compaction,檢查週期爲 hbase.server.thread.wakefrequency * hbase.server.compactchecker.interval.multiplier,這裏主要考慮的是一段時間內沒有寫入仍然需要做 Compact 檢查。其中參數 hbase.server.thread.wakefrequency 默認值 10000 即 10s,是 HBase 服務端線程喚醒時間間隔,用於 LogRoller、MemStoreFlusher 等的週期性檢查;參數 hbase.server.compactchecker.interval.multiplier 默認值1000,是 Compaction 操作週期性檢查乘數因子,10 * 1000 s 時間上約等於2hrs, 46mins, 40sec。
  3. 手動觸發:通過 HBase Shell、Master UI 界面或 HBase API 等任一種方式執行 compact、major_compact等命令,會立即觸發 Compaction。

 

Compaction 核心參數

 

和上面類似,這裏總結了幾個和 Compaction 有關的重要參數,並給出調整建議:

1、hbase.hstore.compaction.min

默認值 3,一個 Store 中 HFile 文件數量超過該閾值就會觸發一次 Compaction(Minor Compaction),這裏稱該參數爲 minFilesToCompact。一般不建議調小,重寫場景下可以調大該參數,比如 5~10 之間,注意相應調整下一個參數。老版本參數名稱爲 hbase.hstore.compactionthreshold。

2、hbase.hstore.compaction.max

默認值 10,一次 Minor Compaction 最多合併的 HFile 文件數量,這裏稱該參數爲 maxFilesToCompact。這個參數也控制着一次壓縮的耗時。一般不建議調整,但如果上一個參數調整了,該參數也應該相應調整,一般設爲 minFilesToCompact 的 2~3 倍。

3、hbase.regionserver.thread.compaction.throttle

HBase RegionServer 內部設計了兩個線程池 large compactions 與 small compactions,用來分離處理 Compaction 操作,該參數就是控制一個 Compaction 交由哪一個線程池處理,默認值是 2 * maxFilesToCompact * hbase.hregion.memstore.flush.size(默認2*10*128M=2560M即2.5G),建議不調整或稍微調大。

4、hbase.regionserver.thread.compaction.large/small

默認值 1,表示 large compactions 與 small compactions 線程池的大小。一般建議調整到 2~5,不建議再調太大比如10,否則可能會消費過多的服務端資源造成不良影響。

5、hbase.hstore.blockingStoreFiles

默認值 10,表示一個 Store 中 HFile 文件數量達到該值就會阻塞寫入,等待 Compaction 的完成。一般建議調大點,比如設置爲 100,避免出現阻塞更新的情況,阻塞日誌如下:

too many store files; delaying flush up to 90000ms

生產環境建議認真根據實際業務量做好集羣規模評估,如果小集羣遇到了持續寫入過快的場景,合理擴展集羣也非常重要。

6、hbase.hregion.majorcompaction

默認值 604800000 ms 即7天,這是 Major Compaction 週期性觸發執行的時間間隔。通常 Major Compaction 持續時間較長、資源消耗較大,一般設爲 0,表示關閉自動觸發,建議在業務低峯期時手動執行。

   

4、總結

          實際情況需要根據具體的數據特點和讀寫特點來調整,沒有一套參數是適合所有集羣的。

 

 

 

 

 

 

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