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

Port Primary Terms to master #17044

Merged
merged 1 commit into from
Mar 25, 2016
Merged

Port Primary Terms to master #17044

merged 1 commit into from
Mar 25, 2016

Conversation

bleskes
Copy link
Contributor

@bleskes bleskes commented Mar 10, 2016

Primary terms is a way to make sure that operations replicated from stale primary are rejected by shards following a newly elected primary.

Original PRs adding this to the seq# feature branch #14062 , #14651

Relates to #17038

@@ -447,6 +446,9 @@ private IndexShardState changeState(IndexShardState newState, String reason) {

public Engine.Index prepareIndexOnReplica(SourceToParse source, long version, VersionType versionType) {
try {
if (shardRouting.primary() && shardRouting.isRelocationTarget() == false) {
throw new IllegalIndexShardStateException(shardId, state, "shard is not a replica");
Copy link
Member

Choose a reason for hiding this comment

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

This exception will be treated as ignore replica exception. 😉

Copy link
Contributor

Choose a reason for hiding this comment

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

I think this check is wrong. When we have relocation going on and relocation source is marked as relocated (i.e. we call executeRemotely in TransportReplicationAction), then we have primary relocation target replicating back to primary relocation source (see also ReplicationPhase).

@bleskes
Copy link
Contributor Author

bleskes commented Mar 11, 2016

@jasontedor pushed an update to those exceptions... sadly testing is harder (but will be possible with new testing infra I'm working on...)

/** marks the primary term in which the operation was performed */
public void primaryTerm(long term) {
primaryTerm = term;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

I guess this can be reused to replace routedBasedOnClusterVersion (#16274). Yay 👍

Copy link
Contributor Author

Choose a reason for hiding this comment

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

interesting idea - it's currently not incremented when relocating a primary though... requires more thought.

@ywelsch
Copy link
Contributor

ywelsch commented Mar 11, 2016

Thanks @bleskes for porting this to master. Primary terms will be really helpful in many kind of resiliency-related scenarios (solved previously with ugly hacks, e.g. routedBasedOnClusterVersion (#16274)).
I left some comments and more general thoughts about primary terms. I haven't looked at src/test/** yet but can do this in a second iteration.

@bleskes
Copy link
Contributor Author

bleskes commented Mar 12, 2016

@ywelsch I pushed a new implementation. I'm starting to warm up to making shard routing immutable on the index shard level (different PR, and not now :))

@bleskes
Copy link
Contributor Author

bleskes commented Mar 13, 2016

Pushed another commit fixing a side effect of changing the exception types from IllegalShardStateException to IllegalArgumentException (to help with #17038 ) - the replica wrapper shouldn't fail shards locally anymore (technical engine level errors are still dealt with by the engine), but leave it to the primary. It was originally added in #5847 but with current machinery it's not needed.

It's also useful to note that adding assertions of the terms invariants to IndexShard forced some clean ups in IndicesClusterService (as @ywelsch already suspected).

I will update the PR description with these and whatever else we find once the review cycles are done.

@@ -1128,6 +1106,9 @@ protected boolean shouldExecuteReplication(Settings settings) {
boolean isRelocated();
void failShard(String reason, @Nullable Throwable e);
ShardRouting routingEntry();

/** returns the primary term of the current opration */
Copy link
Contributor

Choose a reason for hiding this comment

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

opration -> operation

}
indexService.removeShard(existingShardId, "removing shard (index is closed)");
indexService.removeShard(existingShard.id(), "removing shard (index is closed)");
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this somewhat duplicate functionality that is also in applyCleanedIndices? Maybe combine both of them here? It is weird that applyCleanedIndices removes shards.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

agreed and discussed :)

@ywelsch
Copy link
Contributor

ywelsch commented Mar 14, 2016

Left comments/questions here and there. Updating primary terms in AllocationService makes it so much easier to understand how they change (just a single if statement, yay) 😄.

@bleskes
Copy link
Contributor Author

bleskes commented Mar 14, 2016

@ywelsch thanks for the review. I pushed an update

// we do not use newPrimary.isTargetRelocationOf(oldPrimary) because that one enforces newPrimary to
// be initializing. However, when the target shard is activated, we still want the primary term to staty
// the same
(oldPrimary.relocating() && newPrimary.isSameAllocation(oldPrimary.buildTargetRelocatingShard()))) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I believe we can safely expand the semantics of isRelocationTargetOf to also incorporate this case. This means changing isRelocationTarget, isRelocationTargetOf and isRelocationSourceOf such that it not only accounts for INITIALIZING state. (It is a safe change as a STARTED shard can never be a relocation source and RELOCATING shard can never be a relocation target).

For example, replacing

public boolean isRelocationTargetOf(ShardRouting other) {
    return this.allocationId != null && other.allocationId != null && this.state == ShardRoutingState.INITIALIZING &&
        this.allocationId.getId().equals(other.allocationId.getRelocationId());

by

public boolean isRelocationTargetOf(ShardRouting other) {
    return this.allocationId != null && other.allocationId != null && other.state == ShardRoutingState.RELOCATING  &&
        this.allocationId.getId().equals(other.allocationId.getRelocationId());

Can be a follow-up, just something to think about.

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 agree - this is confusing ( I got it wrong first too). I don't want to expand the scope of this PR too much , so prefer a follow up..

@ywelsch
Copy link
Contributor

ywelsch commented Mar 24, 2016

Left really minor comments. I think we're good with the changes in IndicesClusterStateService. Thanks again for porting this to master.

@bleskes
Copy link
Contributor Author

bleskes commented Mar 25, 2016

Thx @ywelsch @jasontedor . I pushed an update and responded to comments

@ywelsch
Copy link
Contributor

ywelsch commented Mar 25, 2016

LGTM

Primary terms is a way to make sure that operations replicated from stale primary are rejected by shards following a newly elected primary.

Original PRs adding this to the seq# feature branch elastic#14062 , elastic#14651 . Unlike those PR, here we take a different approach (based on newer code in master) where the primary terms are stored in the meta data only (and not in `ShardRouting` objects).

Relates to elastic#17038

Closes elastic#17044
@bleskes bleskes merged commit fe43eef into elastic:master Mar 25, 2016
@bleskes bleskes deleted the primary_terms branch March 25, 2016 11:16
bleskes added a commit to bleskes/elasticsearch that referenced this pull request Mar 29, 2016
…ica should be retried

In extreme cases a local primary shard can be replaced with a replica while a replication request is in flight and the primary action is applied to the shard (via `acquirePrimaryOperationLock()).  elastic#17044 changed the exception used in that method to something that isn't recognized as `TransportActions.isShardNotAvailableException`, causing the operation to fail immediately instead of retrying. This commit fixes this by check the primary flag before
acquiring the lock. This is safe to do as an IndexShard will never be demoted once a primary.

Closes elastic#17358
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants