Skip to content
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

Verify AllocationIDs in replication actions #20320

Merged
merged 18 commits into from
Sep 6, 2016

Conversation

bleskes
Copy link
Contributor

@bleskes bleskes commented Sep 4, 2016

Replicated operation consist of a routing action (the original), which is in charge of sending the operation to the primary shard, a primary action which executes the operation on the resolved primary and replica actions which performs the operation on a specific replica. This commit adds the targeted shard's allocation id to the primary and replica actions and makes sure that those match the shard the actions end up executing on.

This helps preventing extremely rare failure mode where a shard moves off a node and back to it, all between an action is sent and the time it's processed.

For example:

  1. Primary action is sent to a relocating primary on node A.
  2. The primary finishes relocation to node B and start relocating back.
  3. The relocation back gets to the phase and opens up the target engine, on the original node, node A.
  4. The primary action is executed on the target engine before the relocation finishes, at which the shard copy on node B is still the official primary - i.e., it is executed on the wrong primary.


RequestWithAllocationID(Supplier<R> requestSupplier) {
request = requestSupplier.get();
allocationId = null;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what is the invariant that this can be null?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh that is for deserialization :( bummer can you document it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah :(. maybe we should add a variant of registerRequestHandler which takes a function of a stream and returns a request.

@s1monw
Copy link
Contributor

s1monw commented Sep 5, 2016

left some suggestions LGTM in general

ActionListener<Releasable> callback = (ActionListener<Releasable>) invocation.getArguments()[1];
final long primaryTerm = indexShard.getPrimaryTerm();
if (term < primaryTerm) {
throw new IllegalArgumentException(LoggerMessageFormat.format("{} operation term [{}] is too old (current [{}])",
Copy link
Member

@jasontedor jasontedor Sep 5, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we not add another use of LoggerMessageFormat; I'd like to remove it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I copied from another place - do you have a decent suggestion for an alternative (the obvious one is chaining strings)

Copy link
Member

@jasontedor jasontedor Sep 5, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

String.format(Locale.ROOT, "%s operation term [%d] is too old (current [%d])", shardId, term, primaryTerm)

}
}

/** test that a replica request is reject if it arrives at a shard with a wrong allocation id */
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: reject -> rejected

@jasontedor
Copy link
Member

I left a few comments, but it looks good.

allocationId = null;
}

RequestWithAllocationID(R request, String allocationId) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess this constructor parameter should be targetAllocationID too to be consistent with my other suggestions.

@bleskes
Copy link
Contributor Author

bleskes commented Sep 5, 2016

thx @s1monw , @jasontedor . I pushed a commit addressing all comments

@s1monw
Copy link
Contributor

s1monw commented Sep 5, 2016

I don't get why we call these properties targetAllocationID? what's wrong with allocationId?

@bleskes
Copy link
Contributor Author

bleskes commented Sep 5, 2016

I don't get why we call these properties targetAllocationID? what's wrong with allocationId?

Because @jasontedor asked.

@s1monw
Copy link
Contributor

s1monw commented Sep 5, 2016

Because @jasontedor asked.

can we keep it simple?

@s1monw
Copy link
Contributor

s1monw commented Sep 6, 2016

@bleskes I don't wanna be in the way for such an improvement just because of some internal debatable naming. lets get it in!

@bleskes bleskes merged commit c56cd46 into elastic:master Sep 6, 2016
@bleskes bleskes deleted the replication_with_aid branch September 6, 2016 12:32
@bleskes
Copy link
Contributor Author

bleskes commented Sep 6, 2016

Thx @s1monw and @jasontedor for the review.

MaineC pushed a commit to MaineC/elasticsearch that referenced this pull request Sep 7, 2016
Replicated operation consist of a routing action (the original), which is in charge of sending the operation to the primary shard, a primary action which executes the operation on the resolved primary and replica actions which performs the operation on a specific replica. This commit adds the targeted shard's allocation id to the primary and replica actions and makes sure that those match the shard the actions end up executing on.

This helps preventing extremely rare failure mode where a shard moves off a node and back to it, all between an action is sent and the time it's processed. 

For example:
1) Primary action is sent to a relocating primary on node A.
2) The primary finishes relocation to node B and start relocating back.
3) The relocation back gets to the phase and opens up the target engine, on the original node, node A.
4) The primary action is executed on the target engine before the relocation finishes, at which the shard copy on node B is still the official primary - i.e., it is executed on the wrong primary.
@clintongormley clintongormley added :Allocation and removed :Core/Infra/Core Core issues without another label labels Sep 7, 2016
@lcawl lcawl added :Distributed Indexing/Distributed A catch all label for anything in the Distributed Area. Please avoid if you can. and removed :Allocation labels Feb 13, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
:Distributed Indexing/Distributed A catch all label for anything in the Distributed Area. Please avoid if you can. >enhancement resiliency v5.0.0-beta1
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants