You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by st...@apache.org on 2020/09/08 19:02:28 UTC
[hbase] branch branch-2 updated: HBASE-24995: MetaFixer fails to
fix overlaps when multiple tables have overlaps (#2361)
This is an automated email from the ASF dual-hosted git repository.
stack pushed a commit to branch branch-2
in repository https://gitbox.apache.org/repos/asf/hbase.git
The following commit(s) were added to refs/heads/branch-2 by this push:
new 672bd1b HBASE-24995: MetaFixer fails to fix overlaps when multiple tables have overlaps (#2361)
672bd1b is described below
commit 672bd1b3a84bfe0c3c4fd9ff984dffadd3e8f2d6
Author: Mohammad Arshad <ar...@apache.org>
AuthorDate: Wed Sep 9 00:30:44 2020 +0530
HBASE-24995: MetaFixer fails to fix overlaps when multiple tables have overlaps (#2361)
Signed-off-by: stack <st...@apache.org>
---
.../org/apache/hadoop/hbase/master/MetaFixer.java | 28 +++++++++++++---
.../apache/hadoop/hbase/master/TestMetaFixer.java | 39 +++++++++++++++++++++-
2 files changed, 62 insertions(+), 5 deletions(-)
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MetaFixer.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MetaFixer.java
index 9f10791..68501da 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MetaFixer.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MetaFixer.java
@@ -19,9 +19,11 @@ package org.apache.hadoop.hbase.master;
import java.io.IOException;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
+import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.SortedSet;
@@ -39,6 +41,8 @@ import org.apache.hadoop.hbase.master.assignment.TransitRegionStateProcedure;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.hbase.util.Pair;
import org.apache.hadoop.hbase.util.ServerRegionReplicaUtil;
+import org.apache.hbase.thirdparty.com.google.common.collect.ArrayListMultimap;
+import org.apache.hbase.thirdparty.com.google.common.collect.ListMultimap;
import org.apache.yetus.audience.InterfaceAudience;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -231,16 +235,18 @@ class MetaFixer {
/**
* Fix overlaps noted in CJ consistency report.
*/
- void fixOverlaps(CatalogJanitor.Report report) throws IOException {
+ List<Long> fixOverlaps(CatalogJanitor.Report report) throws IOException {
+ List<Long> pidList = new ArrayList<>();
for (Set<RegionInfo> regions: calculateMerges(maxMergeCount, report.getOverlaps())) {
RegionInfo [] regionsArray = regions.toArray(new RegionInfo [] {});
try {
- this.masterServices.mergeRegions(regionsArray,
- true, HConstants.NO_NONCE, HConstants.NO_NONCE);
+ pidList.add(this.masterServices
+ .mergeRegions(regionsArray, true, HConstants.NO_NONCE, HConstants.NO_NONCE));
} catch (MergeRegionException mre) {
LOG.warn("Failed overlap fix of {}", regionsArray, mre);
}
}
+ return pidList;
}
/**
@@ -258,6 +264,21 @@ class MetaFixer {
return Collections.emptyList();
}
List<SortedSet<RegionInfo>> merges = new ArrayList<>();
+ // First group overlaps by table then calculate merge table by table.
+ ListMultimap<TableName, Pair<RegionInfo, RegionInfo>> overlapGroups =
+ ArrayListMultimap.create();
+ for (Pair<RegionInfo, RegionInfo> pair : overlaps) {
+ overlapGroups.put(pair.getFirst().getTable(), pair);
+ }
+ for (Map.Entry<TableName, Collection<Pair<RegionInfo, RegionInfo>>> entry : overlapGroups
+ .asMap().entrySet()) {
+ calculateTableMerges(maxMergeCount, merges, entry.getValue());
+ }
+ return merges;
+ }
+
+ private static void calculateTableMerges(int maxMergeCount, List<SortedSet<RegionInfo>> merges,
+ Collection<Pair<RegionInfo, RegionInfo>> overlaps) {
SortedSet<RegionInfo> currentMergeSet = new TreeSet<>();
HashSet<RegionInfo> regionsInMergeSet = new HashSet<>();
RegionInfo regionInfoWithlargestEndKey = null;
@@ -301,7 +322,6 @@ class MetaFixer {
regionInfoWithlargestEndKey);
}
merges.add(currentMergeSet);
- return merges;
}
/**
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/TestMetaFixer.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/TestMetaFixer.java
index fe329f3..d5d8cd7 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/TestMetaFixer.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/TestMetaFixer.java
@@ -44,6 +44,7 @@ import org.apache.hadoop.hbase.master.assignment.GCMultipleMergedRegionsProcedur
import org.apache.hadoop.hbase.master.assignment.RegionStates;
import org.apache.hadoop.hbase.master.procedure.MasterProcedureEnv;
import org.apache.hadoop.hbase.procedure2.ProcedureExecutor;
+import org.apache.hadoop.hbase.procedure2.ProcedureTestingUtility;
import org.apache.hadoop.hbase.testclassification.LargeTests;
import org.apache.hadoop.hbase.testclassification.MasterTests;
import org.apache.hadoop.hbase.util.Bytes;
@@ -169,7 +170,8 @@ public class TestMetaFixer {
Collections.singletonList(MetaTableAccessor.makePutFromRegionInfo(overlapRegion,
System.currentTimeMillis())));
// TODO: Add checks at assign time to PREVENT being able to assign over existing assign.
- services.getAssignmentManager().assign(overlapRegion);
+ long assign = services.getAssignmentManager().assign(overlapRegion);
+ ProcedureTestingUtility.waitProcedures(services.getMasterProcedureExecutor(), assign);
return overlapRegion;
}
@@ -243,6 +245,41 @@ public class TestMetaFixer {
}
@Test
+ public void testMultipleTableOverlaps() throws Exception {
+ TableName t1 = TableName.valueOf("t1");
+ TableName t2 = TableName.valueOf("t2");
+ TEST_UTIL.createMultiRegionTable(t1, new byte[][] { HConstants.CATALOG_FAMILY });
+ TEST_UTIL.createMultiRegionTable(t2, new byte[][] { HConstants.CATALOG_FAMILY });
+ TEST_UTIL.waitTableAvailable(t2);
+
+ HMaster services = TEST_UTIL.getHBaseCluster().getMaster();
+ services.getCatalogJanitor().scan();
+ CatalogJanitor.Report report = services.getCatalogJanitor().getLastReport();
+ assertTrue(report.isEmpty());
+
+ // Make a simple overlap for t1
+ List<RegionInfo> ris = MetaTableAccessor.getTableRegions(TEST_UTIL.getConnection(), t1);
+ makeOverlap(services, ris.get(1), ris.get(2));
+ // Make a simple overlap for t2
+ ris = MetaTableAccessor.getTableRegions(TEST_UTIL.getConnection(), t2);
+ makeOverlap(services, ris.get(1), ris.get(2));
+
+ services.getCatalogJanitor().scan();
+ report = services.getCatalogJanitor().getLastReport();
+ assertEquals("Region overlaps count does not match.", 4, report.getOverlaps().size());
+
+ MetaFixer fixer = new MetaFixer(services);
+ List<Long> longs = fixer.fixOverlaps(report);
+ long[] procIds = longs.stream().mapToLong(l -> l).toArray();
+ ProcedureTestingUtility.waitProcedures(services.getMasterProcedureExecutor(), procIds);
+
+ // After fix, verify no overlaps are left.
+ services.getCatalogJanitor().scan();
+ report = services.getCatalogJanitor().getLastReport();
+ assertTrue("After fix there should not have been any overlaps.", report.isEmpty());
+ }
+
+ @Test
public void testOverlapWithSmallMergeCount() throws Exception {
TableName tn = TableName.valueOf(this.name.getMethodName());
try {