-
Notifications
You must be signed in to change notification settings - Fork 24.9k
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
Noop peer recoveries on closed index #41400
Merged
Merged
Changes from all commits
Commits
Show all changes
20 commits
Select commit
Hold shift + click to select a range
783cd1e
Synced flush indices before closing
dnhatn 1c485e0
move prepare action to internal engine
dnhatn da0f7fe
synced-flush post_recovery state
dnhatn e2bdbb8
Merge branch 'master' into synced-flush-closed-index
dnhatn 9ed30cd
reuse syncId
dnhatn 68c7d0c
wording
dnhatn fe9a294
wording
dnhatn 1946d92
fix tests
dnhatn 95d3536
Merge branch 'master' into synced-flush-closed-index
dnhatn a0f8d03
simplify syncId logic
dnhatn 732049e
fix comment
dnhatn f3228d3
Merge branch 'master' into synced-flush-closed-index
dnhatn 7bdece5
Merge branch 'master' into synced-flush-closed-index
dnhatn 38bd362
backout sync id
dnhatn 042ceb4
Noop peer recoveries on closed index
ywelsch 35c527b
strengthen operation-based condition
dnhatn 685c5cd
Merge branch 'master' into synced-flush-closed-index
dnhatn b50d3f2
add recover existing replica test
dnhatn c1d3324
add test comment
dnhatn aa2d525
Merge branch 'master' into synced-flush-closed-index
dnhatn File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,25 +22,31 @@ | |
import org.elasticsearch.action.ActionRequestValidationException; | ||
import org.elasticsearch.action.admin.indices.close.CloseIndexResponse; | ||
import org.elasticsearch.action.support.ActiveShardCount; | ||
import org.elasticsearch.client.Client; | ||
import org.elasticsearch.cluster.ClusterState; | ||
import org.elasticsearch.cluster.block.ClusterBlockException; | ||
import org.elasticsearch.cluster.health.ClusterHealthStatus; | ||
import org.elasticsearch.cluster.metadata.IndexMetaData; | ||
import org.elasticsearch.cluster.metadata.MetaDataIndexStateService; | ||
import org.elasticsearch.cluster.node.DiscoveryNode; | ||
import org.elasticsearch.cluster.routing.ShardRouting; | ||
import org.elasticsearch.common.settings.Settings; | ||
import org.elasticsearch.common.unit.ByteSizeUnit; | ||
import org.elasticsearch.common.unit.ByteSizeValue; | ||
import org.elasticsearch.common.util.set.Sets; | ||
import org.elasticsearch.index.IndexNotFoundException; | ||
import org.elasticsearch.index.IndexSettings; | ||
import org.elasticsearch.indices.IndexClosedException; | ||
import org.elasticsearch.indices.recovery.RecoveryState; | ||
import org.elasticsearch.test.BackgroundIndexer; | ||
import org.elasticsearch.test.ESIntegTestCase; | ||
import org.elasticsearch.test.InternalTestCluster; | ||
|
||
import java.util.ArrayList; | ||
import java.util.List; | ||
import java.util.Locale; | ||
import java.util.concurrent.CountDownLatch; | ||
import java.util.stream.Collectors; | ||
import java.util.stream.IntStream; | ||
|
||
import static java.util.Collections.emptySet; | ||
|
@@ -50,9 +56,11 @@ | |
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked; | ||
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertHitCount; | ||
import static org.hamcrest.Matchers.containsString; | ||
import static org.hamcrest.Matchers.empty; | ||
import static org.hamcrest.Matchers.equalTo; | ||
import static org.hamcrest.Matchers.hasSize; | ||
import static org.hamcrest.Matchers.is; | ||
import static org.hamcrest.Matchers.not; | ||
import static org.hamcrest.Matchers.notNullValue; | ||
|
||
public class CloseIndexIT extends ESIntegTestCase { | ||
|
@@ -338,6 +346,81 @@ public void testCloseIndexWaitForActiveShards() throws Exception { | |
assertIndexIsClosed(indexName); | ||
} | ||
|
||
public void testNoopPeerRecoveriesWhenIndexClosed() throws Exception { | ||
final String indexName = "noop-peer-recovery-test"; | ||
int numberOfReplicas = between(1, 2); | ||
internalCluster().ensureAtLeastNumDataNodes(numberOfReplicas + between(1, 2)); | ||
createIndex(indexName, Settings.builder() | ||
.put(IndexMetaData.SETTING_NUMBER_OF_SHARDS, 1) | ||
.put(IndexMetaData.SETTING_NUMBER_OF_REPLICAS, numberOfReplicas) | ||
.put("index.routing.rebalance.enable", "none") | ||
.build()); | ||
int iterations = between(1, 3); | ||
for (int iter = 0; iter < iterations; iter++) { | ||
indexRandom(randomBoolean(), randomBoolean(), randomBoolean(), IntStream.range(0, randomIntBetween(0, 50)) | ||
.mapToObj(n -> client().prepareIndex(indexName, "_doc").setSource("num", n)).collect(toList())); | ||
ensureGreen(indexName); | ||
|
||
// Closing an index should execute noop peer recovery | ||
assertAcked(client().admin().indices().prepareClose(indexName).get()); | ||
assertIndexIsClosed(indexName); | ||
ensureGreen(indexName); | ||
assertNoFileBasedRecovery(indexName); | ||
internalCluster().assertSameDocIdsOnShards(); | ||
|
||
// Open a closed index should execute noop recovery | ||
assertAcked(client().admin().indices().prepareOpen(indexName).get()); | ||
assertIndexIsOpened(indexName); | ||
ensureGreen(indexName); | ||
assertNoFileBasedRecovery(indexName); | ||
internalCluster().assertSameDocIdsOnShards(); | ||
} | ||
} | ||
|
||
/** | ||
* Ensures that if a replica of a closed index does not have the same content as the primary, then a file-based recovery will occur. | ||
*/ | ||
public void testRecoverExistingReplica() throws Exception { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. perhaps add a comment that says that this tests recovery of a replica of a closed index that has some docs missing that were on the primary, leading to a file-based recovery |
||
final String indexName = "test-recover-existing-replica"; | ||
internalCluster().ensureAtLeastNumDataNodes(2); | ||
List<String> dataNodes = randomSubsetOf(2, Sets.newHashSet( | ||
clusterService().state().nodes().getDataNodes().valuesIt()).stream().map(DiscoveryNode::getName).collect(Collectors.toSet())); | ||
createIndex(indexName, Settings.builder() | ||
.put(IndexMetaData.SETTING_NUMBER_OF_SHARDS, 1) | ||
.put(IndexMetaData.SETTING_NUMBER_OF_REPLICAS, 1) | ||
.put("index.routing.allocation.include._name", String.join(",", dataNodes)) | ||
.build()); | ||
indexRandom(randomBoolean(), randomBoolean(), randomBoolean(), IntStream.range(0, randomIntBetween(0, 50)) | ||
.mapToObj(n -> client().prepareIndex(indexName, "_doc").setSource("num", n)).collect(toList())); | ||
ensureGreen(indexName); | ||
if (randomBoolean()) { | ||
client().admin().indices().prepareFlush(indexName).get(); | ||
} else { | ||
client().admin().indices().prepareSyncedFlush(indexName).get(); | ||
} | ||
// index more documents while one shard copy is offline | ||
internalCluster().restartNode(dataNodes.get(1), new InternalTestCluster.RestartCallback() { | ||
@Override | ||
public Settings onNodeStopped(String nodeName) throws Exception { | ||
Client client = client(dataNodes.get(0)); | ||
int moreDocs = randomIntBetween(1, 50); | ||
for (int i = 0; i < moreDocs; i++) { | ||
client.prepareIndex(indexName, "_doc").setSource("num", i).get(); | ||
} | ||
assertAcked(client.admin().indices().prepareClose(indexName)); | ||
return super.onNodeStopped(nodeName); | ||
} | ||
}); | ||
assertIndexIsClosed(indexName); | ||
ensureGreen(indexName); | ||
internalCluster().assertSameDocIdsOnShards(); | ||
for (RecoveryState recovery : client().admin().indices().prepareRecoveries(indexName).get().shardRecoveryStates().get(indexName)) { | ||
if (recovery.getPrimary() == false) { | ||
assertThat(recovery.getIndex().fileDetails(), not(empty())); | ||
} | ||
} | ||
} | ||
|
||
static void assertIndexIsClosed(final String... indices) { | ||
final ClusterState clusterState = client().admin().cluster().prepareState().get().getState(); | ||
for (String index : indices) { | ||
|
@@ -383,4 +466,12 @@ static void assertException(final Throwable throwable, final String indexName) { | |
fail("Unexpected exception: " + t); | ||
} | ||
} | ||
|
||
void assertNoFileBasedRecovery(String indexName) { | ||
for (RecoveryState recovery : client().admin().indices().prepareRecoveries(indexName).get().shardRecoveryStates().get(indexName)) { | ||
if (recovery.getPrimary() == false) { | ||
assertThat(recovery.getIndex().fileDetails(), empty()); | ||
} | ||
} | ||
} | ||
} |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would be nice to also test the scenario you described here:
#41400 (comment)
where we expect file based recovery and verify same docs on all shards.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@henningandersen Good suggestion. However we can't test that scenario for now since closing a follower index with gaps in sequence number will make all its shard unassigned; hence no peer recovery will be performed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@dnhatn Can you implement the test scenario that you've described for regular indices (instead of follower index)? It will then show that a closed replica index that is missing some docs IS doing a file-based recovery.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added a test in b50d3f2.