-
Notifications
You must be signed in to change notification settings - Fork 15.4k
KAFKA-14702: Extend server side assignor to support rack aware replica placement #13998
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
Changes from all commits
e8d3607
3df3460
7410529
3b6e65e
4b321aa
b4041a7
7352cbb
57b94ca
5065109
100a04e
73c7fdc
68d53b3
48a9822
dcb8198
9f3a423
a925b02
7d16269
7369db3
918d262
288fa1f
a1bdb58
0737c8d
3d92645
309cc61
7fd7794
dffad67
ef81486
0cd618a
d33bbfa
2d50c27
e56ded2
28ab298
5550e49
feb12ec
cc88822
1c2475b
e1a0325
931bcf7
e9ebc4f
9815d6d
ce540f9
478488e
c50f3bd
f68471a
579bb94
4511683
faafed2
22f2df0
6650ea5
061dac7
57b9a62
a30a534
6fe72df
c0b464c
a39e76f
2d40125
81f1ccd
1c955b5
5a93532
71f8488
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -131,13 +131,21 @@ public static Record newGroupSubscriptionMetadataRecord( | |
| Map<String, TopicMetadata> newSubscriptionMetadata | ||
| ) { | ||
| ConsumerGroupPartitionMetadataValue value = new ConsumerGroupPartitionMetadataValue(); | ||
| newSubscriptionMetadata.forEach((topicName, topicMetadata) -> | ||
| newSubscriptionMetadata.forEach((topicName, topicMetadata) -> { | ||
| List<ConsumerGroupPartitionMetadataValue.PartitionMetadata> partitionMetadata = new ArrayList<>(); | ||
| topicMetadata.partitionRacks().forEach((partition, racks) -> | ||
| partitionMetadata.add(new ConsumerGroupPartitionMetadataValue.PartitionMetadata() | ||
| .setPartition(partition) | ||
| .setRacks(new ArrayList<>(racks)) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we set racks all the time or only when the set is non-empty?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I changed the code now, if no racks are available then an empty map is stored in the topicMetadata and therefore in the subscription metadata. Moreover, an empty list will be stored in the record to save memory |
||
| ) | ||
| ); | ||
| value.topics().add(new ConsumerGroupPartitionMetadataValue.TopicMetadata() | ||
| .setTopicId(topicMetadata.id()) | ||
| .setTopicName(topicMetadata.name()) | ||
| .setNumPartitions(topicMetadata.numPartitions()) | ||
| ) | ||
| ); | ||
| .setPartitionMetadata(partitionMetadata) | ||
| ); | ||
| }); | ||
|
|
||
| return new Record( | ||
| new ApiMessageAndVersion( | ||
|
|
||
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,51 @@ | ||
| /* | ||
| * Licensed to the Apache Software Foundation (ASF) under one or more | ||
| * contributor license agreements. See the NOTICE file distributed with | ||
| * this work for additional information regarding copyright ownership. | ||
| * The ASF licenses this file to You under the Apache License, Version 2.0 | ||
| * (the "License"); you may not use this file except in compliance with | ||
| * the License. You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| */ | ||
| package org.apache.kafka.coordinator.group.assignor; | ||
|
|
||
| import org.apache.kafka.common.Uuid; | ||
| import org.apache.kafka.common.annotation.InterfaceStability; | ||
|
|
||
| import java.util.Set; | ||
|
|
||
| /** | ||
| * The subscribed topic describer is used by the {@link PartitionAssignor} | ||
| * to obtain topic and partition metadata of subscribed topics. | ||
| * | ||
| * The interface is kept in an internal module until KIP-848 is fully | ||
| * implemented and ready to be released. | ||
| */ | ||
| @InterfaceStability.Unstable | ||
| public interface SubscribedTopicDescriber { | ||
| /** | ||
| * Number of partitions for the given topic Id. | ||
| * | ||
| * @param topicId Uuid corresponding to the topic. | ||
| * @return The number of partitions corresponding to the given topicId. | ||
| * If the topicId doesn't exist return -1; | ||
| */ | ||
| int numPartitions(Uuid topicId); | ||
|
|
||
| /** | ||
| * Returns all the racks associated with the replicas for the given partition. | ||
| * | ||
| * @param topicId Uuid corresponding to the partition's topic. | ||
| * @param partition Partition number within topic. | ||
| * @return The set of racks corresponding to the replicas of the topics partition. | ||
| * If the topicId doesn't exist return an empty set; | ||
| */ | ||
| Set<String> racksForPartition(Uuid topicId, int partition); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -19,6 +19,7 @@ | |
| import org.apache.kafka.common.Uuid; | ||
| import org.apache.kafka.common.errors.UnknownMemberIdException; | ||
| import org.apache.kafka.coordinator.group.Group; | ||
| import org.apache.kafka.image.ClusterImage; | ||
| import org.apache.kafka.image.TopicImage; | ||
| import org.apache.kafka.image.TopicsImage; | ||
| import org.apache.kafka.timeline.SnapshotRegistry; | ||
|
|
@@ -28,6 +29,7 @@ | |
|
|
||
| import java.util.Collections; | ||
| import java.util.HashMap; | ||
| import java.util.HashSet; | ||
| import java.util.Map; | ||
| import java.util.Objects; | ||
| import java.util.Optional; | ||
|
|
@@ -434,22 +436,39 @@ public void setSubscriptionMetadata( | |
| public Map<String, TopicMetadata> computeSubscriptionMetadata( | ||
| ConsumerGroupMember oldMember, | ||
| ConsumerGroupMember newMember, | ||
| TopicsImage topicsImage | ||
| TopicsImage topicsImage, | ||
| ClusterImage clusterImage | ||
|
Comment on lines
+439
to
+440
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would it make sense to directly pass
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since metadataImage has a lot more images that we don't need and passing the specific arguments makes it more readable, maintainable, and testable I feel like we can keep it as two separate arguments. |
||
| ) { | ||
| // Copy and update the current subscriptions. | ||
| Map<String, Integer> subscribedTopicNames = new HashMap<>(this.subscribedTopicNames); | ||
| maybeUpdateSubscribedTopicNames(subscribedTopicNames, oldMember, newMember); | ||
|
|
||
| // Create the topic metadata for each subscribed topic. | ||
| Map<String, TopicMetadata> newSubscriptionMetadata = new HashMap<>(subscribedTopicNames.size()); | ||
|
|
||
| subscribedTopicNames.forEach((topicName, count) -> { | ||
| TopicImage topicImage = topicsImage.getTopic(topicName); | ||
| if (topicImage != null) { | ||
| Map<Integer, Set<String>> partitionRacks = new HashMap<>(); | ||
|
|
||
| topicImage.partitions().forEach((partition, partitionRegistration) -> { | ||
| Set<String> racks = new HashSet<>(); | ||
| for (int replica : partitionRegistration.replicas) { | ||
| Optional<String> rackOptional = clusterImage.broker(replica).rack(); | ||
| // Only add rack if it is available for the broker/replica. | ||
| rackOptional.ifPresent(racks::add); | ||
| } | ||
| // If no racks are available for any replica of this partition, store an empty map. | ||
| if (!racks.isEmpty()) | ||
| partitionRacks.put(partition, racks); | ||
| }); | ||
|
|
||
| newSubscriptionMetadata.put(topicName, new TopicMetadata( | ||
| topicImage.id(), | ||
| topicImage.name(), | ||
| topicImage.partitions().size() | ||
| )); | ||
| topicImage.partitions().size(), | ||
| partitionRacks) | ||
| ); | ||
| } | ||
| }); | ||
|
|
||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.