Kafkaパーティション不均衡問題を解決するためのベストプラクティス

Kafkaのパーティション不均衡を診断し、スキューしたキーを修正し、レプリカを再分散し、ラグとブローカーの負荷を監視します。

Kafkaパーティション不均衡問題を解決するためのベストプラクティス

Apache Kafkaの強みは、トピックのパーティション分割によって実現される分散アーキテクチャにあります。パーティションにより、データを複数のブローカーに分散し、並列処理と高スループットを可能にします。しかし、これらのパーティションが均等に分散されていない場合や、時間の経過とともに不均一な負荷パターンが発生すると、パーティション不均衡が生じます。この不均衡は、パフォーマンスを著しく低下させ、過負荷のパーティションでコンシューマーラグを増加させ、Kafkaのスケーリングの利点を損なう可能性がある重大な運用上の問題です。

このガイドでは、区別すべき2種類の不均衡について説明します。ブローカー間での不均一なパーティション配置と、パーティション間での不均一なトラフィックです。修正方法は異なるため、診断が重要です。

Kafkaパーティション不均衡の理解

パーティション不均衡は、ワークロード(データ量、メッセージレート、コンシューマー負荷)がトピック内のすべての利用可能なパーティションに均等に分散されていない場合、またはパーティション自体がブローカークラスター全体に物理的に均等に分散されていない場合に発生します。

不均衡の原因

いくつかの要因がパーティション不均衡を引き起こしたり、悪化させたりする可能性があります。

  1. 初期トピック作成の設定ミス: 必要な並列処理や利用可能なブローカーに対して不適切な数のパーティションでトピックを作成すること。
  2. 不均一なキー分散(スキューしたプロデューサー): プロデューサーが、メッセージの不均衡な割合を単一のパーティションにマッピングするキーを使用する場合(キースキュー)。例えば、特定の顧客IDや識別子が他のものよりもはるかにアクティブな場合などです。
  3. コンシューマーグループの動作: コンシューマーグループ内で、1つのコンシューマーが障害を起こしたり再起動したりすると、以前に割り当てられていたパーティションが再分散されます。再割り当てが遅い場合やパーティション数が多い場合、1つのコンシューマーが一時的に他のコンシューマーよりもはるかに多くのパーティションを処理する可能性があります。
  4. ブローカーの障害と復旧: ブローカーの停止や再起動中に、それらのブローカーでホストされていたパーティションを移動または再割り当てする必要があり、クラスターが完全に復旧するまで一時的に負荷が偏ります。

システムパフォーマンスへの影響

深刻なパーティション不均衡の結果は重大です。

  • スループットのボトルネック: 負荷の高いパーティションをホストするブローカーがボトルネックとなり、他のブローカーがどれだけアイドル状態であっても、トピック全体のスループットが制限されます。
  • コンシューマーラグの増加: 過負荷のパーティションに割り当てられたコンシューマーは追いつくのに苦労し、許容できないエンドツーエンドのレイテンシーが発生します。
  • リソースの飽和: 特定のブローカーでの高いI/O、CPU、またはネットワーク使用率により、不安定性のリスクが高まります。

初期トピック設定のベストプラクティス

不均衡に対する最善の防御は、事前の情報に基づいた初期設定です。

1. 最適なパーティション数の選択

パーティション数は、おそらく最も重要な決定事項です。これは、コンシューマーの最大並列性とブローカー間の分散に直接影響します。

  • 経験則: 1つのコンシューマーグループで予想される最大コンシューマー数以上のパーティション数を選択します。一般的なコンシューマー数の倍数は、割り当てを均等に保つのに役立ちますが、各コンシューマーグループは独立してバランスが取られます。
  • ブローカー容量: パーティション数はクラスターを圧迫しないようにする必要があります。各パーティションは、割り当てられたブローカー上でリソース(メモリとディスク容量)を消費します。I/O容量が制約となる場合は、ブローカーあたりのパーティション数を少なくすることを目指します。
  • 将来の成長: 水平方向にスケールアウト(ブローカー追加)する方が、高スループットのトピックに対して途中でパーティション数を変更するよりもはるかに簡単です。パーティションの増加はサポートされていますが(kafka-topics.sh --alter経由)、既存のパーティションを自動的に再分散するわけではありません。

2. プロデューサー向け戦略的なキー選択

キースキューを防ぐために、プロデューサーはすべてのパーティションにわたってメッセージの均一な分散を生成するキーを選択する必要があります。

  • ホットキーを避ける: 不均衡な割合のメッセージを生成するキーを特定します。user_idのようなカーディナリティの高いキーは通常うまく分散しますが、1つの非常にアクティブなユーザーやテナントがホットパーティションを作成する可能性があります。
  • 適切な場合にランダム性を使用する: データセット全体で厳密な順序付けが必要ない場合は、ランダム化されたキーまたはハッシュ化されたキーを使用して、パーティション全体での分散を強制します。
# 例: 一貫性のある高カーディナリティのIDを使用すると、均等な分散が保証されます
# 悪い例: すべてを'SYSTEM_WIDE_CONFIG'でキー付けする
# 良い例: ボリュームが均等に分散されている場合、'user_id'または'session_id'でキー付けする

既存トピックの再分散のための実践的な戦略

不均衡が発生した場合、均衡を回復するために特定の管理アクションが必要です。

3. パーティション割り当ての再分散の活用(コンシューマーレベル)

コンシューマーグループが再分散する場合(コンシューマーの参加/離脱による)、Kafkaはそのコンシューマーグループ内のアクティブメンバー間でパーティションを均等に分散しようとします。

  • 設定の調整: コンシューマーが正しく設定されていることを確認します。特にセッションタイムアウトとハートビートに関して、不要で破壊的な再分散を防ぎます。
  • スティッキーパーティション割り当て: クライアントバージョンがサポートしている場合は、スティッキーまたは協調スティッキーアサイナーを検討します。これらのアサイナーは、コンシューマーが参加または離脱する際にパーティションの所有権を安定させようとし、不要な移動を減らします。

4. 物理的なバランシングのためのブローカー再割り当て

問題がパーティションがブローカー間で物理的に不均等に配置されている場合(例:ブローカーの追加または削除後)、kafka-reassign-partitions.shツールを使用する必要があります。

このプロセスは、データレプリカセットを現在のブローカーから新しいブローカーに移動し、物理ストレージの負荷を効果的に再分散します。

手動再割り当ての手順(概念的な例):

  1. 現在の計画を生成する: トピックの現在のパーティション割り当てを決定します。
  2. 優先レプリカリストを作成する: 望ましいバランスの取れた割り当てを定義します(例:過負荷のブローカーAから未使用のブローカーBへパーティションを移動)。
  3. 移動を実行する: 生成されたJSON計画で再割り当てツールを実行します。
  4. 完了を確認する: すべてのレプリカがターゲットブローカーに正常に移動されるまで、再割り当てツールを監視します。

警告: パーティションの再割り当ては、I/Oとネットワークを大量に消費する操作です。これらのアクションはメンテナンスウィンドウまたは低トラフィック期間中に実行してください。レプリケーショントラフィックは一時的にクライアントのパフォーマンスに影響を与える可能性があります。

5. パーティション数の増加(スケールアウト)

現在の負荷を処理するためにパーティション数が実際に少なすぎる場合(完全な分散でも高いコンシューマーラグが発生する場合)、パーティション数を増やす必要があります。

安全にパーティションを増やす手順:

  1. 新しい数を決定する: 新しい総パーティション数を決定します(例:12から24へ)。
  2. トピックを変更する: kafka-topics.shツールを使用して数を増やします。新しく作成されたパーティションは、現在のブローカーリストに基づいてブローカーに割り当てられます。
kafka-topics.sh --bootstrap-server localhost:9092 --alter --topic my_topic --partitions 24
  1. コンシューマーグループを再分散する: 変更をコンシューマーグループに反映させるには、グループが再分散をトリガーする必要があります(通常はコンシューマーを再起動するか、タイムアウトを待つことによって)。新しいパーティションは既存のコンシューマーに割り当てられ、負荷がより適切に分散されます。

  2. ブローカー再割り当て(重要なフォローアップ): パーティションを増やすだけでは、新しい負荷が分散されるだけです。新しく利用可能になったブローカースロット全体に既存の負荷を分散するには、元のパーティションを新しいブローカートポロジに移動するために、ブローカー再割り当て計画(手順4)を必ずフォローアップする必要があります。

監視と予防

サービス低下を引き起こす前に不均衡を捉えるために、継続的な監視が不可欠です。

追跡すべき主要メトリクス

監視ツール(Prometheus/Grafana、または組み込みのKafkaツールなど)を使用して、以下のメトリクスを追跡します。

  • パーティションごとのコンシューマーラグ: 最も直接的な指標です。同じコンシューマーグループ内のパーティション間でラグが大きく異なる場合、不均衡が存在します。
  • ブローカーのI/Oとネットワーク使用率: 同じトピックをホストするブローカー間での使用率の高いばらつきは、パーティション負荷の偏りを示しています。
  • ブローカーレベルのパーティション数: 特にブローカーのスケールアップまたはスケールダウン後、各ブローカーでホストされるパーティション数が時間の経過とともに比較的均一に保たれていることを確認します。

ベストプラクティス: 定期的なヘルスチェック

ブローカーの追加、ブローカーの退役、またはプロデューサーキーの変更後は、パーティションの分散を確認します。1つのテナント、デバイス、または顧客がトピックを支配し始めた場合は、過負荷のパーティションがスループットの上限になる前に、キー戦略を修正するか、そのワークロードを分割します。