Skip to content

Commit 99f0c2c

Browse files
author
Ray Mattingly
committed
HBASE-28513 The StochasticLoadBalancer should support discrete evaluations
1 parent 7770103 commit 99f0c2c

20 files changed

+1937
-30
lines changed

hbase-balancer/src/main/java/org/apache/hadoop/hbase/master/balancer/BalanceAction.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ enum Type {
2828
ASSIGN_REGION,
2929
MOVE_REGION,
3030
SWAP_REGIONS,
31+
MOVE_BATCH,
3132
NULL,
3233
}
3334

@@ -51,6 +52,10 @@ Type getType() {
5152
return type;
5253
}
5354

55+
long getStepCount() {
56+
return 1;
57+
}
58+
5459
@Override
5560
public String toString() {
5661
return type + ":";

hbase-balancer/src/main/java/org/apache/hadoop/hbase/master/balancer/BalancerClusterState.java

Lines changed: 121 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,19 +26,26 @@
2626
import java.util.HashMap;
2727
import java.util.List;
2828
import java.util.Map;
29+
import java.util.Set;
30+
import java.util.concurrent.TimeUnit;
2931
import org.agrona.collections.Hashing;
3032
import org.agrona.collections.Int2IntCounterMap;
3133
import org.apache.hadoop.hbase.HDFSBlocksDistribution;
3234
import org.apache.hadoop.hbase.ServerName;
3335
import org.apache.hadoop.hbase.client.RegionInfo;
3436
import org.apache.hadoop.hbase.client.RegionReplicaUtil;
3537
import org.apache.hadoop.hbase.master.RackManager;
38+
import org.apache.hadoop.hbase.master.RegionPlan;
3639
import org.apache.hadoop.hbase.net.Address;
3740
import org.apache.hadoop.hbase.util.Pair;
3841
import org.apache.yetus.audience.InterfaceAudience;
3942
import org.slf4j.Logger;
4043
import org.slf4j.LoggerFactory;
4144

45+
import org.apache.hbase.thirdparty.com.google.common.base.Supplier;
46+
import org.apache.hbase.thirdparty.com.google.common.base.Suppliers;
47+
import org.apache.hbase.thirdparty.com.google.common.collect.ImmutableList;
48+
4249
/**
4350
* An efficient array based implementation similar to ClusterState for keeping the status of the
4451
* cluster in terms of region assignment and distribution. LoadBalancers, such as
@@ -123,6 +130,14 @@ class BalancerClusterState {
123130
// Maps regionName -> oldServerName -> cache ratio of the region on the old server
124131
Map<String, Pair<ServerName, Float>> regionCacheRatioOnOldServerMap;
125132

133+
private Supplier<List<Integer>> shuffledServerIndicesSupplier =
134+
Suppliers.memoizeWithExpiration(() -> {
135+
Collection<Integer> serverIndices = serversToIndex.values();
136+
List<Integer> shuffledServerIndices = new ArrayList<>(serverIndices);
137+
Collections.shuffle(shuffledServerIndices);
138+
return shuffledServerIndices;
139+
}, 5, TimeUnit.SECONDS);
140+
126141
static class DefaultRackManager extends RackManager {
127142
@Override
128143
public String getRack(ServerName server) {
@@ -711,6 +726,44 @@ enum LocalityType {
711726
RACK
712727
}
713728

729+
public List<RegionPlan> convertActionToPlans(BalanceAction action) {
730+
switch (action.getType()) {
731+
case NULL:
732+
break;
733+
case ASSIGN_REGION:
734+
// FindBugs: Having the assert quietens FB BC_UNCONFIRMED_CAST warnings
735+
assert action instanceof AssignRegionAction : action.getClass();
736+
AssignRegionAction ar = (AssignRegionAction) action;
737+
return ImmutableList
738+
.of(new RegionPlan(regions[ar.getRegion()], null, servers[ar.getServer()]));
739+
case MOVE_REGION:
740+
assert action instanceof MoveRegionAction : action.getClass();
741+
MoveRegionAction mra = (MoveRegionAction) action;
742+
return ImmutableList.of(new RegionPlan(regions[mra.getRegion()],
743+
servers[mra.getFromServer()], servers[mra.getToServer()]));
744+
case SWAP_REGIONS:
745+
assert action instanceof SwapRegionsAction : action.getClass();
746+
SwapRegionsAction a = (SwapRegionsAction) action;
747+
return ImmutableList.of(
748+
new RegionPlan(regions[a.getFromRegion()], servers[a.getFromServer()],
749+
servers[a.getToServer()]),
750+
new RegionPlan(regions[a.getToRegion()], servers[a.getToServer()],
751+
servers[a.getFromServer()]));
752+
case MOVE_BATCH:
753+
assert action instanceof MoveBatchAction : action.getClass();
754+
MoveBatchAction mba = (MoveBatchAction) action;
755+
List<RegionPlan> mbRegionPlans = new ArrayList<>();
756+
for (MoveRegionAction moveRegionAction : mba.getMoveActions()) {
757+
mbRegionPlans.add(new RegionPlan(regions[moveRegionAction.getRegion()],
758+
servers[moveRegionAction.getFromServer()], servers[moveRegionAction.getToServer()]));
759+
}
760+
return mbRegionPlans;
761+
default:
762+
throw new RuntimeException("Unknown action:" + action.getType());
763+
}
764+
return Collections.emptyList();
765+
}
766+
714767
public void doAction(BalanceAction action) {
715768
switch (action.getType()) {
716769
case NULL:
@@ -742,8 +795,25 @@ public void doAction(BalanceAction action) {
742795
regionMoved(a.getFromRegion(), a.getFromServer(), a.getToServer());
743796
regionMoved(a.getToRegion(), a.getToServer(), a.getFromServer());
744797
break;
798+
case MOVE_BATCH:
799+
assert action instanceof MoveBatchAction : action.getClass();
800+
MoveBatchAction mba = (MoveBatchAction) action;
801+
for (int serverIndex : mba.getServerToRegionsToRemove().keySet()) {
802+
Set<Integer> regionsToRemove = mba.getServerToRegionsToRemove().get(serverIndex);
803+
regionsPerServer[serverIndex] =
804+
removeRegions(regionsPerServer[serverIndex], regionsToRemove);
805+
}
806+
for (int serverIndex : mba.getServerToRegionsToAdd().keySet()) {
807+
Set<Integer> regionsToAdd = mba.getServerToRegionsToAdd().get(serverIndex);
808+
regionsPerServer[serverIndex] = addRegions(regionsPerServer[serverIndex], regionsToAdd);
809+
}
810+
for (MoveRegionAction moveRegionAction : mba.getMoveActions()) {
811+
regionMoved(moveRegionAction.getRegion(), moveRegionAction.getFromServer(),
812+
moveRegionAction.getToServer());
813+
}
814+
break;
745815
default:
746-
throw new RuntimeException("Uknown action:" + action.getType());
816+
throw new RuntimeException("Unknown action:" + action.getType());
747817
}
748818
}
749819

@@ -905,6 +975,52 @@ int[] addRegion(int[] regions, int regionIndex) {
905975
return newRegions;
906976
}
907977

978+
int[] removeRegions(int[] regions, Set<Integer> regionIndicesToRemove) {
979+
// Calculate the size of the new regions array
980+
int newSize = regions.length - regionIndicesToRemove.size();
981+
if (newSize < 0) {
982+
throw new IllegalStateException(
983+
"Region indices mismatch: more regions to remove than in the regions array");
984+
}
985+
986+
int[] newRegions = new int[newSize];
987+
int newIndex = 0;
988+
989+
// Copy only the regions not in the removal set
990+
for (int region : regions) {
991+
if (!regionIndicesToRemove.contains(region)) {
992+
newRegions[newIndex++] = region;
993+
}
994+
}
995+
996+
// If the newIndex is smaller than newSize, some regions were missing from the input array
997+
if (newIndex != newSize) {
998+
throw new IllegalStateException("Region indices mismatch: some regions in the removal "
999+
+ "set were not found in the regions array");
1000+
}
1001+
1002+
return newRegions;
1003+
}
1004+
1005+
int[] addRegions(int[] regions, Set<Integer> regionIndicesToAdd) {
1006+
int[] newRegions = new int[regions.length + regionIndicesToAdd.size()];
1007+
1008+
// Copy the existing regions to the new array
1009+
System.arraycopy(regions, 0, newRegions, 0, regions.length);
1010+
1011+
// Add the new regions at the end of the array
1012+
int newIndex = regions.length;
1013+
for (int regionIndex : regionIndicesToAdd) {
1014+
newRegions[newIndex++] = regionIndex;
1015+
}
1016+
1017+
return newRegions;
1018+
}
1019+
1020+
List<Integer> getShuffledServerIndices() {
1021+
return shuffledServerIndicesSupplier.get();
1022+
}
1023+
9081024
int[] addRegionSorted(int[] regions, int regionIndex) {
9091025
int[] newRegions = new int[regions.length + 1];
9101026
int i = 0;
@@ -1004,6 +1120,10 @@ void setNumMovedRegions(int numMovedRegions) {
10041120
this.numMovedRegions = numMovedRegions;
10051121
}
10061122

1123+
public int getMaxReplicas() {
1124+
return maxReplicas;
1125+
}
1126+
10071127
@Override
10081128
public String toString() {
10091129
StringBuilder desc = new StringBuilder("Cluster={servers=[");

0 commit comments

Comments
 (0)