1919
2020import java .io .IOException ;
2121import java .util .ArrayList ;
22- import java .util .Collection ;
2322import java .util .Collections ;
2423import java .util .HashMap ;
25- import java .util .HashSet ;
2624import java .util .List ;
2725import java .util .Map ;
2826import java .util .Set ;
5149
5250import org .apache .hbase .thirdparty .com .google .common .annotations .VisibleForTesting ;
5351import org .apache .hbase .thirdparty .com .google .common .collect .ArrayListMultimap ;
54- import org .apache .hbase .thirdparty .com .google .common .collect .LinkedListMultimap ;
5552import org .apache .hbase .thirdparty .com .google .common .collect .ListMultimap ;
5653import org .apache .hbase .thirdparty .com .google .common .collect .Lists ;
5754import org .apache .hbase .thirdparty .com .google .common .collect .Maps ;
@@ -81,15 +78,15 @@ public class RSGroupBasedLoadBalancer implements LoadBalancer {
8178 private LoadBalancer internalBalancer ;
8279
8380 /**
84- * Define the config key of fallback groups
85- * Enabled only if this property is set
81+ * Set this key to {@code true} to allow region fallback.
82+ * Fallback to the default rsgroup first, then fallback to any group if no online servers in
83+ * default rsgroup.
8684 * Please keep balancer switch on at the same time, which is relied on to correct misplaced
8785 * regions
8886 */
89- public static final String FALLBACK_GROUPS_KEY = "hbase.rsgroup.fallback.groups " ;
87+ public static final String FALLBACK_GROUP_ENABLE_KEY = "hbase.rsgroup.fallback.enable " ;
9088
9189 private boolean fallbackEnabled = false ;
92- private Set <String > fallbackGroups ;
9390
9491 /**
9592 * Used by reflection in {@link org.apache.hadoop.hbase.master.balancer.LoadBalancerFactory}.
@@ -180,22 +177,14 @@ public List<RegionPlan> balanceCluster(
180177 public Map <ServerName , List <RegionInfo >> roundRobinAssignment (
181178 List <RegionInfo > regions , List <ServerName > servers ) throws IOException {
182179 Map <ServerName , List <RegionInfo >> assignments = Maps .newHashMap ();
183- ListMultimap <String , RegionInfo > regionMap = ArrayListMultimap .create ();
184- ListMultimap <String , ServerName > serverMap = ArrayListMultimap .create ();
185- generateGroupMaps (regions , servers , regionMap , serverMap );
186- for (String groupKey : regionMap .keySet ()) {
187- if (regionMap .get (groupKey ).size () > 0 ) {
188- Map <ServerName , List <RegionInfo >> result = this .internalBalancer
189- .roundRobinAssignment (regionMap .get (groupKey ), serverMap .get (groupKey ));
190- if (result != null ) {
191- if (result .containsKey (LoadBalancer .BOGUS_SERVER_NAME ) &&
192- assignments .containsKey (LoadBalancer .BOGUS_SERVER_NAME )) {
193- assignments .get (LoadBalancer .BOGUS_SERVER_NAME )
194- .addAll (result .get (LoadBalancer .BOGUS_SERVER_NAME ));
195- } else {
196- assignments .putAll (result );
197- }
198- }
180+ List <Pair <List <RegionInfo >, List <ServerName >>> pairs =
181+ generateGroupAssignments (regions , servers );
182+ for (Pair <List <RegionInfo >, List <ServerName >> pair : pairs ) {
183+ Map <ServerName , List <RegionInfo >> result = this .internalBalancer
184+ .roundRobinAssignment (pair .getFirst (), pair .getSecond ());
185+ if (result != null ) {
186+ result .forEach ((server , regionInfos ) ->
187+ assignments .computeIfAbsent (server , s -> Lists .newArrayList ()).addAll (regionInfos ));
199188 }
200189 }
201190 return assignments ;
@@ -206,36 +195,16 @@ public Map<ServerName, List<RegionInfo>> retainAssignment(Map<RegionInfo, Server
206195 List <ServerName > servers ) throws HBaseIOException {
207196 try {
208197 Map <ServerName , List <RegionInfo >> assignments = new TreeMap <>();
209- ListMultimap <String , RegionInfo > groupToRegion = ArrayListMultimap .create ();
210- RSGroupInfo defaultInfo = rsGroupInfoManager .getRSGroup (RSGroupInfo .DEFAULT_GROUP );
211- for (RegionInfo region : regions .keySet ()) {
212- String groupName =
213- RSGroupUtil .getRSGroupInfo (masterServices , rsGroupInfoManager , region .getTable ())
214- .orElse (defaultInfo ).getName ();
215- groupToRegion .put (groupName , region );
216- }
217- for (String group : groupToRegion .keySet ()) {
218- Map <RegionInfo , ServerName > currentAssignmentMap = new TreeMap <RegionInfo , ServerName >();
219- List <RegionInfo > regionList = groupToRegion .get (group );
220- RSGroupInfo info = rsGroupInfoManager .getRSGroup (group );
221- List <ServerName > candidateList = filterOfflineServers (info , servers );
222- if (fallbackEnabled && candidateList .isEmpty ()) {
223- candidateList = getFallBackCandidates (servers );
224- }
225- for (RegionInfo region : regionList ) {
226- currentAssignmentMap .put (region , regions .get (region ));
227- }
228- if (candidateList .size () > 0 ) {
229- assignments
230- .putAll (this .internalBalancer .retainAssignment (currentAssignmentMap , candidateList ));
231- } else {
232- if (LOG .isDebugEnabled ()) {
233- LOG .debug ("No available servers for group {} to assign regions: {}" , group ,
234- RegionInfo .getShortNameToLog (regionList ));
235- }
236- assignments .computeIfAbsent (LoadBalancer .BOGUS_SERVER_NAME , s -> new ArrayList <>())
237- .addAll (regionList );
238- }
198+ List <Pair <List <RegionInfo >, List <ServerName >>> pairs =
199+ generateGroupAssignments (Lists .newArrayList (regions .keySet ()), servers );
200+ for (Pair <List <RegionInfo >, List <ServerName >> pair : pairs ) {
201+ List <RegionInfo > regionList = pair .getFirst ();
202+ Map <RegionInfo , ServerName > currentAssignmentMap = Maps .newTreeMap ();
203+ regionList .forEach (r -> currentAssignmentMap .put (r , regions .get (r )));
204+ Map <ServerName , List <RegionInfo >> pairResult =
205+ this .internalBalancer .retainAssignment (currentAssignmentMap , pair .getSecond ());
206+ pairResult .forEach ((server , rs ) ->
207+ assignments .computeIfAbsent (server , s -> Lists .newArrayList ()).addAll (rs ));
239208 }
240209 return assignments ;
241210 } catch (IOException e ) {
@@ -246,17 +215,17 @@ public Map<ServerName, List<RegionInfo>> retainAssignment(Map<RegionInfo, Server
246215 @ Override
247216 public ServerName randomAssignment (RegionInfo region ,
248217 List <ServerName > servers ) throws IOException {
249- ListMultimap <String ,RegionInfo > regionMap = LinkedListMultimap .create ();
250- ListMultimap <String ,ServerName > serverMap = LinkedListMultimap .create ();
251- generateGroupMaps (Lists .newArrayList (region ), servers , regionMap , serverMap );
252- List <ServerName > filteredServers = serverMap .get (regionMap .keySet ().iterator ().next ());
218+ List <Pair <List <RegionInfo >, List <ServerName >>> pairs =
219+ generateGroupAssignments (Lists .newArrayList (region ), servers );
220+ List <ServerName > filteredServers = pairs .iterator ().next ().getSecond ();
253221 return this .internalBalancer .randomAssignment (region , filteredServers );
254222 }
255223
256- private void generateGroupMaps (List <RegionInfo > regions , List <ServerName > servers ,
257- ListMultimap <String , RegionInfo > regionMap , ListMultimap <String , ServerName > serverMap )
258- throws HBaseIOException {
224+ private List <Pair <List <RegionInfo >, List <ServerName >>> generateGroupAssignments (
225+ List <RegionInfo > regions , List <ServerName > servers ) throws HBaseIOException {
259226 try {
227+ ListMultimap <String , RegionInfo > regionMap = ArrayListMultimap .create ();
228+ ListMultimap <String , ServerName > serverMap = ArrayListMultimap .create ();
260229 RSGroupInfo defaultInfo = rsGroupInfoManager .getRSGroup (RSGroupInfo .DEFAULT_GROUP );
261230 for (RegionInfo region : regions ) {
262231 String groupName =
@@ -267,15 +236,29 @@ private void generateGroupMaps(List<RegionInfo> regions, List<ServerName> server
267236 for (String groupKey : regionMap .keySet ()) {
268237 RSGroupInfo info = rsGroupInfoManager .getRSGroup (groupKey );
269238 serverMap .putAll (groupKey , filterOfflineServers (info , servers ));
270- if (fallbackEnabled && serverMap .get (groupKey ).isEmpty ()) {
271- serverMap .putAll (groupKey , getFallBackCandidates (servers ));
272- }
239+ }
240+
241+ List <Pair <List <RegionInfo >, List <ServerName >>> result = Lists .newArrayList ();
242+ List <RegionInfo > fallbackRegions = Lists .newArrayList ();
243+ for (String groupKey : regionMap .keySet ()) {
273244 if (serverMap .get (groupKey ).isEmpty ()) {
274- serverMap .put (groupKey , LoadBalancer .BOGUS_SERVER_NAME );
245+ fallbackRegions .addAll (regionMap .get (groupKey ));
246+ } else {
247+ result .add (Pair .newPair (regionMap .get (groupKey ), serverMap .get (groupKey )));
248+ }
249+ }
250+ if (!fallbackRegions .isEmpty ()) {
251+ List <ServerName > candidates = null ;
252+ if (fallbackEnabled ) {
253+ candidates = getFallBackCandidates (servers );
275254 }
255+ candidates = (candidates == null || candidates .isEmpty ()) ?
256+ Lists .newArrayList (BOGUS_SERVER_NAME ) : candidates ;
257+ result .add (Pair .newPair (fallbackRegions , candidates ));
276258 }
259+ return result ;
277260 } catch (IOException e ) {
278- throw new HBaseIOException ("Failed to generate group maps " , e );
261+ throw new HBaseIOException ("Failed to generate group assignments " , e );
279262 }
280263 }
281264
@@ -390,11 +373,7 @@ public void initialize() throws IOException {
390373 }
391374 internalBalancer .initialize ();
392375 // init fallback groups
393- Collection <String > groups = config .getTrimmedStringCollection (FALLBACK_GROUPS_KEY );
394- if (groups != null && !groups .isEmpty ()) {
395- this .fallbackEnabled = true ;
396- this .fallbackGroups = new HashSet <>(groups );
397- }
376+ this .fallbackEnabled = config .getBoolean (FALLBACK_GROUP_ENABLE_KEY , false );
398377 }
399378
400379 public boolean isOnline () {
@@ -485,15 +464,13 @@ public List<RegionPlan> balanceTable(TableName tableName,
485464 }
486465
487466 private List <ServerName > getFallBackCandidates (List <ServerName > servers ) {
488- List <ServerName > serverNames = new ArrayList <>();
489- for (String fallbackGroup : fallbackGroups ) {
490- try {
491- RSGroupInfo info = rsGroupInfoManager .getRSGroup (fallbackGroup );
492- serverNames .addAll (filterOfflineServers (info , servers ));
493- } catch (IOException e ) {
494- LOG .error ("Get group info for {} failed" , fallbackGroup , e );
495- }
467+ List <ServerName > serverNames = null ;
468+ try {
469+ RSGroupInfo info = rsGroupInfoManager .getRSGroup (RSGroupInfo .DEFAULT_GROUP );
470+ serverNames = filterOfflineServers (info , servers );
471+ } catch (IOException e ) {
472+ LOG .error ("Failed to get default rsgroup info to fallback" , e );
496473 }
497- return serverNames ;
474+ return serverNames == null || serverNames . isEmpty () ? servers : serverNames ;
498475 }
499476}
0 commit comments