Skip to content

Move all Snapshot Master Node Steps to SnapshotsService#56365

Merged
original-brownbear merged 4 commits intoelastic:masterfrom
original-brownbear:cleaner-snapshot-shards-service
May 12, 2020
Merged

Move all Snapshot Master Node Steps to SnapshotsService#56365
original-brownbear merged 4 commits intoelastic:masterfrom
original-brownbear:cleaner-snapshot-shards-service

Conversation

@original-brownbear
Copy link
Copy Markdown
Contributor

@original-brownbear original-brownbear commented May 7, 2020

This refactoring has three motivations:

  1. Separate all master node steps during snapshot operations from all data node steps in code.
  2. Set up next steps in concurrent repository operations and general improvements by centralizing tracking of each shard's state in the repository in SnapshotsService so that operations for each shard can be linearized efficiently (i.e. without having to inspect the full snapshot state for all shards on every cluster state update, allowing us to track more in memory and only fall back to inspecting the full CS on master failover like we do in the snapshot shards service).
    • This PR already contains some best effort examples of this, but obviously this could be way improved upon still (just did not want to do it in this PR for complexity reasons)
  3. Make the SnapshotsService less expensive on the CS thread for large snapshots

This refactoring has two motivations:

1. Separate all master node steps during snapshot operations from all data node steps in code.
2. Set up next steps in concurrent repository operations and general improvments by centralizing tracking
of each shard's state in the repository in `SnapshotShardsService` so that operations for each shard
can be linearized efficiently.
@original-brownbear original-brownbear added >non-issue :Distributed/Snapshot/Restore Anything directly related to the `_snapshot/*` APIs v8.0.0 v7.9.0 labels May 7, 2020
@elasticmachine
Copy link
Copy Markdown
Collaborator

Pinging @elastic/es-distributed (:Distributed/Snapshot/Restore)

@elasticmachine elasticmachine added the Team:Distributed Meta label for distributed team. label May 7, 2020
@original-brownbear original-brownbear marked this pull request as draft May 7, 2020 16:59

@Override
public void clusterStateProcessed(String source, ClusterState oldState, ClusterState newState) {
if (changed) {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This is kind of lazy and obviously a better solution would be to simply track those snapshots that were completed in the update by adding them to a list or so to be processed here. Just didn't want to do that in this PR since it introduces quite a bit of complexity. But I figured just adding the changed flag here and in the other tasks was enough to illustrate the motivation for this change and is already a huge win in terms of not having to iterate all the shards on every CS application.

@original-brownbear original-brownbear marked this pull request as ready for review May 8, 2020 05:10
/**
* Internal request that is used to send changes in snapshot status to master
*/
public static class UpdateIndexShardSnapshotStatusRequest extends MasterNodeRequest<UpdateIndexShardSnapshotStatusRequest> {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This stuff all got moved to SnapshotsService exactly as is without changes

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Now it is used in different services it could maybe be located in its own file

try {
listener.onResponse(new UpdateIndexShardSnapshotStatusResponse());
} finally {
endCompletedSnapshots(newState);
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This is the only change relative to what this code did and looked like in SnapshotShardsService.

// 1. Completed snapshots
// 2. Snapshots in state INIT that a previous master of an older version failed to start
// 3. Snapshots in any other state that have all their shard tasks completed
snapshotsInProgress.entries().stream().filter(
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Running this check on every CS update wasn't great and added a lot of cycles on the CS thread for larger snapshots. It would be even worse when we start actually having multiple snapshot-in-progress entries. We really should only have to do a full check if anything changed about the entries' shards or on master fail-over.
This is change moves all the updating of the shard entries into this class so we can selectively run this check (though see my other comment below, we could be even more selective in a follow-up :)).

logger.info("snapshot [{}] started", snapshot);
listener.onResponse(snapshot);
} finally {
if (newEntry.state().completed() || newEntry.shards().isEmpty()) {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

No need to actually run the full check here over all entries in newState here, the only two options of ending the snapshot here right away are if it has no shards or was set to FAILED right away.

Copy link
Copy Markdown
Member

@tlrx tlrx left a comment

Choose a reason for hiding this comment

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

LGTM, thanks for the helpful comments. I left some very minor suggestions and feel free to follow them or not.

/**
* Internal request that is used to send changes in snapshot status to master
*/
public static class UpdateIndexShardSnapshotStatusRequest extends MasterNodeRequest<UpdateIndexShardSnapshotStatusRequest> {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Now it is used in different services it could maybe be located in its own file

// Set of snapshots that are currently being ended by this node
private final Set<Snapshot> endingSnapshots = Collections.synchronizedSet(new HashSet<>());

private final SnapshotsService.SnapshotStateExecutor snapshotStateExecutor = new SnapshotsService.SnapshotStateExecutor();
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

nit: I don't think it need to be fully qualified?

if (DiscoveryNode.isMasterNode(settings)) {
// addLowPriorityApplier to make sure that Repository will be created before snapshot
clusterService.addLowPriorityApplier(this);
// The constructor of UpdateSnapshotStatusAction will register itself to the TransportService.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

nit: maybe comment this right before this.updateSnapshotStatusHandler = ... and not in this block

private void endCompletedSnapshots(ClusterState state) {
SnapshotsInProgress snapshotsInProgress = state.custom(SnapshotsInProgress.TYPE);
assert snapshotsInProgress != null;
// Cleanup all snapshots that have no more work left:
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

nit: this could be javadoc

@original-brownbear
Copy link
Copy Markdown
Contributor Author

Thanks Tanguy! All nits applied :)

@original-brownbear original-brownbear merged commit 36be0ac into elastic:master May 12, 2020
@original-brownbear original-brownbear deleted the cleaner-snapshot-shards-service branch May 12, 2020 15:21
original-brownbear added a commit that referenced this pull request May 15, 2020
Follow up to #56365. Instead of redundantly checking snapshots for completion
over and over, just track the completed snapshots in the CS updates that complete
them instead of looping over the smae snapshot entries over and over.
Also, in the batched snapshot shard status updates, only check for completion
of a snapshot entry if it isn't already finalizing.
original-brownbear added a commit that referenced this pull request Jul 12, 2020
)

This refactoring has three motivations:

1. Separate all master node steps during snapshot operations from all data node steps in code.
2. Set up next steps in concurrent repository operations and general improvements by centralizing tracking of each shard's state in the repository in `SnapshotsService` so that operations for each shard can be linearized efficiently (i.e. without having to inspect the full snapshot state for all shards on every cluster state update, allowing us to track more in memory and only fall back to inspecting the full CS on master failover like we do in the snapshot shards service).
    * This PR already contains some best effort examples of this, but obviously this could be way improved upon still (just did not want to do it in this PR for complexity reasons)
3. Make the `SnapshotsService` less expensive on the CS thread for large snapshots
original-brownbear added a commit that referenced this pull request Jul 13, 2020
Follow up to #56365. Instead of redundantly checking snapshots for completion
over and over, just track the completed snapshots in the CS updates that complete
them instead of looping over the smae snapshot entries over and over.
Also, in the batched snapshot shard status updates, only check for completion
of a snapshot entry if it isn't already finalizing.
@original-brownbear original-brownbear restored the cleaner-snapshot-shards-service branch August 6, 2020 18:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

:Distributed/Snapshot/Restore Anything directly related to the `_snapshot/*` APIs >non-issue Team:Distributed Meta label for distributed team. v7.9.0 v8.0.0-alpha1

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants