-
Notifications
You must be signed in to change notification settings - Fork 25k
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
Port Primary Terms to master #17044
Conversation
@@ -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"); |
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.
This exception will be treated as ignore replica exception. 😉
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 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).
@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; | ||
} |
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 guess this can be reused to replace routedBasedOnClusterVersion
(#16274). Yay 👍
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.
interesting idea - it's currently not incremented when relocating a primary though... requires more thought.
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. |
@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 :)) |
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 */ |
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.
opration -> operation
} | ||
indexService.removeShard(existingShardId, "removing shard (index is closed)"); | ||
indexService.removeShard(existingShard.id(), "removing shard (index is closed)"); |
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.
Is this somewhat duplicate functionality that is also in applyCleanedIndices
? Maybe combine both of them here? It is weird that applyCleanedIndices
removes 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.
agreed and discussed :)
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) 😄. |
@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()))) { |
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 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.
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 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..
Left really minor comments. I think we're good with the changes in IndicesClusterStateService. Thanks again for porting this to master. |
Thx @ywelsch @jasontedor . I pushed an update and responded to comments |
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
…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
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