Kafkaパーティションの最適化によるスケーラビリティとスループットの向上

パーティション最適化をマスターして、Kafkaトピックのピークパフォーマンスを引き出しましょう。このガイドでは、理想的なパーティション数の決定、プロデューサー/コンシューマーのスループットのバランス、スケーラビリティの確保、よくある落とし穴の回避に必要な戦略を網羅しています。高スループットで低レイテンシのイベントストリーミングを実現するための効果的なパーティション設定方法を学びます。

Kafkaパーティションの最適化によるスケーラビリティとスループットの向上

Kafkaのパーティション数は、実際に運用してみるまでは単純に見える設定のひとつです。パーティションが少なすぎるとコンシューマーをスケールアウトできません。多すぎるとブローカーがメタデータ管理に時間を費やし、リバランスに時間がかかり、運用上のノイズが増加します。

普遍的な最適な数は存在しません。決済トピック、クリックストリームトピック、コンパクト化された顧客状態トピックでは、順序要件、メッセージサイズ、リテンション設定、コンシューマーの動作が異なります。有用な質問は「最適なパーティション数はいくつか?」ではなく、「このトピックのスループット、順序性、成長のために、不必要なブローカーオーバーヘッドを発生させずに必要なパーティション数はいくつか?」です。

Kafkaパーティションの理解

Kafkaトピックは、基本的に1つ以上のパーティションに分割されます。各パーティションは、追記専用の順序付けられたログです。パーティションはKafkaにおける並列処理の単位です:

  • プロデューサーはパーティションに書き込む: プロデューサーはパーティションを直接選択するか、キーを使用するか、パーティショナーにレコードの分散を任せることができます。
  • コンシューマーはパーティションから読み取る: コンシューマーグループ内の各コンシューマーには、排他的に読み取る1つ以上のパーティションが割り当てられます。これにより、パーティション内のメッセージは、そのグループ内の単一のコンシューマーインスタンスによって順序通りに処理されることが保証されます。
  • ブローカーはパーティションをホストする: Kafkaブローカーはリーダーとレプリカを保存します。複数のパーティションを持つトピックは、ストレージとトラフィックをブローカー間で分散できます。

パーティションの主な特性:

  • パーティション内での順序性: 単一のパーティション内のメッセージは常に順序付けられます。グループ内のコンシューマーはこの順序を維持します。
  • パーティション間での非順序性: 同じトピックの異なるパーティション間でのメッセージの順序は保証されません。
  • 並列処理: 1つのコンシューマーグループにおいて、トピックに対してアクティブなコンシューマーの有効な数は、パーティション数を超えることはできません。余分なコンシューマーはそのトピックに対してアイドル状態になります。

パーティション数に影響を与える要因

Kafkaトピックのパーティション数を決定する際には、いくつかの重要な要因を評価する必要があります:

1. スループット要件(プロデューサーとコンシューマー)

  • プロデューサースループット: パーティションを増やすと書き込みをブローカー間で分散できますが、それはリーダーがバランスよく配置され、プロデューサーがレコードを適切に分散している場合に限ります。ホットキーが1つあるキー付きトピックでは、1つのパーティションに負荷が集中する可能性があります。
  • コンシューマースループット: 1つのコンシューマーが毎秒2,000メッセージを処理でき、トピックのピークが毎秒20,000メッセージの場合、グループ内で十分な数のコンシューマーを実行するために十分なパーティションが必要です。正確な数は、推測ではなく、実際に測定したコンシューマーの速度に依存します。

2. スケーラビリティ目標

  • 将来の成長: Kafkaではパーティションを増やすことはできますが、パーティション数を減らすことは通常のインプレース操作ではありません。通常は新しいトピックを作成して移行します。
  • リバランス: パーティションを追加すると、コンシューマーグループのリバランスが発生する可能性があります。ビジーなコンシューマーがいる場合、処理が一時的に遅くなったり、停止したりする可能性があります。
  • キーの動作: パーティションを増やすと、デフォルトのパーティショニング動作を使用する多くのプロデューサーにとって、キーとパーティションのマッピングが変更されます。これは、キーが常に同じパーティションに留まると想定していたシステムに影響を与える可能性があります。

3. ブローカーリソース

  • ディスク: パーティションが増えると、特にレプリケーションがある場合、ログセグメントと管理するファイルが増加します。
  • ネットワーク: レプリケーションとコンシューマーフェッチによりトラフィックが増加します。問題はトピック数だけでなく、レプリカ、リテンション、メッセージサイズ、コンシューマーのファンアウトにも関係します。
  • CPUとメモリ: ブローカー、コントローラー、クライアントはすべて、パーティション数が多い場合にオーバーヘッドが発生します。最新のKafkaバージョンは以前のバージョンよりも大規模なクラスターを処理できますが、パーティション数は依然としてキャパシティプランニングの作業です。

4. メッセージ順序要件

  • キーベースの順序: 順序が重要でメッセージキーを使用する場合、同じキーを持つレコードは通常同じパーティションに送られます。これにより、トピック全体ではなく、キーごとの順序が保証されます。ホットキーは依然として1つのパーティションに集中し、1つのコンシューマーのボトルネックになる可能性があります。
  • 厳密な順序が不要な場合: 厳密なメッセージ順序が要件でない場合は、スループットと並列処理を優先して、パーティション間でより自由にメッセージを分散できます。

5. コンシューマーグループのスケーラビリティ

前述の通り、パーティション数によって、コンシューマーグループ内でトピックから同時に読み取ることができるコンシューマーの最大数が決まります。コンシューマーインスタンスを追加して消費をスケールアウトする必要がある場合は、少なくとも目的のコンシューマーインスタンス数と同じ数のパーティションが必要です。

パーティション数を選択する実践的な方法

最適なパーティション数に到達するための実践的な戦略をいくつか紹介します:

1. ベースラインから始めて監視する

有用なベースラインは、コンシューマーの並列処理から始まります。このトピックに4つのコンシューマーインスタンスを想定している場合、4つ以上のパーティションから始めると、リバランスと成長の余地が生まれます。

例:4つのコンシューマーを実行する予定の場合、8つのパーティションから始めるかもしれません。これにより、各コンシューマーが2つのパーティションを所有でき、再パーティション化する前にさらに数台のコンシューマーを追加できます。これは出発点であり、絶対的なルールではありません。

Kafkaクラスターとコンシューマーラグを継続的に監視します。コンシューマーインスタンスを追加しても解決できない(パーティション制限に達したため)高いコンシューマーラグが観測された場合、それはパーティション数を増やす必要がある明確な指標です。

2. 期待スループットに基づいて計算する

測定されたスループットから必要なパーティションを推定できます:

  • 計算式: パーティション数 = (総期待スループット / コンシューマーインスタンスあたりのスループット) * バッファ

    • 総期待スループット: 日次平均ではなく、ピーク生産レートを使用します。
    • コンシューマーインスタンスあたりのスループット: 実際のメッセージサイズとダウンストリーム呼び出しを使用して、実際のコンシューマーを測定します。
    • バッファ: スパイクと成長に備えて余裕を持たせます。計算が正確であると見なさないでください。

例:

  • ピーク期待スループット:毎秒50,000メッセージ
  • 単一コンシューマーインスタンスのスループット:毎秒5,000メッセージ
  • バッファ:1.5倍
  • (50,000 / 5,000) * 1.5 = 15

この場合、16パーティションは妥当な丸い出発点です。順序、ブローカー容量、キー分散がこの数値に反する場合は、調整します。

3. ブローカーの能力と制限を考慮する

クラスター全体の総パーティション数に注意してください。どこにでも適用できる安全なブローカーあたりのパーティション数はありません。ハードウェア、Kafkaバージョン、レプリケーションファクター、リテンション、メッセージサイズ、コントローラーの負荷、障害復旧目標など、すべてが重要です。

「ブローカーあたり100パーティション」や「ブローカーあたり1,000パーティション」を普遍的な真実として扱う代わりに、ブローカーメトリクス(リクエストレイテンシ、ディスクI/O、コントローラーの健全性、アンダーレプリケーションパーティション、ページキャッシュのプレッシャー、リバランス時間)を追跡します。組織にテスト済みの制限がある場合は、それを使用します。

4. キー分散とホットパーティション

メッセージキーを使用する場合は、「パーティションを増やす」ことでスループットが改善されると判断する前に、キー分散を分析します。少数の支配的なキーがホットパーティションを作成する可能性があります。リーダーをホストするブローカーの負荷が高くなり、そのパーティションに割り当てられたコンシューマーが遅れます。

  • 解決策: ホットパーティションが予想される場合は、次のような戦略を検討します:
    • ビジネス上の順序が許せば、偏りの少ないキーを使用します。
    • 必要な順序が維持される場合は、customer_id:event_type のような複合キーを使用します。
    • 1つのホットワークフローを別のトピックに分割します。
    • ホットキーを意図的にシャーディングし、より狭いスコープで順序を処理します。

パーティションを増やすことは、広範な分散に役立ちます。そのキーのすべてのレコードが順序を維持する必要がある場合、1つのキーを複数のコンシューマーに分割することはできません。

パーティションを使用したトピックの作成と変更

新しいトピックを作成する際には、パーティション数を指定します。

特定のパーティション数でトピックを作成する

kafka-topics.sh スクリプトを使用:

kafka-topics.sh --create --topic my-high-throughput-topic \
  --bootstrap-server kafka-broker-1:9092,kafka-broker-2:9092 \
  --partitions 16 \
  --replication-factor 3
  • --partitions 16:トピックに16個のパーティションを設定します。
  • --replication-factor 3:各パーティションは、フォールトトレランスのために異なるブローカーに3つのレプリカを持ちます。

既存のトピックのパーティションを増やす

これは一般的な操作ですが、影響があります。Kafkaではトピックのパーティション数を増やすことができます。減らすには、別のトピックへの移行が必要です。

kafka-topics.sh スクリプトを使用:

kafka-topics.sh --alter --topic my-high-throughput-topic \
  --bootstrap-server kafka-broker-1:9092 \
  --partitions 24
  • --partitions 24my-high-throughput-topic のパーティションを24に増やします。

パーティション変更時の重要な考慮事項:

  • コンシューマーリバランス: パーティションを増やすと、サブスクライブしているコンシューマーグループのリバランスがトリガーされる可能性があります。これにより、消費が一時的に停止または遅くなる可能性があります。
  • 新しいパーティション: 新しいパーティションはトピックに追加されます。既存のメッセージは再パーティション化されません。
  • キーマッピング: キー付きプロデューサーの場合、パーティションを追加すると、キーに対する将来のレコードの書き込み先が変更される可能性があります。
  • ブローカーリソース: ブローカーに追加のリーダーとレプリカを処理する容量があることを確認します。

履歴全体にわたるキーの順序が重要な場合は注意してください。既存のレコードは古いパーティションに残りますが、新しいレコードはパーティション数変更後に異なるマッピングになる可能性があります。

パーティション数が間違っていることを示すメトリクス

コンシューマーラグは明らかなシグナルですが、それだけでは十分ではありません。ラグは、ダウンストリームデータベースの遅延、コンシューマーコードの不良、フェッチ設定の小ささ、ブローカーの過負荷、またはパーティション数の不足が原因である可能性があります。

次のパターンに注意してください:

  • コンシューマーは正常だが、パーティション数がコンシューマー数より少ないため、一部のインスタンスがアイドル状態になっている。
  • 1つのパーティションのラグが他のパーティションよりもはるかに高い。
  • 1つのブローカーが多くのホットパーティションリーダーを抱えている。
  • クラスターに余裕のあるブローカーがあるにもかかわらず、ピークトラフィック時にプロデューサーのレイテンシが上昇する。
  • リバランスに時間がかかり、サービスレベル目標に影響を与えている。

コンシューマーグループの場合:

kafka-consumer-groups.sh --bootstrap-server kafka-broker-1:9092 \
  --describe --group my-consumer-group

トピックレイアウトの場合:

kafka-topics.sh --bootstrap-server kafka-broker-1:9092 \
  --describe --topic my-high-throughput-topic

1つのパーティションだけが遅れている場合、作業をより多くのパーティションに分散できない限り、コンシューマーを追加しても役に立ちません。

ベストプラクティスと落とし穴

推奨事項:

  • 測定されたニーズから始める: 予想されるコンシューマー数、スループットテスト、ブローカー容量を使用します。
  • コンシューマーの並列処理に合わせる: コンシューマーインスタンスを効果的にスケールアウトするために十分なパーティションがあることを確認します。
  • 成長の余地を残す: 後でパーティションを追加することは可能ですが、影響がないわけではありません。
  • キー分散を理解する: キーを使用する場合は、ホットパーティションを避けるためにその分散を分析します。
  • Kafka監視ツールを活用する: ツールを使用して、トピック/パーティションメトリクス、コンシューマーラグ、ブローカーの負荷を追跡します。

避けるべきこと:

  • 過剰なパーティション化: パーティションが多すぎるとオーバーヘッドが増加し、リバランスが遅くなり、障害復旧がより不安定になる可能性があります。
  • パーティション不足: スケーラビリティとスループットが制限され、コンシューマーラグが発生します。
  • 任意の数値を盲目的に従う: 経験則は出発点としてのみ使用します。
  • ブローカー容量を忘れる: ブローカーがすべてのトピックにわたる総パーティション数を処理できることを確認します。
  • パーティション間での完全な順序を期待する: 順序はパーティション内でのみ保証されることを忘れないでください。

合理的な意思決定プロセス

新しいトピックの場合、通常は次の順序で進めます:

  1. 順序要件を定義します。顧客ごと?アカウントごと?厳密な順序は不要?
  2. ピーク時のプロデューサースループットとメッセージサイズを測定または推定します。
  3. 現実的なダウンストリーム依存関係を持つ1つのコンシューマーインスタンスをベンチマークします。
  4. 必要なコンシューマーの並列処理と成長の余地に基づいてパーティションを選択します。
  5. レプリケーションファクターを含めた後のクラスター全体への影響を確認します。
  6. 起動後、パーティションごとのラグとブローカーの負荷を監視します。

パーティション数は美しさを競うものではありません。8つの十分に活用されたパーティションを持つ退屈なトピックは、96のほとんどアイドル状態のパーティションを持ち、リバランスを毎回遅くするトピックよりも優れています。実際に必要な並列処理と成長の余地を提供する最小の数を選択してください。