use of org.apache.hadoop.hbase.ServerName in project hbase by apache.
the class FavoredNodeAssignmentHelper method getFavoredNodesList.
/**
* @param favoredNodes The PB'ed bytes of favored nodes
* @return the array of {@link ServerName} for the byte array of favored nodes.
* @throws IOException
*/
public static ServerName[] getFavoredNodesList(byte[] favoredNodes) throws IOException {
FavoredNodes f = FavoredNodes.parseFrom(favoredNodes);
List<HBaseProtos.ServerName> protoNodes = f.getFavoredNodeList();
ServerName[] servers = new ServerName[protoNodes.size()];
int i = 0;
for (HBaseProtos.ServerName node : protoNodes) {
servers[i++] = ProtobufUtil.toServerName(node);
}
return servers;
}
use of org.apache.hadoop.hbase.ServerName in project hbase by apache.
the class FavoredNodeAssignmentHelper method generateFavoredNodes.
/*
* Generate favored nodes for a region.
*
* Choose a random server as primary and then choose secondary and tertiary FN so its spread
* across two racks.
*/
List<ServerName> generateFavoredNodes(HRegionInfo hri) throws IOException {
List<ServerName> favoredNodesForRegion = new ArrayList<>(FAVORED_NODES_NUM);
ServerName primary = servers.get(random.nextInt(servers.size()));
favoredNodesForRegion.add(ServerName.valueOf(primary.getHostAndPort(), ServerName.NON_STARTCODE));
Map<HRegionInfo, ServerName> primaryRSMap = new HashMap<>(1);
primaryRSMap.put(hri, primary);
Map<HRegionInfo, ServerName[]> secondaryAndTertiaryRSMap = placeSecondaryAndTertiaryRS(primaryRSMap);
ServerName[] secondaryAndTertiaryNodes = secondaryAndTertiaryRSMap.get(hri);
if (secondaryAndTertiaryNodes != null && secondaryAndTertiaryNodes.length == 2) {
for (ServerName sn : secondaryAndTertiaryNodes) {
favoredNodesForRegion.add(ServerName.valueOf(sn.getHostAndPort(), ServerName.NON_STARTCODE));
}
return favoredNodesForRegion;
} else {
throw new HBaseIOException("Unable to generate secondary and tertiary favored nodes.");
}
}
use of org.apache.hadoop.hbase.ServerName in project hbase by apache.
the class FavoredNodeAssignmentHelper method placeSecondaryAndTertiaryRS.
Map<HRegionInfo, ServerName[]> placeSecondaryAndTertiaryRS(Map<HRegionInfo, ServerName> primaryRSMap) {
Map<HRegionInfo, ServerName[]> secondaryAndTertiaryMap = new HashMap<>();
for (Map.Entry<HRegionInfo, ServerName> entry : primaryRSMap.entrySet()) {
// Get the target region and its primary region server rack
HRegionInfo regionInfo = entry.getKey();
ServerName primaryRS = entry.getValue();
try {
// Create the secondary and tertiary region server pair object.
ServerName[] favoredNodes;
// Get the rack for the primary region server
String primaryRack = getRackOfServer(primaryRS);
if (getTotalNumberOfRacks() == 1) {
favoredNodes = singleRackCase(regionInfo, primaryRS, primaryRack);
} else {
favoredNodes = multiRackCase(regionInfo, primaryRS, primaryRack);
}
if (favoredNodes != null) {
secondaryAndTertiaryMap.put(regionInfo, favoredNodes);
LOG.debug("Place the secondary and tertiary region server for region " + regionInfo.getRegionNameAsString());
}
} catch (Exception e) {
LOG.warn("Cannot place the favored nodes for region " + regionInfo.getRegionNameAsString() + " because " + e, e);
continue;
}
}
return secondaryAndTertiaryMap;
}
use of org.apache.hadoop.hbase.ServerName in project hbase by apache.
the class FavoredNodeAssignmentHelper method multiRackCase.
/**
* Place secondary and tertiary nodes in a multi rack case.
* If there are only two racks, then we try the place the secondary
* and tertiary on different rack than primary. But if the other rack has
* only one region server, then we place primary and tertiary on one rack
* and secondary on another. The aim is two distribute the three favored nodes
* on >= 2 racks.
* TODO: see how we can use generateMissingFavoredNodeMultiRack API here
* @param regionInfo Region for which we are trying to generate FN
* @param primaryRS The primary favored node.
* @param primaryRack The rack of the primary favored node.
* @return Array containing secondary and tertiary favored nodes.
* @throws IOException Signals that an I/O exception has occurred.
*/
private ServerName[] multiRackCase(HRegionInfo regionInfo, ServerName primaryRS, String primaryRack) throws IOException {
List<ServerName> favoredNodes = Lists.newArrayList(primaryRS);
// Create the secondary and tertiary pair
ServerName secondaryRS = generateMissingFavoredNodeMultiRack(favoredNodes);
favoredNodes.add(secondaryRS);
String secondaryRack = getRackOfServer(secondaryRS);
ServerName tertiaryRS;
if (primaryRack.equals(secondaryRack)) {
tertiaryRS = generateMissingFavoredNode(favoredNodes);
} else {
// Try to place tertiary in secondary RS rack else place on primary rack.
tertiaryRS = getOneRandomServer(secondaryRack, Sets.newHashSet(secondaryRS));
if (tertiaryRS == null) {
tertiaryRS = getOneRandomServer(primaryRack, Sets.newHashSet(primaryRS));
}
// We couldn't find anything in secondary rack, get any FN
if (tertiaryRS == null) {
tertiaryRS = generateMissingFavoredNode(Lists.newArrayList(primaryRS, secondaryRS));
}
}
return new ServerName[] { secondaryRS, tertiaryRS };
}
use of org.apache.hadoop.hbase.ServerName in project hbase by apache.
the class FavoredNodeAssignmentHelper method generateMissingFavoredNodeMultiRack.
/*
* Generates a missing FN based on the input favoredNodes and also the nodes to be skipped.
*
* Get the current layout of favored nodes arrangement and nodes to be excluded and get a
* random node that goes with HDFS block placement. Eg: If the existing nodes are on one rack,
* generate one from another rack. We exclude as much as possible so the random selection
* has more chance to generate a node within a few iterations, ideally 1.
*/
private ServerName generateMissingFavoredNodeMultiRack(List<ServerName> favoredNodes, List<ServerName> excludeNodes) throws IOException {
Set<String> racks = Sets.newHashSet();
Map<String, Set<ServerName>> rackToFNMapping = new HashMap<>();
// Lets understand the current rack distribution of the FN
for (ServerName sn : favoredNodes) {
String rack = getRackOfServer(sn);
racks.add(rack);
Set<ServerName> serversInRack = rackToFNMapping.get(rack);
if (serversInRack == null) {
serversInRack = Sets.newHashSet();
rackToFNMapping.put(rack, serversInRack);
}
serversInRack.add(sn);
}
// What racks should be skipped while getting a FN?
Set<String> skipRackSet = Sets.newHashSet();
/*
* If both the FN are from the same rack, then we don't want to generate another FN on the
* same rack. If that rack fails, the region would be unavailable.
*/
if (racks.size() == 1 && favoredNodes.size() > 1) {
skipRackSet.add(racks.iterator().next());
}
/*
* If there are no free nodes on the existing racks, we should skip those racks too. We can
* reduce the number of iterations for FN selection.
*/
for (String rack : racks) {
if (getServersFromRack(rack) != null && rackToFNMapping.get(rack).size() == getServersFromRack(rack).size()) {
skipRackSet.add(rack);
}
}
Set<ServerName> favoredNodeSet = Sets.newHashSet(favoredNodes);
if (excludeNodes != null && excludeNodes.size() > 0) {
favoredNodeSet.addAll(excludeNodes);
}
/*
* Lets get a random rack by excluding skipRackSet and generate a random FN from that rack.
*/
int i = 0;
Set<String> randomRacks = Sets.newHashSet();
ServerName newServer = null;
do {
String randomRack = this.getOneRandomRack(skipRackSet);
newServer = this.getOneRandomServer(randomRack, favoredNodeSet);
randomRacks.add(randomRack);
i++;
} while ((i < MAX_ATTEMPTS_FN_GENERATION) && (newServer == null));
if (newServer == null) {
if (LOG.isTraceEnabled()) {
LOG.trace(String.format("Unable to generate additional favored nodes for %s after " + "considering racks %s and skip rack %s with a unique rack list of %s and rack " + "to RS map of %s and RS to rack map of %s", StringUtils.join(favoredNodes, ","), randomRacks, skipRackSet, uniqueRackList, rackToRegionServerMap, regionServerToRackMap));
}
throw new IOException(" Unable to generate additional favored nodes for " + StringUtils.join(favoredNodes, ","));
}
return newServer;
}
Aggregations