在 Region 分配過程當中,起着重要做用有以下一些對象。安全
這些對象的關係如圖所示:負載均衡
HMaster 起動時,首先會經過 RegionManager 把 rootRegionLocation (裏面包含 HServerAddress )的值置爲null ,而後把 root region 從待處理 region 列表中移除(若是有的話),而後從新將其放入待處理 region 列表(regionsInTransition ),並將其狀態設置爲 UNASSIGNED( 未分配 ).函數
當一個 Region server 啓動完成時,它會調用 reportForDuty 函數向 HMaster 報告它的啓動,報告固然是經過HMasterRegionInterface 的 regionServerStartup 方法。而後 HMaster 會把 Region server 的報告轉交給ServerManager 的 regionServerStartup 方法處理。 ServerManager 會將這個新的 RegionServer 加入 region server 列表而且把它的 server load 設爲空閒的。線程
RegionServer 會按期發送報告給 HMaster ,請求 HMaster 進一步的指示。發送報告是經過HMasterRegionInterface 的 regionServerReport 方法。 HMaster 接到報告後,移交報告給 ServerManager 的regionServerReport 方法處理。 ServerManager 會查詢server
regionServer 的狀態,獲得一個 HServerInfo 對像,而後檢查 RegionServer 是否爲正常的。若是爲正常的話,ServerManager 會查詢 regionserver 的負載( HServerLoad ),更新一個 loadToServers 的 map 。而後進入ServerManager 的 processMsgs 函數處理。對象
ServerManager 會檢查該 regionServer 的已經打開的 region 的數目,若是打開的 region 數目少於一個固定的值(對應配置文件中的 hbase.regions.nobalancing.count ),而後就會調用 RegionManager 的 assignRegions 方法。ip
RegionManager 會向 ServerManager 查詢,如今已啓動的 RegionServer 有幾個,若是隻有一個的話,會作特別處理。ci
而後 RegionManager 調用本身的 regionsAwaitingAssignment 方法去取得等待分配的 region 集合。它先會特別考慮 root region ,若是它查到 root region 還沒有被分配,它會立刻返回只包含 root region 的集合。it
若是沒有任何 region 未分配的話並且並未處在安全模式, RegionManager 會讓 loadBalancer 執行負載均衡的動做(就是可能把該 regionserver 負責的 region 分一點出去)。 反之若是有待分配的 region ,serverManager 會調用本身的 assignRegionsToMultipleServers方法。io
在 assignRegionsToMultipleServers 中,參數 regionsToAssign 是全部待分配的 region 集合,由於存在多個regionServer, 因此 regionManager 會考慮到多個 regionServer 的負載。 regionManager 會先調用regionsToGiveOtherServers 方法,求出其餘 regionServer (好比相對負載較輕的)應該承載的 region 數目,那麼當前 regionServer 可能承載的 region 個數就是待分配的 region 總數目減去其餘 regionServer 應該承載的region 數目,這個數量咱們暫稱之爲 N 。若是 N<=0 而且 Meta Region 若是已被分配的話,該 regionServer 會被略過,不會被要求承載 region 。由於比當前 regionServer 的負載輕的 regionServer 個數超過了待分配的region 個數,輪不到當前的 regionServer 。
看起來快水落石出了,可是剩下事情還有點複雜。 regionManager 還會調用 computeNextHeaviestLoad 方法,算出 cluster 中有多少 regionServer 負載超過當前的 regionServer ,這個數目咱們暫稱之爲 NS ,同時該方法會抓出負載最重的 server 的負載。
接着 regionManager 會求出當前 regionServer 負責的 region 數目和負載最重的 regionServer 負責的 region 數目之間的差值。若是這個差值大於 N ,那麼 N 個 region 將所有會交由當前 regionServer 負責。反之這個差值小於N,若是 NS 大於零,當前 regionServer 要被分配的 region 數量爲 (int)Math.ceil(1.0*N/1.0*NS), 若是 NS 等於零,那麼當前 regionServer 要被分配 region 的數量爲 (int)Math.ceil(1.0*N/1.0*regionServer 總數 ) 。
而後 root region 就會被分配到該 RegionServer 上。
這裏特別要提下:若是有多個 region serve 存在, HBase 不會把 root region 和 meta region 分配到一個RegionServer 上。
一旦 root region 被分配完成, RootScanner 線程將被喚醒。而後它會 scan root region 。
在 scan 過程當中,碰到每一個 meta region 條目,它會調用 checkAssigned 函數檢查,該 meta region 是否被分配,若是沒有的話, regionManager 將會記錄之,把該 region 加入待分配的 region 列表中。
一旦有 RegionServer 按期報告來了, meta region 會像 root region 同樣的方式被分配。
一旦 meta region 被分配完成, MetaScanner 將被喚醒,而後它會 scan meta region 。
在 scan 過程當中,碰到每一個 user region 條目,它會調用 checkAssigned 函數檢查,該 user region 是否被分配,若是沒有的話, regionManager 將會記錄之,把該 region 加入待分配的 region 列表中。
一旦有 RegionServer 按期報告來了, user region 會被分配。