use of org.apache.hadoop.hbase.favored.FavoredNodeAssignmentHelper in project hbase by apache.
the class FavoredStochasticBalancer method generateFavoredNodesForDaughter.
/**
* Generate Favored Nodes for daughters during region split.
* <p/>
* If the parent does not have FN, regenerates them for the daughters.
* <p/>
* If the parent has FN, inherit two FN from parent for each daughter and generate the remaining.
* The primary FN for both the daughters should be the same as parent. Inherit the secondary FN
* from the parent but keep it different for each daughter. Choose the remaining FN randomly. This
* would give us better distribution over a period of time after enough splits.
*/
@Override
public void generateFavoredNodesForDaughter(List<ServerName> servers, RegionInfo parent, RegionInfo regionA, RegionInfo regionB) throws IOException {
Map<RegionInfo, List<ServerName>> result = new HashMap<>();
FavoredNodeAssignmentHelper helper = new FavoredNodeAssignmentHelper(servers, rackManager);
helper.initialize();
List<ServerName> parentFavoredNodes = fnm.getFavoredNodes(parent);
if (parentFavoredNodes == null) {
LOG.debug("Unable to find favored nodes for parent, " + parent + " generating new favored nodes for daughter");
result.put(regionA, helper.generateFavoredNodes(regionA));
result.put(regionB, helper.generateFavoredNodes(regionB));
} else {
// Lets get the primary and secondary from parent for regionA
Set<ServerName> regionAFN = getInheritedFNForDaughter(helper, parentFavoredNodes, PRIMARY, SECONDARY);
result.put(regionA, Lists.newArrayList(regionAFN));
// Lets get the primary and tertiary from parent for regionB
Set<ServerName> regionBFN = getInheritedFNForDaughter(helper, parentFavoredNodes, PRIMARY, TERTIARY);
result.put(regionB, Lists.newArrayList(regionBFN));
}
fnm.updateFavoredNodes(result);
}
use of org.apache.hadoop.hbase.favored.FavoredNodeAssignmentHelper in project hbase by apache.
the class FavoredStochasticBalancer method roundRobinAssignment.
/**
* Round robin assignment: Segregate the regions into two types:
*
* 1. The regions that have favored node assignment where at least one of the favored node
* is still alive. In this case, try to adhere to the current favored nodes assignment as
* much as possible - i.e., if the current primary is gone, then make the secondary or
* tertiary as the new host for the region (based on their current load). Note that we don't
* change the favored node assignments here (even though one or more favored node is
* currently down). That will be done by the admin operations.
*
* 2. The regions that currently don't have favored node assignments. Generate favored nodes
* for them and then assign. Generate the primary fn in round robin fashion and generate
* secondary and tertiary as per favored nodes constraints.
*/
@Override
@NonNull
public Map<ServerName, List<RegionInfo>> roundRobinAssignment(List<RegionInfo> regions, List<ServerName> servers) throws HBaseIOException {
metricsBalancer.incrMiscInvocations();
Map<ServerName, List<RegionInfo>> assignmentMap = new HashMap<>();
if (regions.isEmpty()) {
return assignmentMap;
}
Set<RegionInfo> regionSet = new HashSet<>(regions);
try {
FavoredNodeAssignmentHelper helper = new FavoredNodeAssignmentHelper(servers, rackManager);
helper.initialize();
Set<RegionInfo> systemRegions = FavoredNodesManager.filterNonFNApplicableRegions(regionSet);
regionSet.removeAll(systemRegions);
// Assign all system regions
Map<ServerName, List<RegionInfo>> systemAssignments = super.roundRobinAssignment(Lists.newArrayList(systemRegions), servers);
// Segregate favored and non-favored nodes regions and assign accordingly.
Pair<Map<ServerName, List<RegionInfo>>, List<RegionInfo>> segregatedRegions = segregateRegionsAndAssignRegionsWithFavoredNodes(regionSet, servers);
Map<ServerName, List<RegionInfo>> regionsWithFavoredNodesMap = segregatedRegions.getFirst();
Map<ServerName, List<RegionInfo>> regionsWithoutFN = generateFNForRegionsWithoutFN(helper, segregatedRegions.getSecond());
// merge the assignment maps
mergeAssignmentMaps(assignmentMap, systemAssignments);
mergeAssignmentMaps(assignmentMap, regionsWithFavoredNodesMap);
mergeAssignmentMaps(assignmentMap, regionsWithoutFN);
} catch (Exception ex) {
throw new HBaseIOException("Encountered exception while doing favored-nodes assignment " + ex + " Falling back to regular assignment", ex);
}
return assignmentMap;
}
use of org.apache.hadoop.hbase.favored.FavoredNodeAssignmentHelper in project hbase by apache.
the class TestFavoredStochasticLoadBalancer method testMisplacedRegions.
@Ignore
@Test
public void testMisplacedRegions() throws Exception {
TableName tableName = TableName.valueOf("testMisplacedRegions");
TableDescriptor tableDescriptor = TableDescriptorBuilder.newBuilder(tableName).setColumnFamily(ColumnFamilyDescriptorBuilder.of(HConstants.CATALOG_FAMILY)).build();
admin.createTable(tableDescriptor, Bytes.toBytes("aaa"), Bytes.toBytes("zzz"), REGION_NUM);
TEST_UTIL.waitTableAvailable(tableName);
final RegionInfo misplacedRegion = admin.getRegions(tableName).get(0);
FavoredNodesManager fnm = master.getFavoredNodesManager();
List<ServerName> currentFN = fnm.getFavoredNodes(misplacedRegion);
assertNotNull(currentFN);
List<ServerName> serversForNewFN = Lists.newArrayList();
for (ServerName sn : admin.getClusterMetrics(EnumSet.of(Option.LIVE_SERVERS)).getLiveServerMetrics().keySet()) {
serversForNewFN.add(ServerName.valueOf(sn.getHostname(), sn.getPort(), NON_STARTCODE));
}
for (ServerName sn : currentFN) {
serversForNewFN.remove(sn);
}
FavoredNodeAssignmentHelper helper = new FavoredNodeAssignmentHelper(serversForNewFN, conf);
helper.initialize();
List<ServerName> newFavoredNodes = helper.generateFavoredNodes(misplacedRegion);
assertNotNull(newFavoredNodes);
assertEquals(FavoredNodeAssignmentHelper.FAVORED_NODES_NUM, newFavoredNodes.size());
Map<RegionInfo, List<ServerName>> regionFNMap = Maps.newHashMap();
regionFNMap.put(misplacedRegion, newFavoredNodes);
fnm.updateFavoredNodes(regionFNMap);
final RegionStates regionStates = master.getAssignmentManager().getRegionStates();
final ServerName current = regionStates.getRegionServerOfRegion(misplacedRegion);
assertNull("Misplaced region is still hosted on favored node, not expected.", FavoredNodesPlan.getFavoredServerPosition(fnm.getFavoredNodes(misplacedRegion), current));
admin.balancerSwitch(true, true);
assertTrue("Balancer did not run", admin.balance());
TEST_UTIL.waitFor(120000, 30000, new Waiter.Predicate<Exception>() {
@Override
public boolean evaluate() throws Exception {
ServerName host = regionStates.getRegionServerOfRegion(misplacedRegion);
return !ServerName.isSameAddress(host, current);
}
});
checkFavoredNodeAssignments(tableName, fnm, regionStates);
}
use of org.apache.hadoop.hbase.favored.FavoredNodeAssignmentHelper in project hbase by apache.
the class TestFavoredStochasticLoadBalancer method testAllFavoredNodesDeadMasterRestarted.
@Ignore
@Test
public void testAllFavoredNodesDeadMasterRestarted() throws Exception {
TableName tableName = TableName.valueOf("testAllFavoredNodesDeadMasterRestarted");
TableDescriptor tableDescriptor = TableDescriptorBuilder.newBuilder(tableName).setColumnFamily(ColumnFamilyDescriptorBuilder.of(HConstants.CATALOG_FAMILY)).build();
admin.createTable(tableDescriptor, Bytes.toBytes("aaa"), Bytes.toBytes("zzz"), REGION_NUM);
TEST_UTIL.waitTableAvailable(tableName);
final RegionInfo region = admin.getRegions(tableName).get(0);
LOG.info("Region that's supposed to be in transition: " + region);
FavoredNodesManager fnm = master.getFavoredNodesManager();
List<ServerName> currentFN = fnm.getFavoredNodes(region);
assertNotNull(currentFN);
// Lets kill all the RS that are favored nodes for this region.
stopServersAndWaitUntilProcessed(currentFN);
final RegionStates regionStatesBeforeMaster = master.getAssignmentManager().getRegionStates();
TEST_UTIL.waitFor(10000, new Waiter.Predicate<Exception>() {
@Override
public boolean evaluate() throws Exception {
return regionStatesBeforeMaster.getRegionState(region).isFailedOpen();
}
});
assertTrue("Region: " + region + " should be RIT", regionStatesBeforeMaster.getRegionState(region).isFailedOpen());
List<RegionInfo> rit = Lists.newArrayList();
for (RegionStateNode regionState : regionStatesBeforeMaster.getRegionsInTransition()) {
RegionInfo regionInfo = regionState.getRegionInfo();
LOG.debug("Region in transition after stopping FN's: " + regionInfo);
rit.add(regionInfo);
assertTrue("Region: " + regionInfo + " should be RIT", regionStatesBeforeMaster.getRegionState(regionInfo).isFailedOpen());
assertEquals("Region: " + regionInfo + " does not belong to table: " + tableName, tableName, regionInfo.getTable());
}
Configuration conf = cluster.getConf();
conf.setInt(ServerManager.WAIT_ON_REGIONSERVERS_MINTOSTART, SLAVES - FavoredNodeAssignmentHelper.FAVORED_NODES_NUM);
cluster.stopMaster(master.getServerName());
cluster.waitForMasterToStop(master.getServerName(), 60000);
cluster.startMaster();
cluster.waitForActiveAndReadyMaster();
master = cluster.getMaster();
fnm = master.getFavoredNodesManager();
RegionStates regionStates = master.getAssignmentManager().getRegionStates();
assertTrue("Region: " + region + " should be RIT", regionStates.getRegionState(region).isFailedOpen());
for (RegionInfo regionInfo : rit) {
assertTrue("Region: " + regionInfo + " should be RIT", regionStates.getRegionState(regionInfo).isFailedOpen());
}
// Regenerate FN and assign, everything else should be fine
List<ServerName> serversForNewFN = Lists.newArrayList();
for (ServerName sn : admin.getClusterMetrics(EnumSet.of(Option.LIVE_SERVERS)).getLiveServerMetrics().keySet()) {
serversForNewFN.add(ServerName.valueOf(sn.getHostname(), sn.getPort(), NON_STARTCODE));
}
FavoredNodeAssignmentHelper helper = new FavoredNodeAssignmentHelper(serversForNewFN, conf);
helper.initialize();
for (RegionInfo regionInfo : rit) {
List<ServerName> newFavoredNodes = helper.generateFavoredNodes(regionInfo);
assertNotNull(newFavoredNodes);
assertEquals(FavoredNodeAssignmentHelper.FAVORED_NODES_NUM, newFavoredNodes.size());
LOG.info("Region: " + regionInfo.getEncodedName() + " FN: " + newFavoredNodes);
Map<RegionInfo, List<ServerName>> regionFNMap = Maps.newHashMap();
regionFNMap.put(regionInfo, newFavoredNodes);
fnm.updateFavoredNodes(regionFNMap);
LOG.info("Assigning region: " + regionInfo.getEncodedName());
admin.assign(regionInfo.getEncodedNameAsBytes());
}
TEST_UTIL.waitUntilNoRegionsInTransition(60000);
assertEquals("Not all regions are online", REGION_NUM, admin.getRegions(tableName).size());
admin.balancerSwitch(true, true);
assertTrue("Balancer did not run", admin.balance());
TEST_UTIL.waitUntilNoRegionsInTransition(60000);
checkFavoredNodeAssignments(tableName, fnm, regionStates);
}
use of org.apache.hadoop.hbase.favored.FavoredNodeAssignmentHelper in project hbase by apache.
the class FavoredStochasticBalancer method retainAssignment.
/**
* Reuse BaseLoadBalancer's retainAssignment, but generate favored nodes when its missing.
*/
@Override
@NonNull
public Map<ServerName, List<RegionInfo>> retainAssignment(Map<RegionInfo, ServerName> regions, List<ServerName> servers) throws HBaseIOException {
Map<ServerName, List<RegionInfo>> assignmentMap = Maps.newHashMap();
Map<ServerName, List<RegionInfo>> result = super.retainAssignment(regions, servers);
if (result.isEmpty()) {
LOG.warn("Nothing to assign to, probably no servers or no regions");
return result;
}
// Lets check if favored nodes info is in META, if not generate now.
FavoredNodeAssignmentHelper helper = new FavoredNodeAssignmentHelper(servers, getConf());
helper.initialize();
LOG.debug("Generating favored nodes for regions missing them.");
Map<RegionInfo, List<ServerName>> regionFNMap = Maps.newHashMap();
try {
for (Map.Entry<ServerName, List<RegionInfo>> entry : result.entrySet()) {
ServerName sn = entry.getKey();
ServerName primary = ServerName.valueOf(sn.getHostname(), sn.getPort(), NON_STARTCODE);
for (RegionInfo hri : entry.getValue()) {
if (FavoredNodesManager.isFavoredNodeApplicable(hri)) {
List<ServerName> favoredNodes = fnm.getFavoredNodes(hri);
if (favoredNodes == null || favoredNodes.size() < FAVORED_NODES_NUM) {
LOG.debug("Generating favored nodes for: " + hri + " with primary: " + primary);
ServerName[] secondaryAndTertiaryNodes = helper.getSecondaryAndTertiary(hri, primary);
if (secondaryAndTertiaryNodes != null && secondaryAndTertiaryNodes.length == 2) {
List<ServerName> newFavoredNodes = Lists.newArrayList();
newFavoredNodes.add(primary);
newFavoredNodes.add(ServerName.valueOf(secondaryAndTertiaryNodes[0].getHostname(), secondaryAndTertiaryNodes[0].getPort(), NON_STARTCODE));
newFavoredNodes.add(ServerName.valueOf(secondaryAndTertiaryNodes[1].getHostname(), secondaryAndTertiaryNodes[1].getPort(), NON_STARTCODE));
regionFNMap.put(hri, newFavoredNodes);
addRegionToMap(assignmentMap, hri, sn);
} else {
throw new HBaseIOException("Cannot generate secondary/tertiary FN for " + hri + " generated " + (secondaryAndTertiaryNodes != null ? secondaryAndTertiaryNodes : " nothing"));
}
} else {
List<ServerName> onlineFN = getOnlineFavoredNodes(servers, favoredNodes);
if (onlineFN.isEmpty()) {
// All favored nodes are dead, lets assign it to BOGUS
addRegionToMap(assignmentMap, hri, BOGUS_SERVER_NAME);
} else {
// Is primary not on FN? Less likely, but we can still take care of this.
if (FavoredNodesPlan.getFavoredServerPosition(favoredNodes, sn) != null) {
addRegionToMap(assignmentMap, hri, sn);
} else {
ServerName destination = onlineFN.get(ThreadLocalRandom.current().nextInt(onlineFN.size()));
LOG.warn("Region: " + hri + " not hosted on favored nodes: " + favoredNodes + " current: " + sn + " moving to: " + destination);
addRegionToMap(assignmentMap, hri, destination);
}
}
}
} else {
addRegionToMap(assignmentMap, hri, sn);
}
}
}
if (!regionFNMap.isEmpty()) {
LOG.debug("Updating FN in meta for missing regions, count: " + regionFNMap.size());
fnm.updateFavoredNodes(regionFNMap);
}
} catch (IOException e) {
throw new HBaseIOException("Cannot generate/update FN for regions: " + regionFNMap.keySet());
}
return assignmentMap;
}
Aggregations