The throughput and stability of a Consumer Group depend heavily on which Partition Assignor (assignment strategy) you choose. In particular, the stop-the-world time during rebalances is strongly tied to both the strategy and the details of the client implementation.
Here we organize the differences between Range, RoundRobin, Sticky, and Cooperative-Sticky based on their official behavior, from both a practical and a CCDAK exam-prep angle. It is safer to explicitly configure the strategy that matches your requirements rather than relying on the default.
In a Kafka Consumer Group, each partition of the subscribed topics is assigned to exactly one consumer within the same group. The Partition Assignor decides which consumer gets which partitions. You can list multiple class names in the Kafka client setting partition.assignment.strategy, and the group adopts the first entry that every member commonly supports.
The four representative strategies are RangeAssignor, RoundRobinAssignor, StickyAssignor, and CooperativeStickyAssignor. Range, RoundRobin, and Sticky use the Eager protocol (revoking everything first), while Cooperative-Sticky uses the Cooperative protocol (incremental revocation). This rebalance-protocol distinction directly drives stop-the-world time and movement cost.
One caveat: the Assignor only takes effect when you use subscribe for normal group consumption. If you use assign for manual partition assignment, the Assignor is not involved at all. Also, the default strategy is still RangeAssignor in most versions. For latency-sensitive workloads or large groups, explicitly configuring Cooperative-Sticky is the standard practice.
RangeAssignor sorts the subscribing members per topic and assigns partitions as contiguous ranges. For each topic, it splits evenly based on partitions ÷ consumers, and any leftover partitions go to the leading members first. For a single topic the behavior is intuitive and stable, but when the same group subscribes to multiple topics, the same member tends to land on the leading side for every topic, which tends to skew the total assignment.
For example, with T1 (6 partitions) and T2 (4 partitions) consumed by three members, the two leftovers from T1 and the one leftover from T2 all skew toward the leading members, so a single member tends to end up with a larger total assignment. On CCDAK, the line "Range tends to skew across multiple topics" is a frequently tested point.
RoundRobinAssignor lines up every partition across all target topics and distributes them to subscribing members in a single global round-robin pass. When all members subscribe to the same set of topics, the result is extremely even, even across topic boundaries.
However, when each member subscribes to a different set of topics, assignments become hard to predict and rebalances tend to move a relatively large number of partitions. Because the pattern is easily disrupted on each rebalance, this is unfavorable for low-latency requirements.
StickyAssignor aims to combine balance with minimal change from the previous assignment (stickiness). Even when members join or leave, or partition counts change, it moves only what is necessary while keeping the total partition count per member balanced. The protocol is Eager, so a broad revocation still occurs during a rebalance.
CooperativeStickyAssignor keeps the goals of Sticky but switches the protocol to Cooperative (incremental). Because it revokes and reassigns only the necessary partitions in stages, it avoids stop-the-world pauses and suppresses latency spikes. It is generally available in recent Kafka and Confluent versions, but check broker and client support in your environment before enabling it.
| Strategy | Rebalance Protocol | Balance | Reassignment Size |
|---|---|---|---|
| Range | Eager | Roughly even within a topic; tends to skew when summed across topics | Medium-large |
| RoundRobin | Eager | Extremely even overall (when subscription sets are identical) | Large (significant movement during membership changes) |
| Sticky | Eager | Balance between evenness and minimal change | Small (but full revocation still occurs) |
| Cooperative-Sticky | Cooperative (incremental) | Balance + minimal change | Minimal (incremental revocation) |
With Eager, all members first release their partitions and are then reassigned. A brief but complete stop-the-world is likely, which is why commit and state-management design matter. Even Sticky cannot avoid this pause as long as the protocol is Eager.
Cooperative revokes only the minimum necessary partitions while letting the rest keep processing. It converges to the final assignment over multiple stages, suppressing latency spikes and throughput dips. In a ConsumerRebalanceListener implementation, onPartitionsRevoked should reliably commit and stop only the subset that is actually being revoked, and onPartitionsAssigned should resume safely.
Incremental revocation with Cooperative-Sticky (when a new consumer joins)
Timeline --->
C1: [P0][P1][P2] --> revoke [P2] --> [P0][P1] --> final: [P0][P1]
C2: [P3][P4][P5] --> revoke [P5] --> [P3][P4] --> final: [P3][P4]
C3: (join) --------------> assign [P2][P5] --> final: [P2][P5]
Key point: members do not all stop at once; only the necessary partitions are moved in stages to converge.partition.assignment.strategy is specified as a list of class names. In a rolling migration, the common element (for example, Range) is chosen while old and new clients coexist, and once every host supports Cooperative-Sticky, the group automatically switches over. Order the list to enable that handoff.
When using Cooperative, the ConsumerRebalanceListener implementation must reliably commit and stop only the revoked partitions and resume safely upon reassignment. For stateful processing (local caches, external sessions), prepare stop and resume logic that assumes partial revocation.
Configuration example (Java / properties) and a rebalance listener
# Java Properties example (rolling migration: Cooperative first, Range as fallback)
Properties props = new Properties();
props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "broker:9092");
props.put(ConsumerConfig.GROUP_ID_CONFIG, "orders-group");
props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());
props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());
props.put(ConsumerConfig.PARTITION_ASSIGNMENT_STRATEGY_CONFIG, java.util.List.of(
org.apache.kafka.clients.consumer.CooperativeStickyAssignor.class.getName(),
org.apache.kafka.clients.consumer.RangeAssignor.class.getName()
));
// optional: reduce rebalance frequency with static membership
// props.put(ConsumerConfig.GROUP_INSTANCE_ID_CONFIG, "orders-c1");
KafkaConsumer<String, String> consumer = new KafkaConsumer<>(props);
// RebalanceListener written with Cooperative in mind
Map<TopicPartition, OffsetAndMetadata> currentOffsets = new HashMap<>();
ConsumerRebalanceListener listener = new ConsumerRebalanceListener() {
@Override
public void onPartitionsRevoked(Collection<TopicPartition> partitions) {
// sync-commit only the revoked partitions (split explicit commits if needed)
Map<TopicPartition, OffsetAndMetadata> toCommit = new HashMap<>();
for (TopicPartition tp : partitions) {
OffsetAndMetadata off = currentOffsets.get(tp);
if (off != null) toCommit.put(tp, off);
}
if (!toCommit.isEmpty()) consumer.commitSync(toCommit);
}
@Override
public void onPartitionsAssigned(Collection<TopicPartition> partitions) {
// implement seek / resume logic as needed
}
};
consumer.subscribe(java.util.List.of("orders"), listener);
# consumer.properties example (same ordering)
# partition.assignment.strategy is a comma-separated list of class names
partition.assignment.strategy=org.apache.kafka.clients.consumer.CooperativeStickyAssignor,org.apache.kafka.clients.consumer.RangeAssignorThe exam tends to test each strategy's balance, reassignment volume, and rebalance protocol (Eager vs. Cooperative), along with multi-topic skew (Range), maximum evenness when subscription sets are identical (RoundRobin), and stickiness (Sticky family). Also lock in the configuration key (partition.assignment.strategy) and the selection logic when multiple candidates are listed (the first commonly supported one).
In practice, treat Cooperative-Sticky as the default choice for low-latency, large groups, and stateful processing, and migrate via a rolling upgrade. Even if you keep Range as the default, always be aware of multi-topic skew and monitor consumption lag and load imbalance through metrics.
CCDAK
問題 1
For latency-sensitive streaming, you want to minimize stop-the-world time when scaling out a Consumer Group. Which combination of assignment strategy and migration steps is appropriate?
正解: A
Cooperative (incremental) rebalance is effective for minimizing pauses. In a rolling migration, the common Range is selected while old and new coexist, and listing CooperativeSticky first lets it activate automatically once every host supports it — that's the textbook approach. B stays Eager and hardly reduces pauses. C destroys both balance and stability. D is a sloppy Eager-style implementation; with Cooperative you should safely commit only the revoked partitions.
What is the default Partition Assignor in Kafka?
RangeAssignor is the default in most versions. For low-latency or large consumer groups, it is common practice to explicitly configure CooperativeStickyAssignor.
Can consumers with different assignment strategies coexist in the same group?
Yes. From each member's partition.assignment.strategy list, the group selects the first strategy that all members commonly support. During migration, it is safe to list CooperativeStickyAssignor first and RangeAssignor second.
When does load become imbalanced with RangeAssignor?
When the same group subscribes to multiple topics with different partition counts. Leftover partitions from each topic tend to fall on the same member, which can skew the total assignment.
Practice with certification-focused question sets
無料で問題を解いてみるNicheeLab Editorial Team
NicheeLab editorial team focused on data engineering and cloud certification learning. Content is structured around practical study needs and official exam domains.
Kafka Topics & Partitions: Distribution Fundamentals (2026)
How Kafka topics and partitions enable scale — ordering guar...
CCDAK Exam Guide: Confluent Certified Developer (2026)
Complete prep for the CCDAK exam — Producer/Consumer API, St...
CCAAK Exam Guide: Confluent Certified Administrator (2026)
Pass the CCAAK exam — cluster management, partitions, securi...
Kafka Replicas & ISR: Fault Tolerance Explained (2026)
Replica placement, in-sync replicas (ISR), leader election. ...
Kafka Offsets: Commit Modes & Consumer Position (2026)
Offset semantics — auto vs. manual commit, __consumer_offset...