HBASE-18492 [AMv2] Embed code for selecting highest versioned region server for system table regions in AssignmentManager.processAssignQueue()

* Modified AssignmentManager.processAssignQueue() method to consider only highest versioned region servers for system table regions when
  destination server is not specified for them. Destination server is retained, if specified.
* Modified MoveRegionProcedure to allow null value for destination server i.e. moving a region from specific source server to non-specific/ unknown
  destination server (picked by load-balancer) is supported now.
* Removed destination server selection from HMaster.checkIfShouldMoveSystemRegionAsync(), as destination server will be picked by load balancer

Signed-off-by: Michael Stack <stack@apache.org>
This commit is contained in:
Umesh Agashe 2017-07-15 22:51:05 -07:00 committed by Michael Stack
parent 03390684cc
commit f314b5911b
3 changed files with 46 additions and 16 deletions

View File

@ -387,7 +387,8 @@ enum MoveRegionState {
message MoveRegionStateData { message MoveRegionStateData {
optional RegionInfo region_info = 1; optional RegionInfo region_info = 1;
required ServerName source_server = 2; required ServerName source_server = 2;
required ServerName destination_server = 3; // if destination server not specified, its selected with load balancer
optional ServerName destination_server = 3;
} }
enum GCRegionState { enum GCRegionState {

View File

@ -478,15 +478,13 @@ public class AssignmentManager implements ServerListener {
new Thread(() -> { new Thread(() -> {
try { try {
synchronized (checkIfShouldMoveSystemRegionLock) { synchronized (checkIfShouldMoveSystemRegionLock) {
List<ServerName> serverList = master.getServerManager()
.createDestinationServersList(getExcludedServersForSystemTable());
List<RegionPlan> plans = new ArrayList<>(); List<RegionPlan> plans = new ArrayList<>();
for (ServerName server : getExcludedServersForSystemTable()) { for (ServerName server : getExcludedServersForSystemTable()) {
List<HRegionInfo> regionsShouldMove = getCarryingSystemTables(server); List<HRegionInfo> regionsShouldMove = getCarryingSystemTables(server);
if (!regionsShouldMove.isEmpty()) { if (!regionsShouldMove.isEmpty()) {
for (HRegionInfo regionInfo : regionsShouldMove) { for (HRegionInfo regionInfo : regionsShouldMove) {
RegionPlan plan = new RegionPlan(regionInfo, server, // null value for dest forces destination server to be selected by balancer
getBalancer().randomAssignment(regionInfo, serverList)); RegionPlan plan = new RegionPlan(regionInfo, server, null);
if (regionInfo.isMetaRegion()) { if (regionInfo.isMetaRegion()) {
// Must move meta region first. // Must move meta region first.
moveAsync(plan); moveAsync(plan);
@ -1648,9 +1646,14 @@ public class AssignmentManager implements ServerListener {
} }
// TODO: Optimize balancer. pass a RegionPlan? // TODO: Optimize balancer. pass a RegionPlan?
final HashMap<HRegionInfo, ServerName> retainMap = new HashMap<HRegionInfo, ServerName>(); final HashMap<HRegionInfo, ServerName> retainMap = new HashMap<>();
final List<HRegionInfo> rrList = new ArrayList<HRegionInfo>(); final List<HRegionInfo> userRRList = new ArrayList<>();
for (RegionStateNode regionNode: regions.values()) { // regions for system tables requiring reassignment
final List<HRegionInfo> sysRRList = new ArrayList<>();
for (RegionStateNode regionNode : regions.values()) {
boolean sysTable = regionNode.isSystemTable();
final List<HRegionInfo> rrList = sysTable ? sysRRList : userRRList;
if (regionNode.getRegionLocation() != null) { if (regionNode.getRegionLocation() != null) {
retainMap.put(regionNode.getRegionInfo(), regionNode.getRegionLocation()); retainMap.put(regionNode.getRegionInfo(), regionNode.getRegionLocation());
} else { } else {
@ -1659,7 +1662,6 @@ public class AssignmentManager implements ServerListener {
} }
// TODO: connect with the listener to invalidate the cache // TODO: connect with the listener to invalidate the cache
final LoadBalancer balancer = getBalancer();
// TODO use events // TODO use events
List<ServerName> servers = master.getServerManager().createDestinationServersList(); List<ServerName> servers = master.getServerManager().createDestinationServersList();
@ -1679,13 +1681,35 @@ public class AssignmentManager implements ServerListener {
servers = master.getServerManager().createDestinationServersList(); servers = master.getServerManager().createDestinationServersList();
} }
final boolean isTraceEnabled = LOG.isTraceEnabled(); if (!sysRRList.isEmpty()) {
// system table regions requiring reassignment are present, get region servers
// not available for system table regions
final List<ServerName> excludeServers = getExcludedServersForSystemTable();
List<ServerName> serversForSysTables = servers.stream()
.filter(s -> !excludeServers.contains(s)).collect(Collectors.toList());
if (serversForSysTables.isEmpty()) {
LOG.warn("No servers available for system table regions, considering all servers!");
}
LOG.debug("Processing assignment plans for System tables sysServersCount=" +
serversForSysTables.size() + ", allServersCount=" + servers.size());
processAssignmentPlans(regions, null, sysRRList,
serversForSysTables.isEmpty() ? servers : serversForSysTables);
}
processAssignmentPlans(regions, retainMap, userRRList, servers);
}
private void processAssignmentPlans(final HashMap<HRegionInfo, RegionStateNode> regions,
final HashMap<HRegionInfo, ServerName> retainMap, final List<HRegionInfo> rrList,
final List<ServerName> servers) {
boolean isTraceEnabled = LOG.isTraceEnabled();
if (isTraceEnabled) { if (isTraceEnabled) {
LOG.trace("available servers count=" + servers.size() + ": " + servers); LOG.trace("available servers count=" + servers.size() + ": " + servers);
} }
final LoadBalancer balancer = getBalancer();
// ask the balancer where to place regions // ask the balancer where to place regions
if (!retainMap.isEmpty()) { if (retainMap != null && !retainMap.isEmpty()) {
if (isTraceEnabled) { if (isTraceEnabled) {
LOG.trace("retain assign regions=" + retainMap); LOG.trace("retain assign regions=" + retainMap);
} }

View File

@ -54,7 +54,6 @@ public class MoveRegionProcedure extends AbstractStateMachineRegionProcedure<Mov
public MoveRegionProcedure(final MasterProcedureEnv env, final RegionPlan plan) { public MoveRegionProcedure(final MasterProcedureEnv env, final RegionPlan plan) {
super(env, plan.getRegionInfo()); super(env, plan.getRegionInfo());
assert plan.getDestination() != null: plan.toString();
this.plan = plan; this.plan = plan;
} }
@ -70,7 +69,10 @@ public class MoveRegionProcedure extends AbstractStateMachineRegionProcedure<Mov
setNextState(MoveRegionState.MOVE_REGION_ASSIGN); setNextState(MoveRegionState.MOVE_REGION_ASSIGN);
break; break;
case MOVE_REGION_ASSIGN: case MOVE_REGION_ASSIGN:
addChildProcedure(new AssignProcedure(plan.getRegionInfo(), plan.getDestination())); AssignProcedure assignProcedure = plan.getDestination() == null ?
new AssignProcedure(plan.getRegionInfo(), true) :
new AssignProcedure(plan.getRegionInfo(), plan.getDestination());
addChildProcedure(assignProcedure);
return Flow.NO_MORE_STATE; return Flow.NO_MORE_STATE;
default: default:
throw new UnsupportedOperationException("unhandled state=" + state); throw new UnsupportedOperationException("unhandled state=" + state);
@ -127,8 +129,10 @@ public class MoveRegionProcedure extends AbstractStateMachineRegionProcedure<Mov
final MoveRegionStateData.Builder state = MoveRegionStateData.newBuilder() final MoveRegionStateData.Builder state = MoveRegionStateData.newBuilder()
// No need to serialize the HRegionInfo. The super class has the region. // No need to serialize the HRegionInfo. The super class has the region.
.setSourceServer(ProtobufUtil.toServerName(plan.getSource())) .setSourceServer(ProtobufUtil.toServerName(plan.getSource()));
.setDestinationServer(ProtobufUtil.toServerName(plan.getDestination())); if (plan.getDestination() != null) {
state.setDestinationServer(ProtobufUtil.toServerName(plan.getDestination()));
}
state.build().writeDelimitedTo(stream); state.build().writeDelimitedTo(stream);
} }
@ -139,7 +143,8 @@ public class MoveRegionProcedure extends AbstractStateMachineRegionProcedure<Mov
final MoveRegionStateData state = MoveRegionStateData.parseDelimitedFrom(stream); final MoveRegionStateData state = MoveRegionStateData.parseDelimitedFrom(stream);
final HRegionInfo regionInfo = getRegion(); // Get it from super class deserialization. final HRegionInfo regionInfo = getRegion(); // Get it from super class deserialization.
final ServerName sourceServer = ProtobufUtil.toServerName(state.getSourceServer()); final ServerName sourceServer = ProtobufUtil.toServerName(state.getSourceServer());
final ServerName destinationServer = ProtobufUtil.toServerName(state.getDestinationServer()); final ServerName destinationServer = state.hasDestinationServer() ?
ProtobufUtil.toServerName(state.getDestinationServer()) : null;
this.plan = new RegionPlan(regionInfo, sourceServer, destinationServer); this.plan = new RegionPlan(regionInfo, sourceServer, destinationServer);
} }
} }