Kafka

Kafka リバランスの流れと影響: イベント発生条件と停止時間の削減

2026-04-19
NicheeLab編集部

リバランスはコンシューマグループの安定性と可用性に直結します。試験では概念と設定の因果、運用では停止時間の最小化が要点です。

本稿は公式挙動に基づき、イベント発生条件、プロトコル差分、設定のトレードオフ、監視・運用までを一気通貫で解説します。

Kafka リバランスの基本と前提

リバランスは、コンシューマグループ内でパーティション割り当てを再計算し直すプロセスです。グループコーディネータが JoinGroup と SyncGroup の往復でメンバーに割り当てを通知し、各メンバーは再開前に revoke/assign の処理を行います。

プロトコルには大きく Eager と Cooperative(増分)があります。Eager は全メンバーが一度すべてのパーティションを手放す方式で停止時間が伸びがち、Cooperative は段階的に譲り合うため停止時間を短縮できます。

  • グループの安定状態は Stable、リバランス中は PreparingRebalance/CompletingRebalance を遷移
  • 再均衡時は onPartitionsRevoked でコミット、onPartitionsAssigned で初期化が基本
  • 停止時間は「全メンバーが読めない時間」ではなく「各メンバーが担当パーティションを読めない時間」の総和で観測されることが多い
フェーズ主なRPC/イベント失敗時の挙動
検出ハートビート/サブスクリプション変化検知タイムアウトでメンバー不在を判断し再参加を促す
JoinJoinGroup リクエストとリーダー選出期限超過で再試行、過度に長いと長時間の空白が発生
SyncSyncGroup により最終割り当て確定競合や変更があると再ラウンド(Cooperative では増分適用)

基本シーケンス(簡略)

JoinSyncJoin/Sync 集約SyncConsumer C1Group CoordinatorConsumer C2Consumer Cn

Java コンシューマのリバランスリスナー(要点のみ)

consumer.subscribe(Collections.singletonList("orders"), new ConsumerRebalanceListener() {
  @Override
  public void onPartitionsRevoked(Collection<TopicPartition> partitions) {
    // 処理中メッセージを安全に終了し、最後まで読んだ位置を同期コミット
    consumer.commitSync();
  }
  @Override
  public void onPartitionsAssigned(Collection<TopicPartition> partitions) {
    // 再開時の位置調整。必要に応じて seek を行う
    // consumer.seekToCommitted(partitions);
  }
});

リバランスのイベント発生条件

リバランスは任意の変更で常に発生するわけではありません。主因はメンバーシップ、サブスクリプション、トピック構成の変化です。心拍やポーリングの時間超過は、実務で最も多い誘因です。

コーディネータのフェイルオーバー時はメンバーの再参加が発生し得ますが、必ずしも割り当てが大幅に変わるわけではありません。とはいえ短時間の空白や再同期は覚悟が必要です。

  • 新規メンバーの参加・離脱(プロセス終了、クラッシュ、スケール操作)
  • session.timeout.ms の超過、または heartbeat.interval.ms の異常でのメンバー喪失判定
  • max.poll.interval.ms 超過(アプリが長時間 poll を呼べずに不健康と見なされる)
  • サブスクリプションの変更(subscribe の対象更新)
  • トピックのパーティション数増加
  • グループコーディネータの移動や再起動に伴う再参加
イベント代表的な原因回避/抑制の可否
メンバー離脱Pod/VM 再起動、デプロイ、クラッシュ静的メンバーシップとローリングで抑制可
ハートビート切れGC/CPU 飽和、ネットワーク遅延、session.timeout.ms 設定不一致チューニングと監視で抑制可
max.poll 超過重い処理で poll 間隔が延びる、バッチ肥大化処理分割・backpressure・max.poll 設定で抑制可
パーティション増加スケール要件対応不可避だが Cooperative で影響縮小可

発生条件の概念マップ

New MemberLeave/CrashMembership ChangeHeartbeat TimeoutRebalancePartition Count Change

代表的なコンシューマ設定(発生回避の土台)

# 心拍とメンバー健全性
session.timeout.ms=...        # 過度に短い/長いは不安定化
heartbeat.interval.ms=...     # session.timeout の分数に収める

# アプリ処理健全性
max.poll.interval.ms=...      # 処理が長いなら適切に延長
max.poll.records=...          # 1 回の処理量を制御して超過を防ぐ

Eager と Cooperative の違いと選択指針

Eager 方式(Range/Sticky など)は再均衡開始時に全メンバーがいったん全パーティションを revoke し、割り当て完了まで読むのを止めます。単純で互換性が広い反面、停止時間が伸びがちです。

Cooperative Sticky は増分的に譲り合う方式で、影響のあるパーティションのみを段階的に移譲します。複数ラウンドを経て安定化しますが、多くのケースで総停止時間は短くなります。

  • 短時間停止・ローリングデプロイ優先なら Cooperative Sticky を検討
  • 古いクライアント混在や特定のエコシステム要件がある場合は Eager を選ぶこともある
  • 同一グループ内で複数アサイナー混在は避ける(挙動が不安定になる)
項目Eager 系(Range/Sticky)Cooperative Sticky
停止時間の傾向長い(全 revoke)短い(影響範囲のみ段階的に revoke)
収束ラウンド通常 1複数(増分適用)
重複・取りこぼしリスクリスナー実装が弱いと上がる段階的移譲で抑制しやすい
互換性/要件広範に可対応クライアントで明示設定が安全

Eager と Cooperative の時間挙動(概念)

Eager:
[Revoke all]----[Assign all]----[Resume]
         ^ 全停止

Cooperative:
[Revoke impacted]--[Assign subset]--[Resume some]--[Next round]--[Stable]
         ^ 影響範囲のみ停止

アサイン戦略の設定例

# Cooperative(推奨・対応クライアント)
partition.assignment.strategy=[org.apache.kafka.clients.consumer.CooperativeStickyAssignor]

# Eager(互換優先)
# partition.assignment.strategy=[org.apache.kafka.clients.consumer.StickyAssignor]
# または RangeAssignor を明示

停止時間の見積もりと影響ポイント

コンシューマの有効停止時間は、revoke から resume までの区間と、アプリの処理中断・再初期化コストの和で決まります。Cooperative では対象が一部に限定されるため、合計としての空白が短くなります。

アプリ側のコミット設計が未熟だと、リバランスに伴う重複処理や取りこぼしのリスクが上がります。onPartitionsRevoked での同期コミットと、再割り当て時の初期化を明確にしましょう。

  • 重い処理で max.poll.interval.ms を超過しないようにバッチ分割
  • コミット遅延が長いと再開時の重複が増える(小さくし過ぎるとオーバーヘッド)
  • パーティション増加時はウォームアップ時間(キャッシュ、接続)も停止体感に効く
パラメータ主な作用点誤設定時のリスク
max.poll.interval.msアプリ処理の許容最大時間超過で強制離脱→頻繁なリバランス
session.timeout.msメンバー存続の猶予短すぎると誤検知、長すぎると障害検知が遅い
max.poll.records1 回の処理件数大きすぎると処理延伸、小さすぎるとオーバーヘッド

タイムライン(単一メンバーの視点)

time --->
[poll]--process--process--RebalanceStart--revoke--commit--assign--init--resume--process
                       ^ 停止窓口

処理の一時停止と再開の基本パターン

// revoke 受領で安全停止
consumer.pause(currentPartitions);
consumer.commitSync();
// 必要なクローズ処理...

// assign 受領で再初期化
// for (tp : assigned) { seekToCommitted(tp); }
consumer.resume(assignedPartitions);

停止時間を減らす実践テクニック

停止時間を下げる近道は、発生頻度を減らし、発生時の影響範囲を狭めることです。Cooperative Sticky と静的メンバーシップの併用、適切なハートビート・ポーリング設定、計画的スケールが柱になります。

ローリングデプロイ時は静的メンバーシップでスロットを保持しつつ、1 台ずつ入れ替えると再分散の波及を抑えられます。

  • Cooperative Sticky を明示設定し、全 revoke を避ける
  • group.instance.id を付与して静的メンバー化、ローリング時の再分散を抑制
  • heartbeat.interval.ms と session.timeout.ms の比率を健全に保つ
  • バッチ分割と backpressure で max.poll 超過を予防
  • パーティション増加は閑散時間帯に実施し、段階的に検証
手法期待効果補足/注意
Cooperative Sticky影響範囲のみ段階的移譲で短時間化同一グループで統一、互換性確認
静的メンバーシップローリング時の不必要なリバランス抑制group.instance.id はグループ内で一意
ハートビート調整誤検知減・検知時間の適正化過度の短縮は負荷増、長過ぎは検知遅延
段階的スケール大規模再分散の回避各段階でレイテンシとラグを観測

静的メンバーシップのスロット保持イメージ

holds slot for same instance idrestart / no full rebalance if rejoins quicklyGroup Coordinatormember Aid: svc-1member A'id: svc-1

設定とローリングの基本例

# 静的メンバー + Cooperative
partition.assignment.strategy=[org.apache.kafka.clients.consumer.CooperativeStickyAssignor]
group.instance.id=order-svc-1   # グループ内で一意

# ローリング手順(概念)
# 1) 1 台ずつ停止
# 2) すぐに同一 group.instance.id で起動
# 3) 安定化を確認して次の台へ

監視・トラブルシュートと運用コマンド

リバランスの過多はアプリ停止時間とレイテンシ悪化に直結します。クライアントとブローカのメトリクス、ログ、CLI を組み合わせて早期検知・切り分けを行います。

典型的な兆候は rebalances-total の急増、heartbeat-rate の低下、RebalanceInProgressException の多発です。原因がアプリ処理か、インフラ遅延か、設定かを切り分けます。

  • クライアント JMX: consumer-coordinator-metrics.rebalances-total、heartbeat-rate、commit-latency-avg
  • ログ: Member x in group y has failed, RebalanceInProgressException
  • CLI: kafka-consumer-groups で割り当てとラグを即時確認
指標/ログ意味アクション
rebalances-total の増加リバランス頻発発生源の時間帯・デプロイと突き合わせ
heartbeat-rate 低下心拍遅延/停止GC/CPU/ネットワークを調査、タイムアウト再調整
RebalanceInProgressExceptionリバランス衝突リトライとリスナー処理の健全性確認

グループ状態の遷移(概念)

StablePreparingRebalance再参加成功でループCompletingRebalanceStable

よく使う運用コマンド

# 現在の割り当てとラグ
kafka-consumer-groups --bootstrap-server <bkr:9092> --describe --group <group>

# グループのメンバー一覧
kafka-consumer-groups --bootstrap-server <bkr:9092> --describe --members --group <group>

# オフセットを安全に調整(計画メンテ用)
# 実行前に --dry-run で必ず確認
kafka-consumer-groups --bootstrap-server <bkr:9092> --group <group> --topic <t> --reset-offsets --to-latest --dry-run

問題で確認

CCDAK / CCAAK

問題 1

コンシューマグループの停止時間を最小化しつつローリングデプロイを行いたい。最も効果が高く、公式の挙動に沿った対策はどれか。

  1. Cooperative Sticky を partition.assignment.strategy に設定し、各メンバーに固有の group.instance.id を付与して 1 台ずつ再起動する
  2. max.poll.interval.ms を極端に短くして頻繁にポーリングさせる
  3. session.timeout.ms を非常に長くして障害検知を遅らせる
  4. RangeAssignor を用い、全メンバーを一斉に再起動する

正解: A

Cooperative Sticky は段階的な譲り合いで停止時間を縮小し、静的メンバーシップはローリング時の不要な再分散を抑制する。B は max.poll 超過検知を過敏化し逆効果、C は障害検知が遅れ空白が伸びる、D は一時的な全停止を招きやすい。

よくある質問

コーディネータのフェイルオーバーは必ずリバランスを引き起こしますか?

メンバーの再参加は発生し得ますが、必ずしも大規模な再割り当てとは限りません。短時間の空白や再同期は起こり得るため、クライアントの再試行とリスナー実装を堅牢にしておくことが重要です。

パーティション数を増やすと何が起こりますか?

グループは新しいパーティションを含めて再計算し、リバランスが発生します。Cooperative を使うと影響範囲のみ段階的に移譲され、停止体感を抑えられます。閑散時間帯の実施と監視が推奨です。

session.timeout.ms と max.poll.interval.ms の違いは?

session.timeout.ms は心拍ベースのメンバー存続時間で、ネットワークやプロセス健全性を監視します。max.poll.interval.ms はアプリ処理の健全性で、poll 呼び出し間隔が長過ぎると不健全と見なされ離脱します。両者は独立だが、どちらの超過もリバランス誘因になります。

この記事で学んだ内容を問題で確認しましょう

16,000問以上の問題で実力チェック

無料で問題を解いてみる
この記事の著者

NicheeLab編集部

データエンジニアリング・クラウド資格の専門家。Databricks・Snowflake等の認定資格を保有し、実務経験に基づいた問題作成・解説を行っています。NicheeLab運営。


関連記事
Kafka

Kafka Topic と Partition の基礎: 分散とスケーラビリティの要

CCDAK 対策と実務の両立を意識し、Topic/Partition/Replica/Consumer Group の役...

Kafka

CCDAK 試験ガイド:出題範囲・配点・申込み・対策

Confluent Certified Developer for Apache Kafka (CCDAK) の出題範囲...

Kafka

Confluent Certified Administrator (CCAAK) 対策: 出題範囲・配点の考え方・運用観点の要点

CCAAKに向けて、試験領域の押さえどころを運用目線で整理。プロダクションで通用する設定・監視・セキュリティの実践知を、...

Kafka

Kafka の Replica と In-Sync Replicas を正しく設計する: 耐障害性と一貫性

レプリカとISRの仕組みを起点に、acks と min.insync.replicas、クリーン/アンクリーンリーダー選...

Kafka

Kafka の Offset とコミット: ポジション管理と at-least-once の基礎

CCDAK 対策と実務の両立を意識して、Kafka コンシューマのオフセット管理とコミット戦略を整理。at-least-...

Kafkaの記事一覧 (101件)
© 2026 NicheeLab All rights reserved.