「從零單排HBase 05」核心特性region split

  • 2020 年 3 月 13 日
  • 筆記

HBase擁有出色的擴展性,其中最依賴的就是region的自動split機制。

1.split觸發時機與策略

前面我們已經知道了,數據寫入過程中,需要先寫memstore,然後memstore滿了以後,flush寫入磁盤,形成新的HFile文件。

當HFile文件數量不斷累積,Region server就會觸發compaction機制,把小文件合併為大的HFIle。

當每次flush完成 或者 compaction完成後,regionSplitPolicy就會判斷是否需要進行split。

split觸發時機簡單來說,就是看一個region裏面的最大store是否超過閾值。

 

當然,hbase支持多種策略來設置這個閾值到底怎麼計算,這就是觸發策略。

  • 0.94版本前默認的策略是ConstantSizeRegionSplitPolicy,這個閾值時一個固定值。
  • 0.94-2.0版本的默認策略是IncreasingToUpperBoundRegionSplitPolicy。
  • 2.0版本的默認策略是SteppingSplitPolicy。這兩種策略設置的閾值不是一個固定值,而是會和region所屬表在當前regionserver上的region個數有關。只是在計算公式上稍有差異。

另外,還有比如DisableSplitPolicy、KeyPrefixRegionSplitPolicy,DelimitedKeyPrefixRegionSplitPolicy等策略,就不一一介紹了。

2.split流程

一旦開始region split,那麼就會創建兩個daughter region。

這時候不會立刻將所有數據寫到新的region裏面去,而是創建引用文件,叫做Reference files,指向parent region。

reference文件作為一個數據規則文件,在split期間,新的查詢會根據這個文件去父region的HStore上查詢數據。當經過一次major compaction後,數據遷移到新的region中,reference文件會被刪除,表示spilit真正完成。

 

「從零單排HBase 05」核心特性region split

 

具體過程如下:

1)regionserver在zookeeper中創建一個新的znode在/hbase/region-in-transition/region-name目錄下,狀態為SPLITTING

2)master通過watch zk上的region-in-transition目錄,得知這個region處於split狀態

3)region server在HDFS的parent region目錄下創建一個子目錄叫做“.splits”

4)region server關閉parent region,強制flush這個region下的cache數據,並且標記這個region為下線狀態。這個時候,如果有客戶端請求落在這個region上,就會拋出NotServingRegionException。

5)Region server創建新的region在.spllits目錄下,我們標記為daughter region A和daughter region B,同時創建必要的數據結構。然後就會創建兩個Reference文件,指向parent region的那些存儲文件。

6)Region Server在HDFS中創建實際的region目錄,並將daughterA和daughter B移動到HBase根目錄下,形成兩個新的region。

7)Region server會發送put請求給.mete. table,然後把parent region設置為offline的狀態,並且給新的region添加信息。

8)region server 打開新的region接受讀寫請求

9)region server將region A和B的信息添加到.meta.表,可以真正對外提供服務了。

 

掃尾工作:

1)客戶端請求.meta.表,發現新的region信息,就會把本地緩存重新設置

2)region server更新zk上/hbase/region-in-transition/region-name目錄下的znode狀態,改為SPLIT,然後master通過watch得知這個信息。如果有必要,負載均衡器可以選擇將新的region分佈到新的region server上。

3)完成split工作後,meta和HDFS還是會保留reference文件到parent region。等到下次compaction時,會完成數據到新region的遷移,然後才會刪除reference文件。

 

3.pre-splitting

當一張表被首次創建時,只會分配一個region給這個表。因此,在剛剛開始時,所有讀寫請求都會落在這個region所在的region server上,而不管你整個集群有多少個region server。不能充分地利用集群的分佈式特性。

主要原因跟split的機制有關,一開始的時候,系統無法判斷你到底需要用哪個rowkey進行split。

因此,hbase提供了工具讓你能自己解決這個問題,叫做pre-splitting。

你可以在創建表的時候,指定哪些split point將region分成幾份。如果切分的好,那麼自然就可以一開始就充分利用分佈式的特性。但是需要注意,如果切分的不好,存在熱點region,那麼反而會影響讀寫性能。

這裡也沒有一個特別好的原則來說到底pre split多少個region最合適,不過最好的方式,還是以region server數量的倍數(較小的倍數)來創建pre split的region數量,然後讓集群本身去做自動的spliting。

 

4.split的事務性保證

2.0版本後,HBase會使用HLog存儲單機事務(DDLSplitMove等)的中間狀態,保證了即使事務過程中出現異常,也能安全地回滾或繼續提交。

 

看到這裡了,原創不易,點個關注、點個贊吧,你最好看了~

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

掃碼關注我的公眾號“阿丸筆記”,第一時間獲取最新更新。同時可以免費獲取海量Java技術棧電子書、各個大廠面試題。

阿丸筆記