Skip to content

Commit b444889

Browse files
authored
Merge pull request #258 from oceanbase/fix_region_metric_slow
Fix region metric slow and region name does not match with region locator
2 parents 4bb2291 + ce6bfb2 commit b444889

File tree

3 files changed

+88
-52
lines changed

3 files changed

+88
-52
lines changed

src/main/java/com/alipay/oceanbase/hbase/util/OHRegionLocatorExecutor.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -188,10 +188,13 @@ private OHRegionLocator createRangePartitionLocator(
188188
i
189189
);
190190
int boundIndex = i / replicaDict.size();
191+
long tabletId = Integer.toUnsignedLong((Integer) partition.get(1));
191192
final HRegionInfo regionInfo = new HRegionInfo(
192193
TableName.valueOf(tableName),
193194
startKeys[boundIndex],
194-
endKeys[boundIndex]
195+
endKeys[boundIndex],
196+
false,
197+
tabletId
195198
);
196199
HRegionLocation location = new HRegionLocation(regionInfo, serverName, i);
197200
Boolean role = (int) partition.get(4) == 1;
@@ -230,10 +233,13 @@ private OHRegionLocator createHashPartitionLocator(
230233
(int) hostInfo.get(1),
231234
i
232235
);
236+
long tabletId = Integer.toUnsignedLong((Integer) partition.get(1));
233237
final HRegionInfo regionInfo = new HRegionInfo(
234238
TableName.valueOf(tableName),
235239
startKeys[0],
236-
endKeys[0]
240+
endKeys[0],
241+
false,
242+
tabletId
237243
);
238244
HRegionLocation location = new HRegionLocation(regionInfo, serverName, i);
239245
Boolean role = (int) partition.get(4) == 1;

src/main/java/com/alipay/oceanbase/hbase/util/OHRegionMetricsExecutor.java

Lines changed: 50 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
package com.alipay.oceanbase.hbase.util;
1919

20+
import com.alipay.oceanbase.rpc.exception.ObTableUnexpectedException;
2021
import com.fasterxml.jackson.core.type.TypeReference;
2122
import com.fasterxml.jackson.databind.JsonNode;
2223
import com.fasterxml.jackson.databind.ObjectMapper;
@@ -25,8 +26,8 @@
2526
import com.alipay.oceanbase.rpc.meta.ObTableMetaRequest;
2627
import com.alipay.oceanbase.rpc.meta.ObTableMetaResponse;
2728
import com.alipay.oceanbase.rpc.meta.ObTableRpcMetaType;
28-
import org.apache.hadoop.hbase.RegionMetrics;
29-
import org.apache.hadoop.hbase.Size;
29+
import org.apache.hadoop.hbase.*;
30+
import org.apache.hadoop.hbase.client.Table;
3031

3132
import java.io.IOException;
3233
import java.util.*;
@@ -46,11 +47,10 @@ public ObTableRpcMetaType getMetaType() throws IOException {
4647
/*
4748
* {
4849
tableName: "tablegroup_name",
49-
regionList:{
50-
"regions": [200051, 200052, 200053, 200191, 200192, 200193, ...],
51-
"memTableSize":[123, 321, 321, 123, 321, 321, ...],
52-
"ssTableSize":[5122, 4111, 5661, 5122, 4111, 5661, ...]
53-
}
50+
"regions": [200051, 200052, 200053, 200191, 200192, 200193, ...],
51+
"memTableSize":[123, 321, 321, 123, 321, 321, ...],
52+
"ssTableSize":[5122, 4111, 5661, 5122, 4111, 5661, ...],
53+
"boundary":["rowkey1", "rowkey2", "rowkey3", ..., "rowkey100", "rowkey101", "rowkey102", ...]
5454
}
5555
* */
5656
@Override
@@ -61,21 +61,56 @@ public List<RegionMetrics> parse(ObTableMetaResponse response) throws IOExceptio
6161
JsonNode tableGroupNameNode = Optional.<JsonNode>ofNullable(jsonMap.get("tableName"))
6262
.orElseThrow(() -> new IOException("tableName is null"));
6363
String tableGroupName = tableGroupNameNode.asText();
64-
JsonNode regionListNode = Optional.<JsonNode>ofNullable(jsonMap.get("regionList"))
65-
.orElseThrow(() -> new IOException("regionList is null"));
66-
List<Integer> regions = Optional.<List<Integer>>ofNullable(objectMapper.convertValue(regionListNode.get("regions"), new TypeReference<List<Integer>>() {}))
64+
List<Integer> regions = Optional.<List<Integer>>ofNullable(objectMapper.convertValue(jsonMap.get("regions"), new TypeReference<List<Integer>>() {}))
6765
.orElseThrow(() -> new IOException("regions is null"));
68-
List<Integer> memTableSizeList = Optional.<List<Integer>>ofNullable(objectMapper.convertValue(regionListNode.get("memTableSize"), new TypeReference<List<Integer>>() {}))
66+
List<Long> memTableSizeList = Optional.<List<Long>>ofNullable(objectMapper.convertValue(jsonMap.get("memTableSize"), new TypeReference<List<Long>>() {}))
6967
.orElseThrow(() -> new IOException("memTableSize is null"));
70-
List<Integer> ssTableSizeList = Optional.<List<Integer>>ofNullable(objectMapper.convertValue(regionListNode.get("ssTableSize"), new TypeReference<List<Integer>>() {}))
68+
List<Long> ssTableSizeList = Optional.<List<Long>>ofNullable(objectMapper.convertValue(jsonMap.get("ssTableSize"), new TypeReference<List<Long>>() {}))
7169
.orElseThrow(() -> new IOException("ssTableSize is null"));
70+
List<String> boundaryList = Optional.<List<String>>ofNullable(objectMapper.convertValue(jsonMap.get("boundary"), new TypeReference<List<String>>() {}))
71+
.orElseThrow(() -> new IOException("boundary is null"));
72+
boolean isHashLikePartition = boundaryList.stream().allMatch(String::isEmpty);
73+
boolean isRangeLikePartition = boundaryList.stream().noneMatch(String::isEmpty);
74+
if (!isRangeLikePartition && !isHashLikePartition) {
75+
// there are empty string and non-empty string in boundary, which is illegal for ADAPTIVE tablegroup
76+
throw new ObTableUnexpectedException("tablegroup {" + tableGroupName + "} has tables with different partition types");
77+
}
78+
byte[][] startKeys = new byte[regions.size()][];
79+
byte[][] endKeys = new byte[regions.size()][];
80+
if (isHashLikePartition) {
81+
startKeys[0] = HConstants.EMPTY_BYTE_ARRAY;
82+
endKeys[0] = HConstants.EMPTY_BYTE_ARRAY;
83+
} else {
84+
final List<byte[]> startKeysList = new ArrayList<>();
85+
final List<byte[]> endKeysList = new ArrayList<>();
86+
for (int i = 0; i < boundaryList.size(); ++i) {
87+
if (i == 0) {
88+
startKeysList.add(HConstants.EMPTY_BYTE_ARRAY);
89+
endKeysList.add(boundaryList.get(i).getBytes());
90+
} else if (i == boundaryList.size() - 1) {
91+
startKeysList.add(boundaryList.get(i - 1).getBytes());
92+
endKeysList.add(HConstants.EMPTY_BYTE_ARRAY);
93+
} else {
94+
startKeysList.add(boundaryList.get(i - 1).getBytes());
95+
endKeysList.add(boundaryList.get(i).getBytes());
96+
}
97+
}
98+
startKeys = startKeysList.toArray(new byte[0][]);
99+
}
72100
List<RegionMetrics> metricsList = new ArrayList<>();
73-
if (regions.isEmpty() || regions.size() != memTableSizeList.size() || memTableSizeList.size() != ssTableSizeList.size()) {
101+
if (regions.isEmpty() || regions.size() != memTableSizeList.size()
102+
|| memTableSizeList.size() != ssTableSizeList.size()
103+
|| ssTableSizeList.size() != startKeys.length) {
74104
throw new IOException("size length has to be the same");
75105
}
76106
for (int i = 0; i < regions.size(); ++i) {
77-
String name_str = Integer.toString(regions.get(i));
78-
byte[] name = name_str.getBytes();
107+
byte[] startKey = isHashLikePartition ? startKeys[0] : startKeys[i];
108+
byte[] name = HRegionInfo.createRegionName(
109+
TableName.valueOf(tableGroupName),
110+
startKey,
111+
regions.get(i),
112+
HRegionInfo.DEFAULT_REPLICA_ID, true
113+
);
79114
Size storeFileSize = new Size(((double) ssTableSizeList.get(i)) / (1024 * 1024) , Size.Unit.MEGABYTE); // The unit in original HBase is MEGABYTE, for us it is BYTE
80115
Size memStoreSize = new Size(((double) memTableSizeList.get(i)) / (1024 * 1024), Size.Unit.MEGABYTE); // The unit in original HBase is MEGABYTE, for us it is BYTE
81116
OHRegionMetrics ohRegionMetrics = new OHRegionMetrics(tableGroupName, name, storeFileSize, memStoreSize);

src/test/java/com/alipay/oceanbase/hbase/OHTableAdminInterfaceTest.java

Lines changed: 30 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -515,72 +515,72 @@ public void testAdminGetRegionMetrics() throws Exception {
515515
" `T` bigint(20) NOT NULL,\n" +
516516
" `V` varbinary(1024) DEFAULT NULL,\n" +
517517
" PRIMARY KEY (`K`, `Q`, `T`)\n" +
518-
") TABLEGROUP = test_get_region_metrics PARTITION BY KEY(`K`) PARTITIONS 3;\n" +
518+
") TABLEGROUP = test_get_region_metrics PARTITION BY KEY(`K`) PARTITIONS 10;\n" +
519519
"\n" +
520520
"CREATE TABLE IF NOT EXISTS `test_get_region_metrics$cf2` (\n" +
521521
" `K` varbinary(1024) NOT NULL,\n" +
522522
" `Q` varbinary(256) NOT NULL,\n" +
523523
" `T` bigint(20) NOT NULL,\n" +
524524
" `V` varbinary(1024) DEFAULT NULL,\n" +
525525
" PRIMARY KEY (`K`, `Q`, `T`)\n" +
526-
") TABLEGROUP = test_get_region_metrics PARTITION BY KEY(`K`) PARTITIONS 3;\n" +
526+
") TABLEGROUP = test_get_region_metrics PARTITION BY KEY(`K`) PARTITIONS 10;\n" +
527527
"\n" +
528528
"CREATE TABLE IF NOT EXISTS `test_get_region_metrics$cf3` (\n" +
529529
" `K` varbinary(1024) NOT NULL,\n" +
530530
" `Q` varbinary(256) NOT NULL,\n" +
531531
" `T` bigint(20) NOT NULL,\n" +
532532
" `V` varbinary(1024) DEFAULT NULL,\n" +
533533
" PRIMARY KEY (`K`, `Q`, `T`)\n" +
534-
") TABLEGROUP = test_get_region_metrics PARTITION BY KEY(`K`) PARTITIONS 3;\n" +
534+
") TABLEGROUP = test_get_region_metrics PARTITION BY KEY(`K`) PARTITIONS 10;\n" +
535535
"\n" +
536-
"CREATE DATABASE IF NOT EXISTS `get_region`;\n" +
537-
"use `get_region`;\n" +
538-
"CREATE TABLEGROUP IF NOT EXISTS `get_region:test_multi_cf` SHARDING = 'ADAPTIVE';\n" +
539-
"CREATE TABLE IF NOT EXISTS `get_region:test_multi_cf$cf1` (\n" +
536+
"CREATE TABLEGROUP IF NOT EXISTS test_no_part SHARDING = 'ADAPTIVE';\n" +
537+
"CREATE TABLE IF NOT EXISTS `test_no_part$cf1` (\n" +
540538
" `K` varbinary(1024) NOT NULL,\n" +
541539
" `Q` varbinary(256) NOT NULL,\n" +
542540
" `T` bigint(20) NOT NULL,\n" +
543541
" `V` varbinary(1024) DEFAULT NULL,\n" +
544-
" PRIMARY KEY (`K`, `Q`, `T`)\n" +
545-
") TABLEGROUP = `get_region:test_multi_cf` PARTITION BY KEY(`K`) PARTITIONS 3;\n" +
546-
"CREATE TABLE IF NOT EXISTS `get_region:test_multi_cf$cf2` (\n" +
542+
" PRIMARY KEY (`K`, `Q`, `T`)\n" +
543+
") TABLEGROUP = test_no_part;\n" +
544+
"CREATE TABLE IF NOT EXISTS `test_no_part$cf2` (\n" +
547545
" `K` varbinary(1024) NOT NULL,\n" +
548546
" `Q` varbinary(256) NOT NULL,\n" +
549547
" `T` bigint(20) NOT NULL,\n" +
550548
" `V` varbinary(1024) DEFAULT NULL,\n" +
551549
" PRIMARY KEY (`K`, `Q`, `T`)\n" +
552-
") TABLEGROUP = `get_region:test_multi_cf` PARTITION BY KEY(`K`) PARTITIONS 3;\n" +
553-
"CREATE TABLE IF NOT EXISTS `get_region:test_multi_cf$cf3` (\n" +
550+
") TABLEGROUP = test_no_part;\n" +
551+
"CREATE TABLE IF NOT EXISTS `test_no_part$cf3` (\n" +
554552
" `K` varbinary(1024) NOT NULL,\n" +
555553
" `Q` varbinary(256) NOT NULL,\n" +
556554
" `T` bigint(20) NOT NULL,\n" +
557555
" `V` varbinary(1024) DEFAULT NULL,\n" +
558556
" PRIMARY KEY (`K`, `Q`, `T`)\n" +
559-
") TABLEGROUP = `get_region:test_multi_cf` PARTITION BY KEY(`K`) PARTITIONS 3;" +
560-
"USE `test`;" +
561-
"CREATE TABLEGROUP IF NOT EXISTS test_no_part SHARDING = 'ADAPTIVE';" +
562-
"CREATE TABLE IF NOT EXISTS `test_no_part$cf1` (\n" +
557+
") TABLEGROUP = test_no_part;\n" +
558+
"CREATE DATABASE IF NOT EXISTS `get_region`;\n" +
559+
"use `get_region`;\n" +
560+
"CREATE TABLEGROUP IF NOT EXISTS `get_region:test_multi_cf` SHARDING = 'ADAPTIVE';\n" +
561+
"CREATE TABLE IF NOT EXISTS `get_region:test_multi_cf$cf1` (\n" +
563562
" `K` varbinary(1024) NOT NULL,\n" +
564563
" `Q` varbinary(256) NOT NULL,\n" +
565564
" `T` bigint(20) NOT NULL,\n" +
566565
" `V` varbinary(1024) DEFAULT NULL,\n" +
567566
" PRIMARY KEY (`K`, `Q`, `T`)\n" +
568-
") TABLEGROUP = `test_no_part`;\n" +
569-
"CREATE TABLE IF NOT EXISTS `test_no_part$cf2` (\n" +
567+
") TABLEGROUP = `get_region:test_multi_cf` PARTITION BY KEY(`K`) PARTITIONS 3;\n" +
568+
"CREATE TABLE IF NOT EXISTS `get_region:test_multi_cf$cf2` (\n" +
570569
" `K` varbinary(1024) NOT NULL,\n" +
571570
" `Q` varbinary(256) NOT NULL,\n" +
572571
" `T` bigint(20) NOT NULL,\n" +
573572
" `V` varbinary(1024) DEFAULT NULL,\n" +
574573
" PRIMARY KEY (`K`, `Q`, `T`)\n" +
575-
") TABLEGROUP = `test_no_part`;\n" +
576-
"CREATE TABLE IF NOT EXISTS `test_no_part$cf3` (\n" +
574+
") TABLEGROUP = `get_region:test_multi_cf` PARTITION BY KEY(`K`) PARTITIONS 3;\n" +
575+
"CREATE TABLE IF NOT EXISTS `get_region:test_multi_cf$cf3` (\n" +
577576
" `K` varbinary(1024) NOT NULL,\n" +
578577
" `Q` varbinary(256) NOT NULL,\n" +
579578
" `T` bigint(20) NOT NULL,\n" +
580579
" `V` varbinary(1024) DEFAULT NULL,\n" +
581580
" PRIMARY KEY (`K`, `Q`, `T`)\n" +
582-
") TABLEGROUP = `test_no_part`;");
581+
") TABLEGROUP = `get_region:test_multi_cf` PARTITION BY KEY(`K`) PARTITIONS 3;");
583582
st.close();
583+
conn.close();
584584
String tablegroup1 = "test_get_region_metrics";
585585
String tablegroup2 = "get_region:test_multi_cf";
586586
Configuration conf = ObHTableTestUtil.newConfiguration();
@@ -594,11 +594,11 @@ public void testAdminGetRegionMetrics() throws Exception {
594594
Assert.assertTrue(thrown.getCause() instanceof ObTableException);
595595
Assert.assertEquals(ResultCodes.OB_KV_HBASE_TABLE_NOT_EXISTS.errorCode, ((ObTableException) thrown.getCause()).getErrorCode());
596596

597-
// test use serverName without tableName to get region metrics
598-
assertThrows(FeatureNotSupportedException.class,
599-
() -> {
600-
admin.getRegionMetrics(ServerName.valueOf("localhost,1,1"));
601-
});
597+
// test use serverName without tableName to get region metrics
598+
assertThrows(FeatureNotSupportedException.class,
599+
() -> {
600+
admin.getRegionMetrics(ServerName.valueOf("localhost,1,1"));
601+
});
602602

603603
// test single-thread getRegionMetrics after writing
604604
batchInsert(10000, tablegroup1);
@@ -607,7 +607,7 @@ public void testAdminGetRegionMetrics() throws Exception {
607607
List<RegionMetrics> metrics = admin.getRegionMetrics(ServerName.valueOf("localhost,1,1"), TableName.valueOf(tablegroup1));
608608
long cost = System.currentTimeMillis() - start;
609609
System.out.println("get region metrics time usage: " + cost + "ms, tablegroup: " + tablegroup1);
610-
assertEquals(9, metrics.size());
610+
assertEquals(10, metrics.size());
611611

612612
// test getRegionMetrics concurrently reading while writing
613613
ExecutorService executorService = Executors.newFixedThreadPool(10);
@@ -625,7 +625,7 @@ public void testAdminGetRegionMetrics() throws Exception {
625625
regionMetrics = admin.getRegionMetrics(null, TableName.valueOf(tablegroup1));
626626
long thrCost = System.currentTimeMillis() - thrStart;
627627
System.out.println("task: " + taskId + ", get region metrics time usage: " + thrCost + "ms, tablegroup: " + tablegroup1);
628-
if (regionMetrics.size() != 9) {
628+
if (regionMetrics.size() != 10) {
629629
throw new ObTableGetException(
630630
"the number of region metrics does not match the number of tablets, the number of region metrics: " + regionMetrics.size());
631631
}
@@ -634,7 +634,7 @@ public void testAdminGetRegionMetrics() throws Exception {
634634
regionMetrics = admin.getRegionMetrics(null, TableName.valueOf(tablegroup2));
635635
long thrCost = System.currentTimeMillis() - thrStart;
636636
System.out.println("task: " + taskId + ", get region metrics time usage: " + thrCost + "ms, tablegroup: " + tablegroup2);
637-
if (regionMetrics.size() != 9) {
637+
if (regionMetrics.size() != 3) {
638638
throw new ObTableGetException(
639639
"the number of region metrics does not match the number of tablets, the number of region metrics: " + regionMetrics.size());
640640
}
@@ -1624,12 +1624,7 @@ public void testHbaseDDLException() throws Exception {
16241624
}
16251625

16261626
// 11. check table exists from an uncreated namespace
1627-
try {
1628-
admin.tableExists(TableName.valueOf("n101:t1"));
1629-
fail();
1630-
} catch (Exception e) {
1631-
Assert.assertEquals(e.getClass(), NamespaceNotFoundException.class);
1632-
}
1627+
Assert.assertFalse(admin.tableExists(TableName.valueOf("n101:t1")));
16331628

16341629
}
16351630

0 commit comments

Comments
 (0)