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

Avoid copying during iteration of all shards in routing table #94417

Merged
merged 5 commits into from
Mar 10, 2023

Conversation

luyuncheng
Copy link
Contributor

@luyuncheng luyuncheng commented Mar 9, 2023

we used cat/allocation to get cluster allocation.

the logic in the code:

for (ShardRouting shard : state.getState().routingTable().allShards()) {
String nodeId = "UNASSIGNED";
if (shard.assignedToNode()) {
nodeId = shard.currentNodeId();
}
allocs.merge(nodeId, 1, Integer::sum);
}

public List<ShardRouting> allShards() {
List<ShardRouting> shards = new ArrayList<>();
for (String index : indicesRouting.keySet()) {
List<ShardRouting> allShardsIndex = allShards(index);
shards.addAll(allShardsIndex);
}
return shards;
}

it would iterator all shards twice, we can deduplicated it

@elasticsearchmachine elasticsearchmachine added v8.8.0 external-contributor Pull request authored by a developer outside the Elasticsearch team needs:triage Requires assignment of a team area label labels Mar 9, 2023
@DaveCTurner DaveCTurner added >bug :Distributed Coordination/Allocation All issues relating to the decision making around placing a shard (both master logic & on the nodes) and removed needs:triage Requires assignment of a team area label labels Mar 9, 2023
@DaveCTurner DaveCTurner self-assigned this Mar 9, 2023
@elasticsearchmachine
Copy link
Collaborator

Pinging @elastic/es-distributed (Team:Distributed)

@elasticsearchmachine elasticsearchmachine added the Team:Distributed (Obsolete) Meta label for distributed team (obsolete). Replaced by Distributed Indexing/Coordination. label Mar 9, 2023
Copy link
Contributor

@DaveCTurner DaveCTurner left a comment

Choose a reason for hiding this comment

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

I think your analysis is correct. However, this will apply to all callers of RoutingTable#allShards() - there's just no good reason to copy all the shards in the cluster into a new list like this, so I think it would be better to fix the method on RoutingTable so that all callers (including future callers) will see the benefits. For instance, try making it return Iterable<ShardRouting> (you'll probably find org.elasticsearch.common.collect.Iterators#flatMap to be useful in this endeavour) or Stream<ShardRouting>.

Copy link
Contributor

@DaveCTurner DaveCTurner left a comment

Choose a reason for hiding this comment

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

Looks ok to me, but @original-brownbear IIRC we removed some methods that made it easy to iterate over the routing table because they were over-used and much more expensive than doing it by index. Are you ok with bringing them back in this limited format to avoid GET _cat/shards and GET _cat/allocation having to do all that copying?

@DaveCTurner
Copy link
Contributor

@elasticmachine ok to test

@luyuncheng
Copy link
Contributor Author

Are you ok with bringing them back in this limited format to avoid GET _cat/shards and GET _cat/allocation having to do all that copying?

LGTM , let me try it

@DaveCTurner
Copy link
Contributor

LGTM , let me try it

@luyuncheng sorry that question was intended for @original-brownbear who worked on related optimisations such as #84987 and #84955. No need for you to do anything here.

@original-brownbear
Copy link
Member

@DaveCTurner yea definitely, that makes sense to me!

Copy link
Contributor

@DaveCTurner DaveCTurner left a comment

Choose a reason for hiding this comment

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

LGTM then 😄

@DaveCTurner DaveCTurner changed the title Reduce iterator duplicated in RestAllocationAction Avoid copying during iteration of all shards in routing table Mar 9, 2023
@luyuncheng
Copy link
Contributor Author

LGTM , let me try it

@luyuncheng sorry that question was intended for @original-brownbear who worked on related optimisations such as #84987 and #84955. No need for you to do anything here.

Got it , it is great that #84987 and #84955 optimized.

@DaveCTurner DaveCTurner merged commit 78f5cf0 into elastic:main Mar 10, 2023
DaveCTurner added a commit to DaveCTurner/elasticsearch that referenced this pull request Apr 11, 2023
Today when applying a new cluster state we block the cluster applier thread for
up to 5s while waiting to acquire each shard lock. Failure to acquire the shard
lock is treated as an allocation failure, so after 5 retries (by default) we
give up on the allocation.

The shard lock may be held by some other actor, typically the previous
incarnation of the shard which is still shutting down, but it will eventually
be released. Yet, 5 retries of 5s each is sometimes not enough time to wait.
Knowing that the shard lock will eventually be released, we can retry much more
tenaciously.

Moreover there's no reason why we have to create the `IndexShard` while
applying the cluster state, because the shard remains in state `INITIALIZING`,
and therefore unused, while it coordinates its own recovery.

With this commit we try and acquire the shard lock during cluster state
application, but do not wait if the lock is unavailable. Instead, we schedule a
retry (also executed on the cluster state applier thread) and proceed with the
rest of the cluster state application process.

Relates elastic#24530
Backport of elastic#94545 and elastic#94623 (and a little bit of elastic#94417) to 8.7
DaveCTurner added a commit that referenced this pull request Apr 11, 2023
Today when applying a new cluster state we block the cluster applier thread for
up to 5s while waiting to acquire each shard lock. Failure to acquire the shard
lock is treated as an allocation failure, so after 5 retries (by default) we
give up on the allocation.

The shard lock may be held by some other actor, typically the previous
incarnation of the shard which is still shutting down, but it will eventually
be released. Yet, 5 retries of 5s each is sometimes not enough time to wait.
Knowing that the shard lock will eventually be released, we can retry much more
tenaciously.

Moreover there's no reason why we have to create the `IndexShard` while
applying the cluster state, because the shard remains in state `INITIALIZING`,
and therefore unused, while it coordinates its own recovery.

With this commit we try and acquire the shard lock during cluster state
application, but do not wait if the lock is unavailable. Instead, we schedule a
retry (also executed on the cluster state applier thread) and proceed with the
rest of the cluster state application process.

Relates #24530
Backport of #94545 and #94623 (and a little bit of #94417) to 8.7
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
>bug :Distributed Coordination/Allocation All issues relating to the decision making around placing a shard (both master logic & on the nodes) external-contributor Pull request authored by a developer outside the Elasticsearch team Team:Distributed (Obsolete) Meta label for distributed team (obsolete). Replaced by Distributed Indexing/Coordination. v8.8.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants