Document usage of closed token intervals in manual compaction

patch by Andrés de la Peña; reviewed by Ekaterina Dimitrova for CASSANDRA-17575
This commit is contained in:
Andrés de la Peña 2022-07-27 12:50:31 +01:00
parent eb5eda76c5
commit 4e410fc46d
7 changed files with 57 additions and 19 deletions

View File

@ -1,4 +1,5 @@
3.11.14 3.11.14
* Document usage of closed token intervals in manual compaction (CASSANDRA-17575)
* Creating of a keyspace on insufficient number of replicas should filter out gosspping-only members (CASSANDRA-17759) * Creating of a keyspace on insufficient number of replicas should filter out gosspping-only members (CASSANDRA-17759)
* Only use statically defined subcolumns when determining column definition for supercolumn cell (CASSANDRA-14113) * Only use statically defined subcolumns when determining column definition for supercolumn cell (CASSANDRA-14113)
Merged from 3.0: Merged from 3.0:

View File

@ -49,7 +49,12 @@ public interface ColumnFamilyStoreMBean
public void forceMajorCompaction(boolean splitOutput) throws ExecutionException, InterruptedException; public void forceMajorCompaction(boolean splitOutput) throws ExecutionException, InterruptedException;
/** /**
* force a major compaction of specified key range in this column family * Forces a major compaction of specified token ranges in this column family.
* <p>
* The token ranges will be interpreted as closed intervals to match the closed interval defined by the first and
* last keys of a sstable, even though the {@link Range} class is suppossed to be half-open by definition.
*
* @param tokenRanges The token ranges to be compacted, interpreted as closed intervals.
*/ */
public void forceCompactionForTokenRange(Collection<Range<Token>> tokenRanges) throws ExecutionException, InterruptedException; public void forceCompactionForTokenRange(Collection<Range<Token>> tokenRanges) throws ExecutionException, InterruptedException;
/** /**

View File

@ -812,6 +812,15 @@ public class CompactionManager implements CompactionManagerMBean
return futures; return futures;
} }
/**
* Forces a major compaction of specified token ranges of the specified column family.
* <p>
* The token ranges will be interpreted as closed intervals to match the closed interval defined by the first and
* last keys of a sstable, even though the {@link Range} class is suppossed to be half-open by definition.
*
* @param cfStore The column family store to be compacted.
* @param ranges The token ranges to be compacted, interpreted as closed intervals.
*/
public void forceCompactionForTokenRange(ColumnFamilyStore cfStore, Collection<Range<Token>> ranges) public void forceCompactionForTokenRange(ColumnFamilyStore cfStore, Collection<Range<Token>> ranges)
{ {
Callable<Collection<AbstractCompactionTask>> taskCreator = () -> { Callable<Collection<AbstractCompactionTask>> taskCreator = () -> {
@ -849,6 +858,12 @@ public class CompactionManager implements CompactionManagerMBean
FBUtilities.waitOnFuture(executor.submitIfRunning(runnable, "force compaction for token range")); FBUtilities.waitOnFuture(executor.submitIfRunning(runnable, "force compaction for token range"));
} }
/**
* Returns the sstables of the specified column family store that intersect with the specified token ranges.
* <p>
* The token ranges will be interpreted as closed intervals to match the closed interval defined by the first and
* last keys of a sstable, even though the {@link Range} class is suppossed to be half-open by definition.
*/
private static Collection<SSTableReader> sstablesInBounds(ColumnFamilyStore cfs, Collection<Range<Token>> tokenRangeCollection) private static Collection<SSTableReader> sstablesInBounds(ColumnFamilyStore cfs, Collection<Range<Token>> tokenRangeCollection)
{ {
final Set<SSTableReader> sstables = new HashSet<>(); final Set<SSTableReader> sstables = new HashSet<>();

View File

@ -265,8 +265,14 @@ public interface StorageServiceMBean extends NotificationEmitter
@Deprecated @Deprecated
public int relocateSSTables(String keyspace, String ... cfnames) throws IOException, ExecutionException, InterruptedException; public int relocateSSTables(String keyspace, String ... cfnames) throws IOException, ExecutionException, InterruptedException;
public int relocateSSTables(int jobs, String keyspace, String ... cfnames) throws IOException, ExecutionException, InterruptedException; public int relocateSSTables(int jobs, String keyspace, String ... cfnames) throws IOException, ExecutionException, InterruptedException;
/** /**
* Forces major compaction of specified token range in a single keyspace * Forces major compaction of specified token range in a single keyspace.
*
* @param keyspaceName the name of the keyspace to be compacted
* @param startToken the token at which the compaction range starts (inclusive)
* @param endToken the token at which compaction range ends (inclusive)
* @param tableNames the names of the tables to be compacted
*/ */
public void forceKeyspaceCompactionForTokenRange(String keyspaceName, String startToken, String endToken, String... tableNames) throws IOException, ExecutionException, InterruptedException; public void forceKeyspaceCompactionForTokenRange(String keyspaceName, String startToken, String endToken, String... tableNames) throws IOException, ExecutionException, InterruptedException;

View File

@ -397,6 +397,14 @@ public class NodeProbe implements AutoCloseable
ssProxy.relocateSSTables(jobs, keyspace, cfnames); ssProxy.relocateSSTables(jobs, keyspace, cfnames);
} }
/**
* Forces major compaction of specified token range in a single keyspace.
*
* @param keyspaceName the name of the keyspace to be compacted
* @param startToken the token at which the compaction range starts (inclusive)
* @param endToken the token at which compaction range ends (inclusive)
* @param tableNames the names of the tables to be compacted
*/
public void forceKeyspaceCompactionForTokenRange(String keyspaceName, final String startToken, final String endToken, String... tableNames) throws IOException, ExecutionException, InterruptedException public void forceKeyspaceCompactionForTokenRange(String keyspaceName, final String startToken, final String endToken, String... tableNames) throws IOException, ExecutionException, InterruptedException
{ {
ssProxy.forceKeyspaceCompactionForTokenRange(keyspaceName, startToken, endToken, tableNames); ssProxy.forceKeyspaceCompactionForTokenRange(keyspaceName, startToken, endToken, tableNames);

View File

@ -41,10 +41,10 @@ public class Compact extends NodeToolCmd
@Option(title = "user-defined", name = {"--user-defined"}, description = "Use --user-defined to submit listed files for user-defined compaction") @Option(title = "user-defined", name = {"--user-defined"}, description = "Use --user-defined to submit listed files for user-defined compaction")
private boolean userDefined = false; private boolean userDefined = false;
@Option(title = "start_token", name = {"-st", "--start-token"}, description = "Use -st to specify a token at which the compaction range starts") @Option(title = "start_token", name = {"-st", "--start-token"}, description = "Use -st to specify a token at which the compaction range starts (inclusive)")
private String startToken = EMPTY; private String startToken = EMPTY;
@Option(title = "end_token", name = {"-et", "--end-token"}, description = "Use -et to specify a token at which compaction range ends") @Option(title = "end_token", name = {"-et", "--end-token"}, description = "Use -et to specify a token at which compaction range ends (inclusive)")
private String endToken = EMPTY; private String endToken = EMPTY;

View File

@ -385,12 +385,10 @@ public class LeveledCompactionStrategyTest
assertFalse(repaired.manifest.getLevel(1).contains(sstable2)); assertFalse(repaired.manifest.getLevel(1).contains(sstable2));
} }
@Test @Test
public void testTokenRangeCompaction() throws Exception public void testTokenRangeCompaction() throws Exception
{ {
// Remove any existing data so we can start out clean with predictable number of sstables // Remove any existing data, so we can start out clean with predictable number of sstables
cfs.truncateBlocking(); cfs.truncateBlocking();
// Disable auto compaction so cassandra does not compact // Disable auto compaction so cassandra does not compact
@ -400,15 +398,17 @@ public class LeveledCompactionStrategyTest
DecoratedKey key1 = Util.dk(String.valueOf(1)); DecoratedKey key1 = Util.dk(String.valueOf(1));
DecoratedKey key2 = Util.dk(String.valueOf(2)); DecoratedKey key2 = Util.dk(String.valueOf(2));
List<DecoratedKey> keys = new ArrayList<>(Arrays.asList(key1, key2)); List<DecoratedKey> keys = Arrays.asList(key1, key2);
int numIterations = 10; int numIterations = 10;
int columns = 2; int columns = 2;
// Add enough data to trigger multiple sstables. // Add enough data to trigger multiple sstables.
// create 10 sstables that contain data for both key1 and key2 // create 10 sstables that contain data for both key1 and key2
for (int i = 0; i < numIterations; i++) { for (int i = 0; i < numIterations; i++)
for (DecoratedKey key : keys) { {
for (DecoratedKey key : keys)
{
UpdateBuilder update = UpdateBuilder.create(cfs.metadata, key); UpdateBuilder update = UpdateBuilder.create(cfs.metadata, key);
for (int c = 0; c < columns; c++) for (int c = 0; c < columns; c++)
update.newRow("column" + c).add("val", value); update.newRow("column" + c).add("val", value);
@ -418,8 +418,10 @@ public class LeveledCompactionStrategyTest
} }
// create 20 more sstables with 10 containing data for key1 and other 10 containing data for key2 // create 20 more sstables with 10 containing data for key1 and other 10 containing data for key2
for (int i = 0; i < numIterations; i++) { for (int i = 0; i < numIterations; i++)
for (DecoratedKey key : keys) { {
for (DecoratedKey key : keys)
{
UpdateBuilder update = UpdateBuilder.create(cfs.metadata, key); UpdateBuilder update = UpdateBuilder.create(cfs.metadata, key);
for (int c = 0; c < columns; c++) for (int c = 0; c < columns; c++)
update.newRow("column" + c).add("val", value); update.newRow("column" + c).add("val", value);
@ -431,13 +433,14 @@ public class LeveledCompactionStrategyTest
// We should have a total of 30 sstables by now // We should have a total of 30 sstables by now
assertEquals(30, cfs.getLiveSSTables().size()); assertEquals(30, cfs.getLiveSSTables().size());
// Compact just the tables with key2 // Compact just the tables with key2. The token ranges for compaction are interpreted as closed intervals,
// Bit hackish to use the key1.token as the prior key but works in BytesToken // so we can use [token, token] to select a single token.
Range<Token> tokenRange = new Range<>(key2.getToken(), key2.getToken()); Range<Token> tokenRange = new Range<>(key2.getToken(), key2.getToken());
Collection<Range<Token>> tokenRanges = new ArrayList<>(Arrays.asList(tokenRange)); Collection<Range<Token>> tokenRanges = singleton(tokenRange);
cfs.forceCompactionForTokenRange(tokenRanges); cfs.forceCompactionForTokenRange(tokenRanges);
while(CompactionManager.instance.isCompacting(Arrays.asList(cfs))) { while (CompactionManager.instance.isCompacting(singleton(cfs)))
{
Thread.sleep(100); Thread.sleep(100);
} }
@ -446,11 +449,11 @@ public class LeveledCompactionStrategyTest
// Compact just the tables with key1. At this point all 11 tables should have key1 // Compact just the tables with key1. At this point all 11 tables should have key1
Range<Token> tokenRange2 = new Range<>(key1.getToken(), key1.getToken()); Range<Token> tokenRange2 = new Range<>(key1.getToken(), key1.getToken());
Collection<Range<Token>> tokenRanges2 = new ArrayList<>(Arrays.asList(tokenRange2)); Collection<Range<Token>> tokenRanges2 = new ArrayList<>(singleton(tokenRange2));
cfs.forceCompactionForTokenRange(tokenRanges2); cfs.forceCompactionForTokenRange(tokenRanges2);
while (CompactionManager.instance.isCompacting(singleton(cfs)))
while(CompactionManager.instance.isCompacting(Arrays.asList(cfs))) { {
Thread.sleep(100); Thread.sleep(100);
} }