HBASE-22767 System table RIT STUCK if their RSGroup has no highest version RSes

Signed-off-by: stack <stack@apache.org>
This commit is contained in:
haxiaolin 2019-08-01 10:13:49 +08:00 committed by stack
parent 57439e5bf5
commit 92bf07a98d
4 changed files with 84 additions and 3 deletions

View File

@ -166,6 +166,10 @@ public class VersionInfo {
return comps; return comps;
} }
public static int getMajorVersion(String version) {
return Integer.parseInt(version.split("\\.")[0]);
}
public static void main(String[] args) { public static void main(String[] args) {
writeTo(System.out); writeTo(System.out);
} }

View File

@ -70,8 +70,10 @@ package org.apache.hadoop.hbase;
import org.apache.yetus.audience.InterfaceAudience; import org.apache.yetus.audience.InterfaceAudience;
@InterfaceAudience.Private @InterfaceAudience.Private
@edu.umd.cs.findbugs.annotations.SuppressWarnings(value="DM_STRING_CTOR",
justification="Intentional; to be modified in test")
public class Version { public class Version {
public static final String version = "$version"; public static final String version = new String("$version");
public static final String revision = "$revision"; public static final String revision = "$revision";
public static final String user = "$user"; public static final String user = "$user";
public static final String date = "$date"; public static final String date = "$date";

View File

@ -21,6 +21,8 @@ import static org.apache.hadoop.hbase.util.Threads.sleep;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
@ -30,6 +32,7 @@ import org.apache.hadoop.hbase.HBaseClassTestRule;
import org.apache.hadoop.hbase.NamespaceDescriptor; import org.apache.hadoop.hbase.NamespaceDescriptor;
import org.apache.hadoop.hbase.ServerName; import org.apache.hadoop.hbase.ServerName;
import org.apache.hadoop.hbase.TableName; import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.Version;
import org.apache.hadoop.hbase.Waiter; import org.apache.hadoop.hbase.Waiter;
import org.apache.hadoop.hbase.client.ColumnFamilyDescriptorBuilder; import org.apache.hadoop.hbase.client.ColumnFamilyDescriptorBuilder;
import org.apache.hadoop.hbase.client.RegionInfo; import org.apache.hadoop.hbase.client.RegionInfo;
@ -40,6 +43,7 @@ import org.apache.hadoop.hbase.net.Address;
import org.apache.hadoop.hbase.testclassification.MediumTests; import org.apache.hadoop.hbase.testclassification.MediumTests;
import org.apache.hadoop.hbase.util.Bytes; import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.hbase.util.JVMClusterUtil; import org.apache.hadoop.hbase.util.JVMClusterUtil;
import org.apache.hadoop.hbase.util.VersionInfo;
import org.junit.After; import org.junit.After;
import org.junit.AfterClass; import org.junit.AfterClass;
import org.junit.Before; import org.junit.Before;
@ -224,4 +228,54 @@ public class TestRSGroupsKillRS extends TestRSGroupsBase {
// wait and check if table regions are online // wait and check if table regions are online
TEST_UTIL.waitTableAvailable(tableName, 30000); TEST_UTIL.waitTableAvailable(tableName, 30000);
} }
@Test
public void testLowerMetaGroupVersion() throws Exception{
// create a rsgroup and move one regionserver to it
String groupName = "meta_group";
int groupRSCount = 1;
addGroup(groupName, groupRSCount);
// move hbase:meta to meta_group
tableName = TableName.META_TABLE_NAME;
Set<TableName> toAddTables = new HashSet<>();
toAddTables.add(tableName);
rsGroupAdmin.moveTables(toAddTables, groupName);
assertTrue(rsGroupAdmin.getRSGroupInfo(groupName).getTables().contains(tableName));
TEST_UTIL.waitTableAvailable(tableName, 30000);
// restart the regionserver in meta_group, and lower its version
String originVersion = "";
Set<Address> servers = new HashSet<>();
for(Address addr : rsGroupAdmin.getRSGroupInfo(groupName).getServers()) {
servers.add(addr);
TEST_UTIL.getMiniHBaseCluster().stopRegionServer(getServerName(addr));
originVersion = master.getRegionServerVersion(getServerName(addr));
}
// better wait for a while for region reassign
sleep(10000);
assertEquals(NUM_SLAVES_BASE - groupRSCount,
TEST_UTIL.getMiniHBaseCluster().getLiveRegionServerThreads().size());
Address address = servers.iterator().next();
int majorVersion = VersionInfo.getMajorVersion(originVersion);
assertTrue(majorVersion >= 1);
String lowerVersion = String.valueOf(majorVersion - 1) + originVersion.split("\\.")[1];
setFinalStatic(Version.class.getField("version"), lowerVersion);
TEST_UTIL.getMiniHBaseCluster().startRegionServer(address.getHostname(),
address.getPort());
assertEquals(NUM_SLAVES_BASE,
TEST_UTIL.getMiniHBaseCluster().getLiveRegionServerThreads().size());
assertTrue(VersionInfo.compareVersion(originVersion,
master.getRegionServerVersion(getServerName(servers.iterator().next()))) > 0);
LOG.debug("wait for META assigned...");
TEST_UTIL.waitTableAvailable(tableName, 30000);
}
private static void setFinalStatic(Field field, Object newValue) throws Exception {
field.setAccessible(true);
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
field.set(null, newValue);
}
} }

View File

@ -1965,12 +1965,24 @@ public class AssignmentManager {
LOG.debug("Processing assignQueue; systemServersCount=" + serversForSysTables.size() + LOG.debug("Processing assignQueue; systemServersCount=" + serversForSysTables.size() +
", allServersCount=" + servers.size()); ", allServersCount=" + servers.size());
processAssignmentPlans(regions, null, systemHRIs, processAssignmentPlans(regions, null, systemHRIs,
serversForSysTables.isEmpty()? servers: serversForSysTables); serversForSysTables.isEmpty() && !containsBogusAssignments(regions, systemHRIs) ?
servers: serversForSysTables);
} }
processAssignmentPlans(regions, retainMap, userHRIs, servers); processAssignmentPlans(regions, retainMap, userHRIs, servers);
} }
private boolean containsBogusAssignments(Map<RegionInfo, RegionStateNode> regions,
List<RegionInfo> hirs) {
for (RegionInfo ri : hirs) {
if (regions.get(ri).getRegionLocation() != null &&
regions.get(ri).getRegionLocation().equals(LoadBalancer.BOGUS_SERVER_NAME)){
return true;
}
}
return false;
}
private void processAssignmentPlans(final HashMap<RegionInfo, RegionStateNode> regions, private void processAssignmentPlans(final HashMap<RegionInfo, RegionStateNode> regions,
final HashMap<RegionInfo, ServerName> retainMap, final List<RegionInfo> hris, final HashMap<RegionInfo, ServerName> retainMap, final List<RegionInfo> hris,
final List<ServerName> servers) { final List<ServerName> servers) {
@ -2026,7 +2038,16 @@ public class AssignmentManager {
for (RegionInfo hri: entry.getValue()) { for (RegionInfo hri: entry.getValue()) {
final RegionStateNode regionNode = regions.get(hri); final RegionStateNode regionNode = regions.get(hri);
regionNode.setRegionLocation(server); regionNode.setRegionLocation(server);
events[evcount++] = regionNode.getProcedureEvent(); if (server.equals(LoadBalancer.BOGUS_SERVER_NAME) && regionNode.isSystemTable()) {
assignQueueLock.lock();
try {
pendingAssignQueue.add(regionNode);
} finally {
assignQueueLock.unlock();
}
}else {
events[evcount++] = regionNode.getProcedureEvent();
}
} }
} }
ProcedureEvent.wakeEvents(getProcedureScheduler(), events); ProcedureEvent.wakeEvents(getProcedureScheduler(), events);