HBASE-20901 Reducing region replica has no effect
Signed-off-by: tedyu <yuzhihong@gmail.com>
This commit is contained in:
parent
35a3c605f2
commit
cf1f63bf91
|
@ -846,6 +846,30 @@ public class MetaTableAccessor {
|
|||
return HConstants.STATE_QUALIFIER;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the column qualifier for serialized region state
|
||||
* @param replicaId the replicaId of the region
|
||||
* @return a byte[] for state qualifier
|
||||
*/
|
||||
@VisibleForTesting
|
||||
public static byte[] getRegionStateColumn(int replicaId) {
|
||||
return replicaId == 0 ? HConstants.STATE_QUALIFIER
|
||||
: Bytes.toBytes(HConstants.STATE_QUALIFIER_STR + META_REPLICA_ID_DELIMITER
|
||||
+ String.format(RegionInfo.REPLICA_ID_FORMAT, replicaId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the column qualifier for serialized region state
|
||||
* @param replicaId the replicaId of the region
|
||||
* @return a byte[] for sn column qualifier
|
||||
*/
|
||||
@VisibleForTesting
|
||||
public static byte[] getServerNameColumn(int replicaId) {
|
||||
return replicaId == 0 ? HConstants.SERVERNAME_QUALIFIER
|
||||
: Bytes.toBytes(HConstants.SERVERNAME_QUALIFIER_STR + META_REPLICA_ID_DELIMITER
|
||||
+ String.format(RegionInfo.REPLICA_ID_FORMAT, replicaId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the column qualifier for server column for replicaId
|
||||
* @param replicaId the replicaId of the region
|
||||
|
@ -1406,7 +1430,10 @@ public class MetaTableAccessor {
|
|||
getSeqNumColumn(i), now);
|
||||
deleteReplicaLocations.addColumns(getCatalogFamily(),
|
||||
getStartCodeColumn(i), now);
|
||||
deleteReplicaLocations.addColumns(getCatalogFamily(), getServerNameColumn(i), now);
|
||||
deleteReplicaLocations.addColumns(getCatalogFamily(), getRegionStateColumn(i), now);
|
||||
}
|
||||
|
||||
deleteFromMetaTable(connection, deleteReplicaLocations);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,16 +21,12 @@ package org.apache.hadoop.hbase.master.procedure;
|
|||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.hadoop.hbase.Cell;
|
||||
import org.apache.hadoop.hbase.HConstants;
|
||||
import org.apache.hadoop.hbase.MetaTableAccessor;
|
||||
import org.apache.hadoop.hbase.TableName;
|
||||
import org.apache.hadoop.hbase.TableNotDisabledException;
|
||||
import org.apache.hadoop.hbase.TableNotFoundException;
|
||||
import org.apache.yetus.audience.InterfaceAudience;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.apache.hadoop.hbase.client.Connection;
|
||||
import org.apache.hadoop.hbase.client.Get;
|
||||
import org.apache.hadoop.hbase.client.RegionInfo;
|
||||
|
@ -42,6 +38,10 @@ import org.apache.hadoop.hbase.client.TableState;
|
|||
import org.apache.hadoop.hbase.master.MasterCoprocessorHost;
|
||||
import org.apache.hadoop.hbase.master.TableStateManager;
|
||||
import org.apache.hadoop.hbase.procedure2.ProcedureStateSerializer;
|
||||
import org.apache.yetus.audience.InterfaceAudience;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;
|
||||
import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProcedureProtos;
|
||||
import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProcedureProtos.EnableTableState;
|
||||
|
@ -94,37 +94,37 @@ public class EnableTableProcedure
|
|||
|
||||
try {
|
||||
switch (state) {
|
||||
case ENABLE_TABLE_PREPARE:
|
||||
if (prepareEnable(env)) {
|
||||
setNextState(EnableTableState.ENABLE_TABLE_PRE_OPERATION);
|
||||
} else {
|
||||
assert isFailed() : "enable should have an exception here";
|
||||
return Flow.NO_MORE_STATE;
|
||||
}
|
||||
break;
|
||||
case ENABLE_TABLE_PRE_OPERATION:
|
||||
preEnable(env, state);
|
||||
setNextState(EnableTableState.ENABLE_TABLE_SET_ENABLING_TABLE_STATE);
|
||||
break;
|
||||
case ENABLE_TABLE_SET_ENABLING_TABLE_STATE:
|
||||
setTableStateToEnabling(env, tableName);
|
||||
setNextState(EnableTableState.ENABLE_TABLE_MARK_REGIONS_ONLINE);
|
||||
break;
|
||||
case ENABLE_TABLE_MARK_REGIONS_ONLINE:
|
||||
Connection connection = env.getMasterServices().getConnection();
|
||||
// we will need to get the tableDescriptor here to see if there is a change in the replica
|
||||
// count
|
||||
TableDescriptor hTableDescriptor =
|
||||
env.getMasterServices().getTableDescriptors().get(tableName);
|
||||
case ENABLE_TABLE_PREPARE:
|
||||
if (prepareEnable(env)) {
|
||||
setNextState(EnableTableState.ENABLE_TABLE_PRE_OPERATION);
|
||||
} else {
|
||||
assert isFailed() : "enable should have an exception here";
|
||||
return Flow.NO_MORE_STATE;
|
||||
}
|
||||
break;
|
||||
case ENABLE_TABLE_PRE_OPERATION:
|
||||
preEnable(env, state);
|
||||
setNextState(EnableTableState.ENABLE_TABLE_SET_ENABLING_TABLE_STATE);
|
||||
break;
|
||||
case ENABLE_TABLE_SET_ENABLING_TABLE_STATE:
|
||||
setTableStateToEnabling(env, tableName);
|
||||
setNextState(EnableTableState.ENABLE_TABLE_MARK_REGIONS_ONLINE);
|
||||
break;
|
||||
case ENABLE_TABLE_MARK_REGIONS_ONLINE:
|
||||
Connection connection = env.getMasterServices().getConnection();
|
||||
// we will need to get the tableDescriptor here to see if there is a change in the replica
|
||||
// count
|
||||
TableDescriptor hTableDescriptor =
|
||||
env.getMasterServices().getTableDescriptors().get(tableName);
|
||||
|
||||
// Get the replica count
|
||||
int regionReplicaCount = hTableDescriptor.getRegionReplication();
|
||||
// Get the replica count
|
||||
int regionReplicaCount = hTableDescriptor.getRegionReplication();
|
||||
|
||||
// Get the regions for the table from memory; get both online and offline regions ('true').
|
||||
List<RegionInfo> regionsOfTable =
|
||||
env.getAssignmentManager().getRegionStates().getRegionsOfTable(tableName, true);
|
||||
// Get the regions for the table from memory; get both online and offline regions
|
||||
// ('true').
|
||||
List<RegionInfo> regionsOfTable =
|
||||
env.getAssignmentManager().getRegionStates().getRegionsOfTable(tableName, true);
|
||||
|
||||
if (regionReplicaCount > 1) {
|
||||
int currentMaxReplica = 0;
|
||||
// Check if the regions in memory have replica regions as marked in META table
|
||||
for (RegionInfo regionInfo : regionsOfTable) {
|
||||
|
@ -166,36 +166,33 @@ public class EnableTableProcedure
|
|||
}
|
||||
} else {
|
||||
// the replicasFound is less than the regionReplication
|
||||
LOG.info(
|
||||
"The number of replicas has been changed(increased)."
|
||||
+ " Lets assign the new region replicas. The previous replica count was "
|
||||
+ (currentMaxReplica + 1) + ". The current replica count is "
|
||||
+ regionReplicaCount);
|
||||
LOG.info("The number of replicas has been changed(increased)."
|
||||
+ " Lets assign the new region replicas. The previous replica count was "
|
||||
+ (currentMaxReplica + 1) + ". The current replica count is " + regionReplicaCount);
|
||||
regionsOfTable = RegionReplicaUtil.addReplicas(hTableDescriptor, regionsOfTable,
|
||||
currentMaxReplica + 1, regionReplicaCount);
|
||||
}
|
||||
}
|
||||
// Assign all the table regions. (including region replicas if added).
|
||||
// createAssignProcedure will try to retain old assignments if possible.
|
||||
addChildProcedure(env.getAssignmentManager().createAssignProcedures(regionsOfTable));
|
||||
setNextState(EnableTableState.ENABLE_TABLE_SET_ENABLED_TABLE_STATE);
|
||||
break;
|
||||
case ENABLE_TABLE_SET_ENABLED_TABLE_STATE:
|
||||
setTableStateToEnabled(env, tableName);
|
||||
setNextState(EnableTableState.ENABLE_TABLE_POST_OPERATION);
|
||||
break;
|
||||
case ENABLE_TABLE_POST_OPERATION:
|
||||
postEnable(env, state);
|
||||
return Flow.NO_MORE_STATE;
|
||||
default:
|
||||
throw new UnsupportedOperationException("unhandled state=" + state);
|
||||
// Assign all the table regions. (including region replicas if added).
|
||||
// createAssignProcedure will try to retain old assignments if possible.
|
||||
addChildProcedure(env.getAssignmentManager().createAssignProcedures(regionsOfTable));
|
||||
setNextState(EnableTableState.ENABLE_TABLE_SET_ENABLED_TABLE_STATE);
|
||||
break;
|
||||
case ENABLE_TABLE_SET_ENABLED_TABLE_STATE:
|
||||
setTableStateToEnabled(env, tableName);
|
||||
setNextState(EnableTableState.ENABLE_TABLE_POST_OPERATION);
|
||||
break;
|
||||
case ENABLE_TABLE_POST_OPERATION:
|
||||
postEnable(env, state);
|
||||
return Flow.NO_MORE_STATE;
|
||||
default:
|
||||
throw new UnsupportedOperationException("unhandled state=" + state);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
if (isRollbackSupported(state)) {
|
||||
setFailure("master-enable-table", e);
|
||||
} else {
|
||||
LOG.warn("Retriable error trying to enable table=" + tableName +
|
||||
" (in state=" + state + ")", e);
|
||||
LOG.warn(
|
||||
"Retriable error trying to enable table=" + tableName + " (in state=" + state + ")", e);
|
||||
}
|
||||
}
|
||||
return Flow.HAS_MORE_STATE;
|
||||
|
|
|
@ -22,7 +22,7 @@ import static org.junit.Assert.assertFalse;
|
|||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Matchers.anyObject;
|
||||
import static org.mockito.ArgumentMatchers.anyObject;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.reset;
|
||||
|
@ -68,6 +68,7 @@ import org.slf4j.Logger;
|
|||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.apache.hbase.thirdparty.com.google.common.collect.Lists;
|
||||
import org.apache.hbase.thirdparty.com.google.common.collect.Sets;
|
||||
|
||||
/**
|
||||
* Test {@link org.apache.hadoop.hbase.MetaTableAccessor}.
|
||||
|
@ -438,6 +439,44 @@ public class TestMetaTableAccessor {
|
|||
assertEquals(0, startCodeCell.getValueLength());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMetaLocationForRegionReplicasIsRemovedAtTableDeletion() throws IOException {
|
||||
long regionId = System.currentTimeMillis();
|
||||
RegionInfo primary = RegionInfoBuilder.newBuilder(TableName.valueOf(name.getMethodName()))
|
||||
.setStartKey(HConstants.EMPTY_START_ROW).setEndKey(HConstants.EMPTY_END_ROW).setSplit(false)
|
||||
.setRegionId(regionId).setReplicaId(0).build();
|
||||
|
||||
Table meta = MetaTableAccessor.getMetaHTable(connection);
|
||||
try {
|
||||
List<RegionInfo> regionInfos = Lists.newArrayList(primary);
|
||||
MetaTableAccessor.addRegionsToMeta(connection, regionInfos, 3);
|
||||
MetaTableAccessor.removeRegionReplicasFromMeta(Sets.newHashSet(primary.getRegionName()), 1, 2,
|
||||
connection);
|
||||
Get get = new Get(primary.getRegionName());
|
||||
Result result = meta.get(get);
|
||||
for (int replicaId = 0; replicaId < 3; replicaId++) {
|
||||
Cell serverCell = result.getColumnLatestCell(HConstants.CATALOG_FAMILY,
|
||||
MetaTableAccessor.getServerColumn(replicaId));
|
||||
Cell startCodeCell = result.getColumnLatestCell(HConstants.CATALOG_FAMILY,
|
||||
MetaTableAccessor.getStartCodeColumn(replicaId));
|
||||
Cell stateCell = result.getColumnLatestCell(HConstants.CATALOG_FAMILY,
|
||||
MetaTableAccessor.getRegionStateColumn(replicaId));
|
||||
Cell snCell = result.getColumnLatestCell(HConstants.CATALOG_FAMILY,
|
||||
MetaTableAccessor.getServerNameColumn(replicaId));
|
||||
if (replicaId == 0) {
|
||||
assertNotNull(stateCell);
|
||||
} else {
|
||||
assertNull(serverCell);
|
||||
assertNull(startCodeCell);
|
||||
assertNull(stateCell);
|
||||
assertNull(snCell);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
meta.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMetaLocationForRegionReplicasIsAddedAtTableCreation() throws IOException {
|
||||
long regionId = System.currentTimeMillis();
|
||||
|
|
Loading…
Reference in New Issue