Skip to content

Commit

Permalink
Default to zero replicas for searchable snapshots (#57802)
Browse files Browse the repository at this point in the history
Today a mounted searchable snapshot defaults to having the same replica
configuration as the index that was snapshotted. This commit changes this
behaviour so that we default to zero replicas on these indices, but allow the
user to override this in the mount request.

Relates #50999
  • Loading branch information
DaveCTurner authored Jun 16, 2020
1 parent b87132c commit 57dea5e
Show file tree
Hide file tree
Showing 2 changed files with 159 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,8 @@ protected void masterOperation(
// Pass through index settings, adding the index-level settings required to use searchable snapshots
.indexSettings(
Settings.builder()
.put(IndexMetadata.SETTING_NUMBER_OF_REPLICAS, 0) // can be overridden
.put(IndexMetadata.SETTING_AUTO_EXPAND_REPLICAS, false) // can be overridden
.put(request.indexSettings())
.put(buildIndexSettings(request.repositoryName(), snapshotId, indexId))
.build()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import org.elasticsearch.action.admin.indices.recovery.RecoveryResponse;
import org.elasticsearch.action.admin.indices.shrink.ResizeType;
import org.elasticsearch.action.index.IndexRequestBuilder;
import org.elasticsearch.cluster.ClusterState;
import org.elasticsearch.cluster.metadata.IndexMetadata;
import org.elasticsearch.cluster.node.DiscoveryNode;
import org.elasticsearch.cluster.routing.ShardRouting;
Expand Down Expand Up @@ -153,6 +154,13 @@ public void testCreateAndRestoreSearchableSnapshot() throws Exception {
new ByteSizeValue(randomLongBetween(10, 100_000))
);
}
final int expectedReplicas;
if (randomBoolean()) {
expectedReplicas = numberOfReplicas();
indexSettingsBuilder.put(IndexMetadata.SETTING_NUMBER_OF_REPLICAS, expectedReplicas);
} else {
expectedReplicas = 0;
}
final MountSearchableSnapshotRequest req = new MountSearchableSnapshotRequest(
restoredIndexName,
fsRepoName,
Expand All @@ -178,6 +186,8 @@ public void testCreateAndRestoreSearchableSnapshot() throws Exception {
assertTrue(IndexMetadata.INDEX_BLOCKS_WRITE_SETTING.get(settings));
assertTrue(SearchableSnapshots.SNAPSHOT_SNAPSHOT_ID_SETTING.exists(settings));
assertTrue(SearchableSnapshots.SNAPSHOT_INDEX_ID_SETTING.exists(settings));
assertThat(IndexMetadata.INDEX_AUTO_EXPAND_REPLICAS_SETTING.get(settings).toString(), equalTo("false"));
assertThat(IndexMetadata.INDEX_NUMBER_OF_REPLICAS_SETTING.get(settings), equalTo(expectedReplicas));

assertRecovered(restoredIndexName, originalAllHits, originalBarHits);
assertSearchableSnapshotStats(restoredIndexName, cacheEnabled, nonCachedExtensions);
Expand Down Expand Up @@ -425,6 +435,152 @@ public void testMaxRestoreBytesPerSecIsUsed() throws Exception {
}
}

public void testMountedSnapshotHasNoReplicasByDefault() throws Exception {
final String fsRepoName = randomAlphaOfLength(10);
final String indexName = randomAlphaOfLength(10).toLowerCase(Locale.ROOT);
final String restoredIndexName = randomBoolean() ? indexName : randomAlphaOfLength(10).toLowerCase(Locale.ROOT);
final String snapshotName = randomAlphaOfLength(10).toLowerCase(Locale.ROOT);

final Path repo = randomRepoPath();
assertAcked(
client().admin().cluster().preparePutRepository(fsRepoName).setType("fs").setSettings(Settings.builder().put("location", repo))
);

final int dataNodesCount = internalCluster().numDataNodes();
final Settings.Builder originalIndexSettings = Settings.builder();
originalIndexSettings.put(INDEX_SOFT_DELETES_SETTING.getKey(), true);
if (randomBoolean()) {
originalIndexSettings.put(IndexMetadata.SETTING_NUMBER_OF_REPLICAS, numberOfReplicas());
}
if (randomBoolean()) {
final int replicaLimit = between(0, dataNodesCount);
originalIndexSettings.put(
IndexMetadata.SETTING_AUTO_EXPAND_REPLICAS,
replicaLimit == dataNodesCount ? "0-all" : "0-" + replicaLimit
);
}
assertAcked(prepareCreate(indexName, originalIndexSettings));
ensureGreen(indexName);

final List<IndexRequestBuilder> indexRequestBuilders = new ArrayList<>();
for (int i = between(10, 100); i >= 0; i--) {
indexRequestBuilders.add(client().prepareIndex(indexName).setSource("foo", randomBoolean() ? "bar" : "baz"));
}
indexRandom(true, true, indexRequestBuilders);
refresh(indexName);
assertThat(
client().admin().indices().prepareForceMerge(indexName).setOnlyExpungeDeletes(true).setFlush(true).get().getFailedShards(),
equalTo(0)
);

CreateSnapshotResponse createSnapshotResponse = client().admin()
.cluster()
.prepareCreateSnapshot(fsRepoName, snapshotName)
.setWaitForCompletion(true)
.get();
final SnapshotInfo snapshotInfo = createSnapshotResponse.getSnapshotInfo();
assertThat(snapshotInfo.successfulShards(), greaterThan(0));
assertThat(snapshotInfo.successfulShards(), equalTo(snapshotInfo.totalShards()));

assertAcked(client().admin().indices().prepareDelete(indexName));

{
logger.info("--> restoring index [{}] with default replica counts", restoredIndexName);
Settings.Builder indexSettingsBuilder = Settings.builder()
.put(SearchableSnapshots.SNAPSHOT_CACHE_ENABLED_SETTING.getKey(), true)
.put(IndexSettings.INDEX_CHECK_ON_STARTUP.getKey(), Boolean.FALSE.toString());
final MountSearchableSnapshotRequest req = new MountSearchableSnapshotRequest(
restoredIndexName,
fsRepoName,
snapshotName,
indexName,
indexSettingsBuilder.build(),
Strings.EMPTY_ARRAY,
true
);

final RestoreSnapshotResponse restoreSnapshotResponse = client().execute(MountSearchableSnapshotAction.INSTANCE, req).get();
assertThat(restoreSnapshotResponse.getRestoreInfo().failedShards(), equalTo(0));
ensureGreen(restoredIndexName);

final Settings settings = client().admin()
.indices()
.prepareGetSettings(restoredIndexName)
.get()
.getIndexToSettings()
.get(restoredIndexName);
assertThat(IndexMetadata.INDEX_NUMBER_OF_REPLICAS_SETTING.get(settings), equalTo(0));
assertThat(IndexMetadata.INDEX_AUTO_EXPAND_REPLICAS_SETTING.get(settings).toString(), equalTo("false"));

assertAcked(client().admin().indices().prepareDelete(restoredIndexName));
}

{
final int replicaCount = numberOfReplicas();

logger.info("--> restoring index [{}] with specific replica count", restoredIndexName);
Settings.Builder indexSettingsBuilder = Settings.builder()
.put(SearchableSnapshots.SNAPSHOT_CACHE_ENABLED_SETTING.getKey(), true)
.put(IndexSettings.INDEX_CHECK_ON_STARTUP.getKey(), Boolean.FALSE.toString())
.put(IndexMetadata.SETTING_NUMBER_OF_REPLICAS, replicaCount);
final MountSearchableSnapshotRequest req = new MountSearchableSnapshotRequest(
restoredIndexName,
fsRepoName,
snapshotName,
indexName,
indexSettingsBuilder.build(),
Strings.EMPTY_ARRAY,
true
);

final RestoreSnapshotResponse restoreSnapshotResponse = client().execute(MountSearchableSnapshotAction.INSTANCE, req).get();
assertThat(restoreSnapshotResponse.getRestoreInfo().failedShards(), equalTo(0));
ensureGreen(restoredIndexName);

final Settings settings = client().admin()
.indices()
.prepareGetSettings(restoredIndexName)
.get()
.getIndexToSettings()
.get(restoredIndexName);
assertThat(IndexMetadata.INDEX_NUMBER_OF_REPLICAS_SETTING.get(settings), equalTo(replicaCount));
assertThat(IndexMetadata.INDEX_AUTO_EXPAND_REPLICAS_SETTING.get(settings).toString(), equalTo("false"));

assertAcked(client().admin().indices().prepareDelete(restoredIndexName));
}

{
final int replicaLimit = between(0, dataNodesCount);
logger.info("--> restoring index [{}] with auto-expand replicas configured", restoredIndexName);
Settings.Builder indexSettingsBuilder = Settings.builder()
.put(SearchableSnapshots.SNAPSHOT_CACHE_ENABLED_SETTING.getKey(), true)
.put(IndexSettings.INDEX_CHECK_ON_STARTUP.getKey(), Boolean.FALSE.toString())
.put(IndexMetadata.SETTING_AUTO_EXPAND_REPLICAS, replicaLimit == dataNodesCount ? "0-all" : "0-" + replicaLimit);
final MountSearchableSnapshotRequest req = new MountSearchableSnapshotRequest(
restoredIndexName,
fsRepoName,
snapshotName,
indexName,
indexSettingsBuilder.build(),
Strings.EMPTY_ARRAY,
true
);

final RestoreSnapshotResponse restoreSnapshotResponse = client().execute(MountSearchableSnapshotAction.INSTANCE, req).get();
assertThat(restoreSnapshotResponse.getRestoreInfo().failedShards(), equalTo(0));
ensureGreen(restoredIndexName);

final ClusterState state = client().admin().cluster().prepareState().clear().setRoutingTable(true).get().getState();
assertThat(
state.toString(),
state.routingTable().index(restoredIndexName).shard(0).size(),
equalTo(Math.min(replicaLimit + 1, dataNodesCount))
);

assertAcked(client().admin().indices().prepareDelete(restoredIndexName));
}
}

private void assertRecovered(String indexName, TotalHits originalAllHits, TotalHits originalBarHits) throws Exception {
assertRecovered(indexName, originalAllHits, originalBarHits, true);
}
Expand Down Expand Up @@ -588,4 +744,5 @@ private void assertSearchableSnapshotStats(String indexName, boolean cacheEnable
}
}
}

}

0 comments on commit 57dea5e

Please sign in to comment.