Consumer Group のスループットや安定性は、どの Partition Assignor(割当戦略)を選ぶかで大きく変わります。特に再バランス時の停止時間は、戦略選択とクライアント実装の細部に強く依存します。
ここでは Range / RoundRobin / Sticky / Cooperative-Sticky の違いを、公式挙動に基づき実務と CCDAK 対策の両面から整理します。既定値に任せず、要件に応じて明示設定するのが安全です。
Kafka の Consumer Group では、同一 Group 内の消費者に対し、購読中トピックの各パーティションが重複なく割り当てられます。どの消費者にどのパーティションを割り振るかを決めるのが Partition Assignor です。Kafka クライアント設定 partition.assignment.strategy に複数クラス名を並べられ、Group はメンバー全員が共通でサポートするリストの先頭を採用します。
代表的な戦略は RangeAssignor、RoundRobinAssignor、StickyAssignor、CooperativeStickyAssignor の4つです。Range/RoundRobin/Sticky は Eager(全リボーク前提)、Cooperative-Sticky は Cooperative(段階的リボーク)という再バランス・プロトコルの違いが、停止時間と移動コストに直結します。
注意点として、subscribe を使う通常の Group 消費では Assignor が効きますが、assign を使って手動割当をすると Assignor は関与しません。また、デフォルト戦略は多くのバージョンで RangeAssignor のままです。レイテンシが厳しいワークロードや大規模 Group では Cooperative-Sticky を明示設定するのが実務の定石です。
RangeAssignor は「トピックごと」に、購読メンバーをソートし、パーティションを連続範囲で配分します。各トピックについて partitions ÷ consumers を基準に均等割りし、余りは先頭メンバーから順に多めに受け取ります。単一トピックでは直感的で安定しやすい一方、複数トピックを同一 Group が購読する場合、同じメンバーが各トピックで“先頭側”を取りやすく、総割当が偏る傾向があります。
例えば T1(6パーティション)と T2(4パーティション)を3消費者で購読すると、T1 の余り2つと T2 の余り1つが先頭側に寄り、同一メンバーの総割当が増えがちです。CCDAK では『Range はマルチトピックで偏りやすい』が頻出ポイントです。
RoundRobinAssignor は、対象となる全トピックの全パーティションを並べ、購読しているメンバーに対し「全体でのラウンドロビン」で配分します。購読集合が同一であれば、トピックをまたいでも非常に均等です。
ただし、メンバーごとに購読トピックが異なる場合、割当の見通しが悪くなり、メンバー増減時の移動が比較的大きくなります。再バランスのたびにパターンが崩れやすい点は、低遅延要件では不利です。
StickyAssignor は『均等さ』と『前回からの変更最小化(スティッキネス)』の両立を目指します。会員増減やパーティション数変化があっても、必要最小限だけを動かしつつ、各メンバーの総割当個数が均等になるよう調整します。プロトコルは Eager で、再バランス時はいったん広くリボークが発生します。
CooperativeStickyAssignor は Sticky の目標を保ったまま、プロトコルを Cooperative(増分的)にします。段階的に『必要なパーティションだけ』をリボーク・再割当するため、ストップ・ザ・ワールドを避けやすく、遅延スパイクを抑制できます。一般に Kafka/Confluent の近年バージョンで利用可能ですが、環境のサポート状況(ブローカーとクライアントの対応)を確認してから有効化してください。
| 戦略 | 再バランス方式 | 均等性 | 再配置の大きさ |
|---|---|---|---|
| Range | Eager | トピック内では概ね均等、複数トピック合算で偏りがち | 中〜大 |
| RoundRobin | Eager | 全体で非常に均等(購読集合が同じ場合) | 大(会員変動時の動きが大きい) |
| Sticky | Eager | 均等性と変更最小化のバランス | 小(ただし全体リボークは発生) |
| Cooperative-Sticky | Cooperative(増分) | 均等性 + 変更最小化 | 最小(段階的リボーク) |
Eager は全メンバーが一旦パーティションを手放し、その後に再割当します。短時間でも全体停止しやすく、コミットや状態管理の設計が重要です。Sticky 系でも Eager の場合はこの停止を避けられません。
Cooperative は、必要最小限のパーティションだけをリボークし、残りは処理を継続できます。多段階の調整で最終配置へと収束し、レイテンシのスパイクとスループット低下を抑制します。ConsumerRebalanceListener 実装では、onPartitionsRevoked で『実際にリボークされる一部だけ』を確実にコミット・停止し、onPartitionsAssigned で安全に再開します。
Cooperative-Sticky による段階的リボーク(新規 Consumer 参加時)
時系列 --->
C1: [P0][P1][P2] ──> revoke [P2] ──> [P0][P1] ──> 最終: [P0][P1]
C2: [P3][P4][P5] ──> revoke [P5] ──> [P3][P4] ──> 最終: [P3][P4]
C3: (join) ────────────────> assign [P2][P5] ──> 最終: [P2][P5]
ポイント: 全メンバーが一斉停止せず、必要分だけを段階的に移動して収束する。partition.assignment.strategy はクラス名のリストで指定します。ローリング移行では、新旧が混在する間は共通部分(例: Range)が選ばれ、全台が Cooperative-Sticky をサポートした段階で自動的に Cooperative-Sticky に切り替わるよう並べます。
Cooperative を使う際は、ConsumerRebalanceListener でリボーク対象だけを確実にコミット・停止し、再割当で安全に再開する実装が重要です。状態付き処理(ローカルキャッシュや外部セッション)では、partial revoke を想定した停止・再開処理を用意してください。
設定例(Java / properties)とリバランスリスナー
# Java Properties 例(ローリング移行: Cooperative を先頭、Range をフォールバック)
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: static membership で再バランス頻度を低減
// props.put(ConsumerConfig.GROUP_INSTANCE_ID_CONFIG, "orders-c1");
KafkaConsumer<String, String> consumer = new KafkaConsumer<>(props);
// Cooperative を意識した RebalanceListener
Map<TopicPartition, OffsetAndMetadata> currentOffsets = new HashMap<>();
ConsumerRebalanceListener listener = new ConsumerRebalanceListener() {
@Override
public void onPartitionsRevoked(Collection<TopicPartition> partitions) {
// リボーク対象のみを同期コミット(必要に応じて明示コミットを分割)
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) {
// 必要に応じてシーク/再開処理を実装
}
};
consumer.subscribe(java.util.List.of("orders"), listener);
# consumer.properties 例(同様の並び順)
# partition.assignment.strategy はカンマ区切りでクラス名を列挙
partition.assignment.strategy=org.apache.kafka.clients.consumer.CooperativeStickyAssignor,org.apache.kafka.clients.consumer.RangeAssignor試験では、戦略の『均等性』『再配置量』『再バランス方式(Eager/Cooperative)』と、『マルチトピック時の偏り(Range)』『購読集合が同じときに最も均等(RoundRobin)』『スティッキネス(Sticky 系)』が問われがちです。設定キー名(partition.assignment.strategy)と、複数候補を並べたときの選択ロジック(共通先頭)も押さえておきましょう。
実務では、低遅延・大規模 Group・状態付き処理では Cooperative-Sticky を基本選択肢にし、移行はローリングで。Range の既定値をそのまま使う場合でも、マルチトピックでの偏りを常に念頭に置き、メトリクスで消費遅延や負荷の偏りを監視するのが安全です。
CCDAK
問題 1
レイテンシ敏感なストリーミング処理で、Consumer Group のスケールアウト時の停止時間を最小化したい。適切な割当戦略と移行手順の組み合わせはどれか。
正解: A
停止時間最小化には Cooperative(増分)リバランスが有効。ローリング移行では新旧混在中は共通の Range が選ばれ、全台が対応後に CooperativeSticky が自動適用されるよう先頭に置くのが定石。B は Eager のままで停止時間が減りにくい。C は均等性と安定性を損なう。D は Eager 前提の雑な実装で、Cooperative ではリボーク対象のみを安全にコミットすべき。
Kafka の既定の Partition Assignor は何ですか?
多くのバージョンで RangeAssignor が既定です。低遅延や大規模 Group では CooperativeStickyAssignor を明示設定するのが一般的です。
同じ Group に異なる戦略を設定した Consumer が混在しても動きますか?
はい。各メンバーの partition.assignment.strategy のリストから、全員が共通でサポートする戦略の最初のものが採用されます。移行時は CooperativeStickyAssignor を先頭、RangeAssignor を次に置く並べ方が安全です。
RangeAssignor で負荷が偏るのはどんなときですか?
同一 Group が複数トピックを同時に購読し、各トピックのパーティション数が異なる場合です。各トピックで余りが同じメンバーに寄りやすく、総割当が偏る可能性があります。
NicheeLab編集部
データエンジニアリング・クラウド資格の専門家。Databricks・Snowflake等の認定資格を保有し、実務経験に基づいた問題作成・解説を行っています。NicheeLab運営。
Kafka Topic と Partition の基礎: 分散とスケーラビリティの要
CCDAK 対策と実務の両立を意識し、Topic/Partition/Replica/Consumer Group の役...
CCDAK 試験ガイド:出題範囲・配点・申込み・対策
Confluent Certified Developer for Apache Kafka (CCDAK) の出題範囲...
Confluent Certified Administrator (CCAAK) 対策: 出題範囲・配点の考え方・運用観点の要点
CCAAKに向けて、試験領域の押さえどころを運用目線で整理。プロダクションで通用する設定・監視・セキュリティの実践知を、...
Kafka の Replica と In-Sync Replicas を正しく設計する: 耐障害性と一貫性
レプリカとISRの仕組みを起点に、acks と min.insync.replicas、クリーン/アンクリーンリーダー選...
Kafka の Offset とコミット: ポジション管理と at-least-once の基礎
CCDAK 対策と実務の両立を意識して、Kafka コンシューマのオフセット管理とコミット戦略を整理。at-least-...