hbase中balance機制


          HBase是一種支持自動負載均衡的分布式KV數據庫,在開啟balance的開關(balance_switch)后,HBase的HMaster進程會自動根據指定策略挑選出一些Region,並將這些Region分配給負載比較低的RegionServer上。官方目前支持兩種挑選Region的策略,一種叫做DefaultLoadBalancer,另一種叫做StochasticLoadBalancer,這兩種策略后面會具體講到。由於HBase的所有數據(包括HLog/Meta/HStoreFile等)都是寫入到HDFS文件系統中的, 因此HBase的Region移動其實非常輕量級。在做Region移動的時候,保持這個Region對應的HDFS文件位置不變,只需要將Region的Meta數據分配到相關的RegionServer即可,整個Region移動的過程取決於RegionClose以及RegionOpen的耗時,這個時間一般都很短。

本文來講講hbase的balance實現。

balance的流程

  • 首先通過LoadBalancer找出所有需要移動的region plan,一個region plan包括region/原始RegionServer/目的RegionServer三個屬性
  • unassign region , 將region從原來的RegionServer上解除綁定;
  • assign region ,將region綁定到目標RegionServer上;

     其中, unassign region的具體流程為:

  • create zk closing node . 該節點在/unassigned路徑下, 包含(znode狀態,region名字,原始RS名,payload)這些數據。
  • hmaster 調用rpc服務關閉region server。region-close的流程大致為先獲取region的writeLock , 然后flush memstore, 再並發關閉該region下的所有的store file文件(注意一個region有多個store,每個store又有多個store file , 所以可以實現並發close store file) 。最后釋放region的writeLock.
  • 設置zk closing node的znode狀態為closed.

assgin region的具體流程為:

  • 獲取到對應的Region Plan.
  • HMaster調用rpc服務去Region Plan對應的RegionServer上open region. 這里會先更新/unassigned節點為opening. 然后並發Load HStore,再更行zk/ROOT/META表信息,這里是為了client下次能獲取到正確的路由信息, 最后更新region狀態為OPEN.

DefaultLoadBalancer策略

這種策略能夠保證每個RS的regions個數基本上都相等,確切來說,假設一共有n個RS,第i個RS有Ai個region,記average=sigma(Ai)/n , 那么這種策略能夠保證所有的RS的region個數都在[floor(average), ceil(average)]之間。這種策略的實現簡單,應用廣泛。

但是,這種策略考慮的因素比較單一, 沒有考慮到每台region server的讀寫qps/負載壓力等等,這樣就可能導致出現一種情況:雖然每個region server的regions都非常接近,但是90%的請求還是落在了一台RS上,因為這台RS上的region全部都是熱點數據,這樣還是沒有達到負載均衡的目的。 但我覺得balance的首要目的是保證數據均衡,如果在數據均衡的情況下,負載還是集中,這時候就要考慮下rowKey的選擇是否有問題了。因此, 我個人還是比較推薦采用DefaultLoadBalancer的。

StochasticLoadBalancer策略

StochasticLoadBalancer 這種策略真的是非常復雜,簡單來講,是一種綜合權衡一下6個因素的均衡策略:

  • 每台服務器讀請求數(ReadRequestCostFunction)
  • 每台服務器寫請求數(WriteRequestCostFunction)
  • Region個數(RegionCountSkewCostFunction)
  • 移動代價(MoveCostFunction)
  • 數據locality(TableSkewCostFunction)
  • 每張表占據RegionServer中region個數上限(LocalityCostFunction)

對於cluster的每一種region分布, 采用6個因素加權的方式算出一個代價值,這個代價值就用來評估當前region分布是否均衡,越均衡代價值越低。然后通過成千上萬次隨機迭代來找到一組RegionMove的序列,使得最終的代價值嚴格遞減。 得到的這一組RegionMove就是HMaster最終執行的region遷移方案。

這里用一段偽代碼來描述這個迭代的過程:

currentCost = MAX ; 
plans  = []
for(step = 0 ; step < 1000000; step ++ ){
    action = cluster.generateMove() 
    doAction( action );
    newCost  = computeCost(action) ;
    if (newCost < currentCost){
        currentCost = newCost;
    }else{
        undoAction(action);
    }
    plans.add( action )
}

 

  其中generateMove()每次隨機選擇以下3種策略之一來生成RegionMove:

  1. 隨機選擇兩個RS, 從每個RS中隨機選擇兩個Region,然后生成一個Action, 這個Action有一半概率做RegionMove(從Region多的RS遷移到Region少的RS), 另一半概率做RegionSwap。
  2. 選擇Region最多的RS和Region最少的RS,然后生成一個Action, 這個Action一半概率做RegionMove, 一半概率做RegionSwap。
  3. 隨機找一個RS,然后找到該RS上數據locality最差的Region,然后找到Region大部分數據落在的RS,然后生成一個Action,該Action用來把Region遷移到它應該所在的RS,用來提高locality.

  對於這種策略,JavaDoc上說效果比較好,但其中的合理性個人覺得有待測試數據的證明(官方基本沒有給出這方面的測試結果)。如果6個因素每個參數占據的權重如果沒有調好的話,會導致線上的Region大量不均衡。按照我的一次線上經歷,采用如下blance配置,出現過每次balance都只選擇60個左右的plan去移動, 但真實的情況是145個RS,其中region數量最多的有700+個, 最少的region數量有2個,然后其他RS的region數量在2~700不等,這時候按理來講應該需要進行大量的balance,但HMaster每隔一個period只生成60個plan左右去移動,這樣balance太慢導致很長一段時間內負載不均,有的RS非常清閑,有的RS非常繁忙經常超時。

hbase.master.loadbalancer.class=\
    org.apache.hadoop.hbase.master.StochasticLoadBalancer
hbase.master.balancer.stochastic.regionCountCost=10
hbase.master.balancer.stochastic.tableSkewCost=5
hbase.master.balancer.stochastic.readRequestCost=5
hbase.master.balancer.stochastic.writeRequestCost=5
hbase.master.balancer.stochastic.localityCost=10
hbase.master.balancer.stochastic.moveCost=4
hbase.master.balancer.stochastic.maxMovePercent=1

后面對比了下了官方的默認配置,應該是regionCountCost一項權重太低, 但是,我想說的是除非線下有一個測試結果支撐具體的權重配置下 balance是符合預期的,否則線上操作時一般對權重很難有一個准確的把握,所以像這么復雜的策略還是要比較謹慎的選擇,最好有過歷史測試數據來評估balance的效果。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM