Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@
import org.apache.hadoop.hbase.master.balancer.BalancerChore;
import org.apache.hadoop.hbase.master.balancer.ClusterStatusChore;
import org.apache.hadoop.hbase.master.balancer.LoadBalancerFactory;
import org.apache.hadoop.hbase.master.balancer.MaintenanceLoadBalancer;
import org.apache.hadoop.hbase.master.cleaner.DirScanPool;
import org.apache.hadoop.hbase.master.cleaner.HFileCleaner;
import org.apache.hadoop.hbase.master.cleaner.LogCleaner;
Expand Down Expand Up @@ -678,7 +679,13 @@ public MetricsMaster getMasterMetrics() {
* should have already been initialized along with {@link ServerManager}.
*/
private void initializeZKBasedSystemTrackers()
throws IOException, KeeperException, ReplicationException {
throws IOException, KeeperException, ReplicationException {
if (maintenanceMode) {
// in maintenance mode, always use MaintenanceLoadBalancer.
conf.unset(LoadBalancer.HBASE_RSGROUP_LOADBALANCER_CLASS);
conf.setClass(HConstants.HBASE_MASTER_LOADBALANCER_CLASS, MaintenanceLoadBalancer.class,
LoadBalancer.class);
}
this.balancer = new RSGroupBasedLoadBalancer();
this.balancer.setConf(conf);
this.loadBalancerTracker = new LoadBalancerTracker(zooKeeper, this);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import java.util.Random;
import java.util.Set;
import java.util.TreeMap;
import java.util.concurrent.ThreadLocalRandom;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import org.apache.commons.lang3.NotImplementedException;
Expand Down Expand Up @@ -1027,7 +1028,6 @@ public String toString() {
protected float overallSlop;
protected Configuration config = HBaseConfiguration.create();
protected RackManager rackManager;
private static final Random RANDOM = new Random(System.currentTimeMillis());
private static final Logger LOG = LoggerFactory.getLogger(BaseLoadBalancer.class);
protected MetricsBalancer metricsBalancer = null;
protected ClusterMetrics clusterStatus = null;
Expand All @@ -1041,17 +1041,21 @@ public String toString() {
@Deprecated
protected boolean onlySystemTablesOnMaster;

protected boolean maintenanceMode;

@Override
public void setConf(Configuration conf) {
this.config = conf;
setSlop(conf);
if (slop < 0) slop = 0;
else if (slop > 1) slop = 1;
if (slop < 0) {
slop = 0;
} else if (slop > 1) {
slop = 1;
}

if (overallSlop < 0) overallSlop = 0;
else if (overallSlop > 1) overallSlop = 1;
if (overallSlop < 0) {
overallSlop = 0;
} else if (overallSlop > 1) {
overallSlop = 1;
}

this.onlySystemTablesOnMaster = LoadBalancer.isSystemTablesOnlyOnMaster(this.config);

Expand All @@ -1061,8 +1065,7 @@ public void setConf(Configuration conf) {
}
this.isByTable = conf.getBoolean(HConstants.HBASE_MASTER_LOADBALANCE_BYTABLE, isByTable);
// Print out base configs. Don't print overallSlop since it for simple balancer exclusively.
LOG.info("slop={}, systemTablesOnMaster={}",
this.slop, this.onlySystemTablesOnMaster);
LOG.info("slop={}, systemTablesOnMaster={}", this.slop, this.onlySystemTablesOnMaster);
}

protected void setSlop(Configuration conf) {
Expand All @@ -1079,8 +1082,7 @@ protected void setSlop(Configuration conf) {
*/
@Deprecated
public boolean shouldBeOnMaster(RegionInfo region) {
return (this.maintenanceMode || this.onlySystemTablesOnMaster)
&& region.getTable().isSystemTable();
return this.onlySystemTablesOnMaster && region.getTable().isSystemTable();
}

/**
Expand Down Expand Up @@ -1147,7 +1149,7 @@ protected List<RegionPlan> balanceMasterRegions(Map<ServerName, List<RegionInfo>
protected Map<ServerName, List<RegionInfo>> assignMasterSystemRegions(
Collection<RegionInfo> regions, List<ServerName> servers) {
Map<ServerName, List<RegionInfo>> assignments = new TreeMap<>();
if (this.maintenanceMode || this.onlySystemTablesOnMaster) {
if (this.onlySystemTablesOnMaster) {
if (masterServerName != null && servers.contains(masterServerName)) {
assignments.put(masterServerName, new ArrayList<>());
for (RegionInfo region : regions) {
Expand Down Expand Up @@ -1181,9 +1183,6 @@ public void setMasterServices(MasterServices masterServices) {
if (useRegionFinder) {
this.regionFinder.setClusterInfoProvider(new MasterClusterInfoProvider(services));
}
if (this.services.isInMaintenanceMode()) {
this.maintenanceMode = true;
}
}

@Override
Expand Down Expand Up @@ -1298,7 +1297,7 @@ public Map<ServerName, List<RegionInfo>> roundRobinAssignment(List<RegionInfo> r
/**
* only need assign system table
*/
if (this.maintenanceMode || regions.isEmpty()) {
if (regions.isEmpty()) {
return assignments;
}

Expand Down Expand Up @@ -1438,7 +1437,7 @@ public Map<ServerName, List<RegionInfo>> retainAssignment(Map<RegionInfo, Server
regions = regions.entrySet().stream().filter(e -> !masterRegions.contains(e.getKey()))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
}
if (this.maintenanceMode || regions.isEmpty()) {
if (regions.isEmpty()) {
return assignments;
}

Expand Down Expand Up @@ -1585,8 +1584,9 @@ private ServerName randomAssignment(Cluster cluster, RegionInfo regionInfo,
final int maxIterations = numServers * 4;
int iterations = 0;
List<ServerName> usedSNs = new ArrayList<>(servers.size());
Random rand = ThreadLocalRandom.current();
do {
int i = RANDOM.nextInt(numServers);
int i = rand.nextInt(numServers);
sn = servers.get(i);
if (!usedSNs.contains(sn)) {
usedSNs.add(sn);
Expand Down Expand Up @@ -1616,13 +1616,14 @@ private ServerName randomAssignment(Cluster cluster, RegionInfo regionInfo,
*/
private void roundRobinAssignment(Cluster cluster, List<RegionInfo> regions,
List<ServerName> servers, Map<ServerName, List<RegionInfo>> assignments) {
Random rand = ThreadLocalRandom.current();
List<RegionInfo> unassignedRegions = new ArrayList<>();
int numServers = servers.size();
int numRegions = regions.size();
int max = (int) Math.ceil((float) numRegions / numServers);
int serverIdx = 0;
if (numServers > 1) {
serverIdx = RANDOM.nextInt(numServers);
serverIdx = rand.nextInt(numServers);
}
int regionIdx = 0;
for (int j = 0; j < numServers; j++) {
Expand All @@ -1644,17 +1645,17 @@ private void roundRobinAssignment(Cluster cluster, List<RegionInfo> regions,

List<RegionInfo> lastFewRegions = new ArrayList<>();
// assign the remaining by going through the list and try to assign to servers one-by-one
serverIdx = RANDOM.nextInt(numServers);
OUTER : for (RegionInfo region : unassignedRegions) {
serverIdx = rand.nextInt(numServers);
for (RegionInfo region : unassignedRegions) {
boolean assigned = false;
INNER : for (int j = 0; j < numServers; j++) { // try all servers one by one
for (int j = 0; j < numServers; j++) { // try all servers one by one
ServerName server = servers.get((j + serverIdx) % numServers);
if (cluster.wouldLowerAvailability(region, server)) {
continue INNER;
continue;
} else {
assignments.computeIfAbsent(server, k -> new ArrayList<>()).add(region);
cluster.doAssignRegion(region, server);
serverIdx = (j + serverIdx + 1) % numServers; //remain from next server
serverIdx = (j + serverIdx + 1) % numServers; // remain from next server
assigned = true;
break;
}
Expand All @@ -1666,7 +1667,7 @@ private void roundRobinAssignment(Cluster cluster, List<RegionInfo> regions,
// just sprinkle the rest of the regions on random regionservers. The balanceCluster will
// make it optimal later. we can end up with this if numReplicas > numServers.
for (RegionInfo region : lastFewRegions) {
int i = RANDOM.nextInt(numServers);
int i = rand.nextInt(numServers);
ServerName server = servers.get(i);
assignments.computeIfAbsent(server, k -> new ArrayList<>()).add(region);
cluster.doAssignRegion(region, server);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.hadoop.hbase.master.balancer;

import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.conf.Configured;
import org.apache.hadoop.hbase.ClusterMetrics;
import org.apache.hadoop.hbase.ServerName;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.RegionInfo;
import org.apache.hadoop.hbase.master.LoadBalancer;
import org.apache.hadoop.hbase.master.MasterServices;
import org.apache.hadoop.hbase.master.RegionPlan;
import org.apache.yetus.audience.InterfaceAudience;

/**
* a balancer which is only used in maintenance mode.
*/
@InterfaceAudience.Private
public class MaintenanceLoadBalancer extends Configured implements LoadBalancer {

private volatile boolean stopped = false;

@Override
public void stop(String why) {
stopped = true;
}

@Override
public boolean isStopped() {
return stopped;
}

@Override
public void setClusterMetrics(ClusterMetrics st) {
}

@Override
public void setMasterServices(MasterServices masterServices) {
}

@Override
public List<RegionPlan> balanceCluster(
Map<TableName, Map<ServerName, List<RegionInfo>>> loadOfAllTable) throws IOException {
// do not need to balance in maintenance mode
return Collections.emptyList();
}

@Override
public List<RegionPlan> balanceTable(TableName tableName,
Map<ServerName, List<RegionInfo>> loadOfOneTable) {
return Collections.emptyList();
}

private Map<ServerName, List<RegionInfo>> assign(Collection<RegionInfo> regions,
List<ServerName> servers) {
// should only have 1 region server in maintenance mode
assert servers.size() == 1;
List<RegionInfo> systemRegions =
regions.stream().filter(r -> r.getTable().isSystemTable()).collect(Collectors.toList());
if (!systemRegions.isEmpty()) {
return Collections.singletonMap(servers.get(0), systemRegions);
} else {
return Collections.emptyMap();
}
}

@Override
public Map<ServerName, List<RegionInfo>> roundRobinAssignment(List<RegionInfo> regions,
List<ServerName> servers) throws IOException {
return assign(regions, servers);
}

@Override
public Map<ServerName, List<RegionInfo>> retainAssignment(Map<RegionInfo, ServerName> regions,
List<ServerName> servers) throws IOException {
return assign(regions.keySet(), servers);
}

@Override
public ServerName randomAssignment(RegionInfo regionInfo, List<ServerName> servers)
throws IOException {
// should only have 1 region server in maintenance mode
assert servers.size() == 1;
return regionInfo.getTable().isSystemTable() ? servers.get(0) : null;
}

@Override
public void initialize() {
}

@Override
public void regionOnline(RegionInfo regionInfo, ServerName sn) {
}

@Override
public void regionOffline(RegionInfo regionInfo) {
}

@Override
public void onConfigurationChange(Configuration conf) {
}

@Override
public void postMasterStartupInitialize() {
}

@Override
public void updateBalancerStatus(boolean status) {
}
}
Loading