參與 Region 分配的重要對象
在 Region 分配過程中,起着重要作用有如下一些對象。
- HMaster— 是 HBase 中的 Master server ,僅有一個。
- HRegionServer--- 負責多個 HRegion 使之能向 client 端提供服務,在 HBase cluster 中存在多個HRegionServer 。
- ServerManager--- 負責管理 Region server 信息,比如每個 Region server 的 HServerInfo( 這個對象包含HServerAddress 和 startCode), 已 load Region 個數,死亡的 Region server 列表
- RegionManager --- 負責將 region 分配到 region server 的具體工作,還有監視 root 和 meta 這 2 個特殊 region的狀態。
- RootScanner --- 定期掃描 root region ,以發現沒有分配的 meta region 。
- MetaScanner--- 定期掃描 meta region, 以發現沒有分配的 user region 。
這些對象的關系如圖所示:
Region 分配過程
- Root 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 會查詢
regionServer 的狀態,得到一個 HServerInfo 對像,然后檢查 RegionServer 是否為正常的。如果為正常的話,ServerManager 會查詢 regionserver 的負載( HServerLoad ),更新一個 loadToServers 的 map 。然后進入ServerManager 的 processMsgs 函數處理。
ServerManager 會檢查該 regionServer 的已經打開的 region 的數目,如果打開的 region 數目少於一個固定的值(對應配置文件中的 hbase.regions.nobalancing.count ),然后就會調用 RegionManager 的 assignRegions 方法。
RegionManager 會向 ServerManager 查詢,現在已啟動的 RegionServer 有幾個,如果只有一個的話,會做特別處理。
然后 RegionManager 調用自己的 regionsAwaitingAssignment 方法去取得等待分配的 region 集合。它先會特別考慮 root region ,如果它查到 root region 尚未被分配,它會馬上返回只包含 root region 的集合。
如果沒有任何 region 未分配的話而且並未處在安全模式, RegionManager 會讓 loadBalancer 執行負載均衡的動作(就是可能把該 regionserver 負責的 region 分一點出去)。 反之如果有待分配的 region ,serverManager 會調用自己的 assignRegionsToMultipleServers方法。
在 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 上。
- Meta region 的分配
一旦 root region 被分配完成, RootScanner 線程將被喚醒。然后它會 scan root region 。
在 scan 過程中,碰到每個 meta region 條目,它會調用 checkAssigned 函數檢查,該 meta region 是否被分配,如果沒有的話, regionManager 將會記錄之,把該 region 加入待分配的 region 列表中。
一旦有 RegionServer 定期報告來了, meta region 會像 root region 一樣的方式被分配。
- User region 的分配
一旦 meta region 被分配完成, MetaScanner 將被喚醒,然后它會 scan meta region 。
在 scan 過程中,碰到每個 user region 條目,它會調用 checkAssigned 函數檢查,該 user region 是否被分配,如果沒有的話, regionManager 將會記錄之,把該 region 加入待分配的 region 列表中。
一旦有 RegionServer 定期報告來了, user region 會被分配。
