Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HBASE-28443 Return too slow when scanning a table with non-existing REGION_REPLICA_ID #5764

Closed
wants to merge 6 commits into from
Closed
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
update unit test
guluo2016 committed Mar 17, 2024
commit cf6443608770be4803bed169517626d6c0dd720e
Original file line number Diff line number Diff line change
@@ -200,7 +200,9 @@ CompletableFuture<HRegionLocation> getRegionLocation(TableName tableName, byte[]
future
.completeExceptionally(new DoNotRetryIOException("The specified region replica id '"
+ replicaId + "' does not exist, the REGION_REPLICATION of this table "
+ tableName.getNameAsString() + " is " + regionReplicationCount + " ."));
+ tableName.getNameAsString() + " is " + regionReplicationCount + " , this means "
+ "that the maximum region replica id you can specify is "
+ (regionReplicationCount - 1) + "."));
return;
}
// meta region can not be split right now so we always call the same method.
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
package org.apache.hadoop.hbase.client;

import org.apache.hadoop.hbase.DoNotRetryIOException;
import org.apache.hadoop.hbase.HBaseClassTestRule;
import org.apache.hadoop.hbase.HBaseTestingUtil;
import org.apache.hadoop.hbase.HRegionLocation;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.regionserver.HRegion;
import org.apache.hadoop.hbase.testclassification.ClientTests;
import org.apache.hadoop.hbase.testclassification.MediumTests;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.io.IOUtils;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.junit.rules.ExpectedException;
import org.junit.rules.TestName;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

@Category({ MediumTests.class, ClientTests.class })
public class TestAsyncTableRegionLocatorWithRegionReplicaId {
@ClassRule
public static final HBaseClassTestRule CLASS_RULE =
HBaseClassTestRule.forClass(TestAsyncTableRegionLocatorWithRegionReplicaId.class);

@Rule
public TestName name = new TestName();

private ExpectedException exception = ExpectedException.none();

private final static HBaseTestingUtil UTIL = new HBaseTestingUtil();
private static final String ROW = "r1";
private static final byte[] FAMILY = Bytes.toBytes("info");
private static final int REGION_REPLICATION_COUNT = 2;
// region replica id starts from 0
private static final int NON_EXISTING_REGION_REPLICA_ID = REGION_REPLICATION_COUNT;
private static Connection connection;
private static AsyncConnection asyncConn;
private static Admin admin;
private TableName tableName;

@BeforeClass
public static void setUpBeforeClass() throws Exception {
UTIL.startMiniCluster(1);
connection = UTIL.getConnection();
asyncConn = ConnectionFactory.createAsyncConnection(UTIL.getConfiguration()).get();
admin = UTIL.getAdmin();
}

@AfterClass
public static void tearDownAfterClass() throws Exception {
IOUtils.cleanup(null, admin);
IOUtils.cleanup(null, connection);
UTIL.shutdownMiniCluster();
}

@Before
public void setUp() throws Exception {
tableName = TableName.valueOf(name.getMethodName());
ColumnFamilyDescriptor columnFamilyDescriptor =
ColumnFamilyDescriptorBuilder.newBuilder(FAMILY).build();
TableDescriptor tableDescriptor =
TableDescriptorBuilder.newBuilder(tableName).setColumnFamily(columnFamilyDescriptor)
.setRegionReplication(REGION_REPLICATION_COUNT).build();
admin.createTable(tableDescriptor);
UTIL.waitTableAvailable(tableName);
assertTrue(admin.tableExists(tableName));
assertEquals(REGION_REPLICATION_COUNT, tableDescriptor.getRegionReplication());

List<HRegion> regions = UTIL.getHBaseCluster().getRegions(tableName);
assertEquals(REGION_REPLICATION_COUNT, regions.size());

Table table = connection.getTable(tableName);
Put put = new Put(Bytes.toBytes(ROW)).addColumn(FAMILY, Bytes.toBytes("q"),
Bytes.toBytes("test_value"));
table.put(put);
admin.flush(tableName);

Scan scan = new Scan();
ResultScanner rs = table.getScanner(scan);
rs.forEach(r -> assertEquals(ROW, Bytes.toString(r.getRow())));
}

@After
public void tearDown() throws Exception {
UTIL.deleteTable(tableName);
}

@Test
public void testMetaTableRegionLocatorWithRegionReplicaId()
throws ExecutionException, InterruptedException {
AsyncTableRegionLocator locator = asyncConn.getRegionLocator(TableName.META_TABLE_NAME);
CompletableFuture<HRegionLocation>
future = locator.getRegionLocation(tableName.getName(), RegionReplicaUtil.DEFAULT_REPLICA_ID, true);
HRegionLocation hrl = future.get();
assertNotNull(hrl);
}

@Test
public void testMetaTableRegionLocatorWithNonExistingRegionReplicaId() throws InterruptedException {
AsyncTableRegionLocator locator = asyncConn.getRegionLocator(TableName.META_TABLE_NAME);
CompletableFuture<HRegionLocation>
future = locator.getRegionLocation(tableName.getName(), NON_EXISTING_REGION_REPLICA_ID, true);
try {
future.get();
} catch (ExecutionException e) {
assertTrue(e.getCause() instanceof DoNotRetryIOException);
String message = "The specified region replica id '"
+ NON_EXISTING_REGION_REPLICA_ID + "' does not exist, the REGION_REPLICATION of this "
+ "table " + TableName.META_TABLE_NAME.getNameAsString() + " is "
+ TableDescriptorBuilder.DEFAULT_REGION_REPLICATION + ", "
+ "this means that the maximum region replica id you can specify is "
+ (TableDescriptorBuilder.DEFAULT_REGION_REPLICATION - 1) + ".";
assertEquals(message, e.getCause().getMessage());
}
}

@Test
public void testTableRegionLocatorWithRegionReplicaId()
throws ExecutionException, InterruptedException {
AsyncTableRegionLocator locator = asyncConn.getRegionLocator(tableName);
CompletableFuture<HRegionLocation>
future = locator.getRegionLocation(Bytes.toBytes(ROW), RegionReplicaUtil.DEFAULT_REPLICA_ID, true);
HRegionLocation hrl = future.get();
assertNotNull(hrl);
}

@Test
public void testTableRegionLocatorWithNonExistingRegionReplicaId() throws InterruptedException {
AsyncTableRegionLocator locator = asyncConn.getRegionLocator(tableName);
CompletableFuture<HRegionLocation> future = locator.getRegionLocation(Bytes.toBytes(ROW), NON_EXISTING_REGION_REPLICA_ID, true);
try {
future.get();
} catch (ExecutionException e) {
assertTrue(e.getCause() instanceof DoNotRetryIOException);
String message = "The specified region replica id '"
+ NON_EXISTING_REGION_REPLICA_ID + "' does not exist, the REGION_REPLICATION of this "
+ "table " + tableName.getNameAsString() + " is " + REGION_REPLICATION_COUNT + ", "
+ "this means that the maximum region replica id you can specify is "
+ (REGION_REPLICATION_COUNT - 1) + ".";
assertEquals(message, e.getCause().getMessage());
}
}
}
Original file line number Diff line number Diff line change
@@ -22,9 +22,12 @@

import java.io.IOException;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import org.apache.hadoop.hbase.DoNotRetryIOException;
import org.apache.hadoop.hbase.HBaseClassTestRule;
import org.apache.hadoop.hbase.HBaseTestingUtil;
import org.apache.hadoop.hbase.HRegionLocation;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.filter.PrefixFilter;
import org.apache.hadoop.hbase.regionserver.HRegion;
@@ -61,13 +64,15 @@ public class TestScanTableWithReplicationFromClient {
// region replica id starts from 0
private static final int NON_EXISTING_REGION_REPLICA_ID = REGION_REPLICATION_COUNT;
private static Connection connection;
private static AsyncConnection asyncConn;
private static Admin admin;
private TableName tableName;

@BeforeClass
public static void setUpBeforeClass() throws Exception {
UTIL.startMiniCluster(1);
connection = UTIL.getConnection();
asyncConn = ConnectionFactory.createAsyncConnection(UTIL.getConfiguration()).get();
admin = UTIL.getAdmin();
}

@@ -102,7 +107,7 @@ public void setUp() throws Exception {

Scan scan = new Scan();
ResultScanner rs = table.getScanner(scan);
rs.forEach(r -> assertEquals(ROW, r.getRow().toString()));
rs.forEach(r -> assertEquals(ROW, Bytes.toString(r.getRow())));
}

@After
@@ -118,7 +123,7 @@ public void testScanMetaWithRegionReplicaId() throws IOException {
scan.setReplicaId(RegionReplicaUtil.DEFAULT_REPLICA_ID);
scan.setConsistency(Consistency.TIMELINE);
ResultScanner rs = metaTable.getScanner(scan);
rs.forEach(r -> assertTrue(r.getRow().toString().contains(tableName.getNameAsString())));
rs.forEach(r -> assertTrue(Bytes.toString(r.getRow()).contains(tableName.getNameAsString())));
}

@Test
@@ -138,16 +143,24 @@ public void testScanTableWithRegionReplicaId() throws IOException {
scan.setReplicaId(RegionReplicaUtil.DEFAULT_REPLICA_ID);
scan.setConsistency(Consistency.TIMELINE);
ResultScanner rs = table.getScanner(scan);
rs.forEach(r -> assertEquals(ROW, r.getRow().toString()));
rs.forEach(r -> assertEquals(ROW, Bytes.toString(r.getRow())));
}

@Test
public void testScanTableWithNonExistingRegionReplicaId() throws IOException {
Table table = connection.getTable(tableName);
Scan scan = new Scan();
scan.setReplicaId(NON_EXISTING_REGION_REPLICA_ID);
scan.setConsistency(Consistency.TIMELINE);
exception.expect(DoNotRetryIOException.class);
table.getScanner(scan);
public void testScanTableWithNonExistingRegionReplicaId()
throws InterruptedException {
AsyncTableRegionLocator locator = asyncConn.getRegionLocator(tableName);
CompletableFuture<HRegionLocation> future = locator.getRegionLocation(Bytes.toBytes(ROW), NON_EXISTING_REGION_REPLICA_ID, true);
try {
future.get();
} catch (ExecutionException e) {
assertTrue(e.getCause() instanceof DoNotRetryIOException);
String message = "The specified region replica id '"
+ NON_EXISTING_REGION_REPLICA_ID + "' does not exist, the REGION_REPLICATION of this "
+ "table " + tableName.getNameAsString() + " is " + REGION_REPLICATION_COUNT + ", "
+ "this means that the maximum region replica id you can specify is "
+ (REGION_REPLICATION_COUNT - 1) + ".";
assertEquals(message, e.getCause().getMessage());
}
}
}