従来の Eager Rebalance は全コンシューマーが一斉にパーティションを手放すため、短時間でも“全停止”が発生しやすく、遅延やスループット低下の原因になっていました。
Cooperative Rebalance は割り当てを段階的・増分で移し替えることで Stop-the-world を避ける最新のプロトコルです。ここでは仕組み、導入手順、コールバック設計、運用の勘所を CCDAK 受験にも役立つ視点で解説します。
Eager Rebalance では、メンバーの増減や設定変更をきっかけに、グループ内の全コンシューマーが一度すべてのパーティションを手放し、再割り当てを待ちます。短時間でも消費停止が全体に波及するため、レイテンシ尖りや処理スループットの落ち込みを招きます。
実務ではローリングデプロイ、スケールアウト、ネットワーク揺らぎ等が頻発し、再均衡の回数が増えがちです。Stop-the-world を抑えることは、そのまま SLO の安定やピーク時の耐性に直結します。
Eager Rebalance(従来)の典型設定例
props.put("partition.assignment.strategy", java.util.List.of(
"org.apache.kafka.clients.consumer.RangeAssignor"
));
// デフォルトは RangeAssignor(Eager)で、全メンバーが一旦 revoke されるIncremental Cooperative Rebalancing は、必要最小限のパーティションのみを段階的に移動します。既存メンバーの大半は割り当てを維持したまま、移動対象だけを revoke/assign するため、Stop-the-world を避けられます。
コンシューマー側は ConsumerRebalanceListener のコールバックで、revoke されたものだけを安全にコミット・解放し、assign されたものを消費開始します。グレースフルに revoke できなかった場合のために onPartitionsLost が呼ばれるケースを考慮します。
| 戦略 | 挙動 | Stop-the-world | 主なコールバック |
|---|---|---|---|
| Eager (Range/RoundRobin/Sticky) | 全メンバーが一度全パーティションを手放す | 発生しやすい | onPartitionsRevoked/Assigned(Lost は想定外) |
| CooperativeSticky | 必要最小限のみ増分移動(段階的) | ほぼ回避可能 | onPartitionsRevoked/Assigned/Lost |
| Sticky(Eager) | 移動量は抑えるが全 revoke は発生 | 軽減するが回避は不可 | onPartitionsRevoked/Assigned |
増分的な移動イメージ(Cooperative Rebalance)
Cooperative Sticky Assignor の有効化
props.put("partition.assignment.strategy", java.util.List.of(
"org.apache.kafka.clients.consumer.CooperativeStickyAssignor"
));
// 可能なら全メンバーで同一戦略に統一すること同一コンシューマーグループ内では、実効的に選ばれるアサイナーは“共通集合の先頭”になります。混在期間は予期せぬフォールバック(Eager 化)を招くため、切替は計画的に行います。
最も安全なのは、全メンバーを CooperativeStickyAssignor をサポートするバージョンへ先に上げ、その後に戦略を統一するか、新しい group.id へ移行する方法です。
安全な切替(例: 新 group.id を用いた段階移行)
# 1) 先にアプリを CooperativeStickyAssignor 対応版へデプロイ
# 2) 新しい group.id で起動し、旧グループから段階的にトラフィック移行
props.put("group.id", "orders-consumer-v2");
props.put("partition.assignment.strategy", java.util.List.of(
"org.apache.kafka.clients.consumer.CooperativeStickyAssignor"
));Cooperative では revoke されるパーティションだけを整然と閉じられます。onPartitionsRevoked 内では、対象パーティションの未処理を flush/commit し、外部リソースを解放します。onPartitionsAssigned では新規割り当ての初期化を軽量に行います。
onPartitionsLost は異常系(グレースフルに返却できなかった)で呼ばれます。ここでは“未処理が確実に再処理されうる”前提で、状態を破棄・再初期化する方が安全です。
ConsumerRebalanceListener の骨子(Java)
consumer.subscribe(List.of("orders"), new ConsumerRebalanceListener() {
@Override
public void onPartitionsRevoked(Collection<TopicPartition> partitions) {
// revoke 対象だけを同期コミット・クローズ
commitOffsetsFor(partitions);
closeResourcesFor(partitions);
}
@Override
public void onPartitionsAssigned(Collection<TopicPartition> partitions) {
// 必要最小の初期化。重い処理は避ける
initStateFor(partitions);
}
@Override
public void onPartitionsLost(Collection<TopicPartition> partitions) {
// 異常系。未処理は再処理前提で状態を破棄
dropStateFor(partitions);
}
});Stop-the-world を避けられても、再均衡そのものは発生します。タイムアウトやハートビートはアプリの処理時間と整合させます。特に max.poll.interval.ms は“1回の poll で処理できる最大時間”に見合う値が必要です。
監視では consumer lag、rebalancing の発生回数・時間、onPartitionsLost の有無に着目します。静的メンバーシップ(group.instance.id)や cooperative の採用で、グループの churn を最小化します。
監視・点検コマンド例
$ kafka-consumer-groups.sh \
--bootstrap-server broker:9092 \
--group orders-consumer \
--describe
# 再均衡の兆候はアプリログ(JoinGroup/SyncGroup)やメトリクスで確認CCDAK では、Eager と Cooperative の違い、CooperativeStickyAssignor の利点、関連コールバック(特に onPartitionsLost)、静的メンバーシップ併用による安定化といった論点が頻出です。
設定の優先順位や混在時の挙動、ローリングデプロイ時の安全策、コミット設計の原則(重複許容・順序性)を、正確な概念として押さえておくと得点に直結します。
試験で問われやすい設定キー(抜粋)
# コンシューマー設定(代表例)
partition.assignment.strategy=org.apache.kafka.clients.consumer.CooperativeStickyAssignor
max.poll.interval.ms=900000
session.timeout.ms=45000
heartbeat.interval.ms=15000
group.instance.id=orders-c1 # 静的メンバーの例(ユニークに)CCDAK
問題 1
コンシューマーグループのスケールアウト時に Stop-the-world を最小化したい。最も適切なアプローチはどれか。
正解: A
CooperativeStickyAssignor は増分・段階的な再均衡で Stop-the-world を避ける。静的メンバーシップの併用でリバランス自体も減らせる。B は逆効果、C は運用負荷かつ Eager の限界を解決しない、D は Eager で全 revoke を避けられない。
Cooperative にすると二度取り(重複処理)は完全になくなる?
いいえ。Stop-the-world を避ける仕組みであり、重複処理の可能性は依然としてあります。重複許容な処理設計(冪等化、正確なオフセットコミット)と組み合わせて整合性を保ちます。
onPartitionsLost は必ず発生する?
通常は発生しません。ネットワーク断や長時間の停止で“グレースフルに返却できなかった”場合に呼ばれます。ここでは未処理データが再処理される前提で、局所状態を破棄して再初期化するのが安全です。
混在環境で徐々に CooperativeSticky に切り替えてよい?
同一グループで戦略が混在すると、共通集合の先頭にフォールバックし、Eager 挙動に戻る場合があります。安全なのは、全メンバーを対応版に更新してから戦略を統一するか、新しい group.id に移行する方法です。
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-...