[ILM] make alias swapping atomic (#35972)
In the current implementation, there is a time between the ShrinkStep and the ShrinkSetAliasStep that both the source and target indices will be present with the same aliases. This means that queries to during this time will query both and return duplicates. This fixes that scenario by moving the alias inheritance to the same aliases update request as is done in ShrinkSetAliasStep
This commit is contained in:
parent
ba3ee98943
commit
fa5f551b80
|
@ -9,6 +9,7 @@ import org.elasticsearch.action.ActionListener;
|
|||
import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest;
|
||||
import org.elasticsearch.client.Client;
|
||||
import org.elasticsearch.cluster.ClusterState;
|
||||
import org.elasticsearch.cluster.metadata.AliasMetaData;
|
||||
import org.elasticsearch.cluster.metadata.IndexMetaData;
|
||||
|
||||
import java.util.Objects;
|
||||
|
@ -36,11 +37,20 @@ public class ShrinkSetAliasStep extends AsyncActionStep {
|
|||
String index = indexMetaData.getIndex().getName();
|
||||
// get target shrink index
|
||||
String targetIndexName = shrunkIndexPrefix + index;
|
||||
|
||||
IndicesAliasesRequest aliasesRequest = new IndicesAliasesRequest()
|
||||
.addAliasAction(IndicesAliasesRequest.AliasActions.removeIndex().index(index))
|
||||
.addAliasAction(IndicesAliasesRequest.AliasActions.add().index(targetIndexName).alias(index));
|
||||
|
||||
// copy over other aliases from original index
|
||||
indexMetaData.getAliases().values().spliterator().forEachRemaining(aliasMetaDataObjectCursor -> {
|
||||
AliasMetaData aliasMetaDataToAdd = aliasMetaDataObjectCursor.value;
|
||||
// inherit all alias properties except `is_write_index`
|
||||
aliasesRequest.addAliasAction(IndicesAliasesRequest.AliasActions.add()
|
||||
.index(targetIndexName).alias(aliasMetaDataToAdd.alias())
|
||||
.indexRouting(aliasMetaDataToAdd.indexRouting())
|
||||
.searchRouting(aliasMetaDataToAdd.searchRouting())
|
||||
.filter(aliasMetaDataToAdd.filter() == null ? null : aliasMetaDataToAdd.filter().string())
|
||||
.writeIndex(null));
|
||||
});
|
||||
getClient().admin().indices().aliases(aliasesRequest, ActionListener.wrap(response ->
|
||||
listener.onResponse(true), listener::onFailure));
|
||||
}
|
||||
|
@ -54,7 +64,7 @@ public class ShrinkSetAliasStep extends AsyncActionStep {
|
|||
public int hashCode() {
|
||||
return Objects.hash(super.hashCode(), shrunkIndexPrefix);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == null) {
|
||||
|
@ -64,7 +74,7 @@ public class ShrinkSetAliasStep extends AsyncActionStep {
|
|||
return false;
|
||||
}
|
||||
ShrinkSetAliasStep other = (ShrinkSetAliasStep) obj;
|
||||
return super.equals(obj) &&
|
||||
return super.equals(obj) &&
|
||||
Objects.equals(shrunkIndexPrefix, other.shrunkIndexPrefix);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
package org.elasticsearch.xpack.core.indexlifecycle;
|
||||
|
||||
import org.elasticsearch.action.ActionListener;
|
||||
import org.elasticsearch.action.admin.indices.alias.Alias;
|
||||
import org.elasticsearch.action.admin.indices.shrink.ResizeRequest;
|
||||
import org.elasticsearch.client.Client;
|
||||
import org.elasticsearch.cluster.ClusterState;
|
||||
|
@ -58,13 +57,9 @@ public class ShrinkStep extends AsyncActionStep {
|
|||
|
||||
String shrunkenIndexName = shrunkIndexPrefix + indexMetaData.getIndex().getName();
|
||||
ResizeRequest resizeRequest = new ResizeRequest(shrunkenIndexName, indexMetaData.getIndex().getName());
|
||||
indexMetaData.getAliases().values().spliterator().forEachRemaining(aliasMetaDataObjectCursor -> {
|
||||
resizeRequest.getTargetIndexRequest().alias(new Alias(aliasMetaDataObjectCursor.value.alias()));
|
||||
});
|
||||
resizeRequest.getTargetIndexRequest().settings(relevantTargetSettings);
|
||||
|
||||
getClient().admin().indices().resizeIndex(resizeRequest, ActionListener.wrap(response -> {
|
||||
// TODO(talevy): when is this not acknowledged?
|
||||
listener.onResponse(response.isAcknowledged());
|
||||
}, listener::onFailure));
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ import org.elasticsearch.action.support.master.AcknowledgedResponse;
|
|||
import org.elasticsearch.client.AdminClient;
|
||||
import org.elasticsearch.client.Client;
|
||||
import org.elasticsearch.client.IndicesAdminClient;
|
||||
import org.elasticsearch.cluster.metadata.AliasMetaData;
|
||||
import org.elasticsearch.cluster.metadata.IndexMetaData;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.AsyncActionStep.Listener;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.Step.StepKey;
|
||||
|
@ -71,15 +72,33 @@ public class ShrinkSetAliasStepTests extends AbstractStepTestCase<ShrinkSetAlias
|
|||
}
|
||||
|
||||
public void testPerformAction() {
|
||||
IndexMetaData indexMetaData = IndexMetaData.builder(randomAlphaOfLength(10)).settings(settings(Version.CURRENT))
|
||||
.numberOfShards(randomIntBetween(1, 5)).numberOfReplicas(randomIntBetween(0, 5)).build();
|
||||
IndexMetaData.Builder indexMetaDataBuilder = IndexMetaData.builder(randomAlphaOfLength(10)).settings(settings(Version.CURRENT))
|
||||
.numberOfShards(randomIntBetween(1, 5)).numberOfReplicas(randomIntBetween(0, 5));
|
||||
AliasMetaData.Builder aliasBuilder = AliasMetaData.builder(randomAlphaOfLengthBetween(3, 10));
|
||||
if (randomBoolean()) {
|
||||
aliasBuilder.routing(randomAlphaOfLengthBetween(3, 10));
|
||||
}
|
||||
if (randomBoolean()) {
|
||||
aliasBuilder.searchRouting(randomAlphaOfLengthBetween(3, 10));
|
||||
}
|
||||
if (randomBoolean()) {
|
||||
aliasBuilder.indexRouting(randomAlphaOfLengthBetween(3, 10));
|
||||
}
|
||||
String aliasMetaDataFilter = randomBoolean() ? null : "{\"term\":{\"year\":2016}}";
|
||||
aliasBuilder.filter(aliasMetaDataFilter);
|
||||
aliasBuilder.writeIndex(randomBoolean());
|
||||
AliasMetaData aliasMetaData = aliasBuilder.build();
|
||||
IndexMetaData indexMetaData = indexMetaDataBuilder.putAlias(aliasMetaData).build();
|
||||
ShrinkSetAliasStep step = createRandomInstance();
|
||||
|
||||
String sourceIndex = indexMetaData.getIndex().getName();
|
||||
String shrunkenIndex = step.getShrunkIndexPrefix() + sourceIndex;
|
||||
List<AliasActions> expectedAliasActions = Arrays.asList(
|
||||
IndicesAliasesRequest.AliasActions.removeIndex().index(sourceIndex),
|
||||
IndicesAliasesRequest.AliasActions.add().index(shrunkenIndex).alias(sourceIndex));
|
||||
IndicesAliasesRequest.AliasActions.add().index(shrunkenIndex).alias(sourceIndex),
|
||||
IndicesAliasesRequest.AliasActions.add().index(shrunkenIndex).alias(aliasMetaData.alias())
|
||||
.searchRouting(aliasMetaData.searchRouting()).indexRouting(aliasMetaData.indexRouting())
|
||||
.filter(aliasMetaDataFilter).writeIndex(null));
|
||||
AdminClient adminClient = Mockito.mock(AdminClient.class);
|
||||
IndicesAdminClient indicesClient = Mockito.mock(IndicesAdminClient.class);
|
||||
|
||||
|
|
|
@ -8,7 +8,6 @@ package org.elasticsearch.xpack.core.indexlifecycle;
|
|||
import org.apache.lucene.util.SetOnce;
|
||||
import org.elasticsearch.Version;
|
||||
import org.elasticsearch.action.ActionListener;
|
||||
import org.elasticsearch.action.admin.indices.alias.Alias;
|
||||
import org.elasticsearch.action.admin.indices.rollover.RolloverResponse;
|
||||
import org.elasticsearch.action.admin.indices.shrink.ResizeRequest;
|
||||
import org.elasticsearch.action.admin.indices.shrink.ResizeResponse;
|
||||
|
@ -112,7 +111,7 @@ public class ShrinkStepTests extends AbstractStepTestCase<ShrinkStep> {
|
|||
@SuppressWarnings("unchecked")
|
||||
ActionListener<ResizeResponse> listener = (ActionListener<ResizeResponse>) invocation.getArguments()[1];
|
||||
assertThat(request.getSourceIndex(), equalTo(sourceIndexMetaData.getIndex().getName()));
|
||||
assertThat(request.getTargetIndexRequest().aliases(), equalTo(Collections.singleton(new Alias("my_alias"))));
|
||||
assertThat(request.getTargetIndexRequest().aliases(), equalTo(Collections.emptySet()));
|
||||
assertThat(request.getTargetIndexRequest().settings(), equalTo(Settings.builder()
|
||||
.put(IndexMetaData.SETTING_NUMBER_OF_SHARDS, step.getNumberOfShards())
|
||||
.put(IndexMetaData.SETTING_NUMBER_OF_REPLICAS, sourceIndexMetaData.getNumberOfReplicas())
|
||||
|
|
Loading…
Reference in New Issue