Kafkaパーティションの不均衡問題に対処するためのベストプラクティス
Apache Kafkaの強みは、トピックのパーティショニングによって実現される分散性にあります。パーティションにより、データは複数のブローカーに分散され、並列コンシューマと高いスループットが可能になります。しかし、これらのパーティションが均等に分散されていない場合や、時間の経過とともに不均一な負荷パターンが出現した場合、パーティションの不均衡が発生します。この不均衡は、パフォーマンスを著しく低下させ、負荷の高いパーティションでのコンシューマーラグを増加させ、Kafkaのスケールメリットを損なう重要な運用上の問題です。
本ガイドでは、Kafkaパーティションの不均衡の背後にあるメカニズムを探り、初期設定から継続的な監視、リバランス戦略に至るまで、アクション可能なベストプラクティスを詳述し、分散ストリーミングプラットフォームが最適なスループットと回復力を維持できるようにする方法を説明します。
Kafkaパーティションの不均衡の理解
パーティションの不均衡は、ワークロード(データ量、メッセージレート、またはコンシューマー負荷)がトピック内の利用可能なすべてのパーティションに均等に分散されていない場合、またはパーティション自体がブローカークラスター全体に物理的に均等に分散されていない場合に発生します。
不均衡の原因
いくつかの要因がパーティションの不均衡を引き起こしたり、悪化させたりする可能性があります。
- 初期トピック作成時の設定ミス: 目的の並列処理や利用可能なブローカーに対して不適切な数のパーティションでトピックを作成すること。
- 不均一なキーの分散(偏ったプロデューサー): プロデューサーが、メッセージの不均衡な数を単一のパーティションにマッピングするキーを使用する場合(キーのスキュー)。たとえば、特定の顧客IDや識別子が他のものよりもはるかにアクティブである場合などです。
- コンシューマーグループの動作: コンシューマーグループ内で、コンシューマーが失敗または再起動すると、以前に割り当てられていたパーティションが再割り当てされます。再割り当てが遅い場合やパーティション数が多い場合、1つのコンシューマーが一時的に他のコンシューマーよりも著しく多くのパーティションを処理することがあります。
- ブローカーの障害と回復: ブローカーの停止や再起動中、それらのブローカーでホストされているパーティションを移動または再割り当てする必要があり、クラスターが完全に回復するまで一時的に負荷が偏ります。
システムパフォーマンスへの影響
深刻なパーティションの不均衡の結果は重大です。
- スループットのボトルネック: 負荷の高いパーティションをホストするブローカーがボトルネックとなり、他のブローカーがどれだけアイドル状態であっても、トピック全体の全体的なスループットが制限されます。
- コンシューマーラグの増加: 負荷の高いパーティションに割り当てられたコンシューマーは追いつくのに苦労し、許容できないエンドツーエンドの遅延につながります。
- リソースの飽和: 特定のブローカーでの高いI/O、CPU、またはネットワーク使用率により、不安定性のリスクが増加します。
初期トピック設定のためのベストプラクティス
不均衡に対する最善の防御策は、積極的で情報に基づいた初期設定です。
1. 最適なパーティション数の選択
パーティション数は、おそらく最も重要な決定事項です。これは、コンシューマーの最大並列処理とブローカー間の分散を直接決定します。
- 経験則: 良い出発点は、パーティション数が、並列にトピックを読み取る最大コンシューマーグループ数の倍数であることを確認することです(グループ内のコンシューマー間の均等な分散を保証するため)。
- ブローカーの容量: パーティション数がクラスターを圧倒してはなりません。各パーティションは、割り当てられたブローカーでリソース(メモリとディスク容量)を消費します。I/O容量が制約となる場合は、ブローカーあたりのパーティション数を少なくすることを目指します。
- 将来の成長: 水平方向のスケール(ブローカーの追加)は、高スループットのトピックで稼働中にパーティション数を変更するよりもはるかに簡単です。パーティションの増加はサポートされています(
kafka-topics.sh --alter経由)が、既存のパーティションを自動的に再バランスするわけではありません。
2. プロデューサーのための戦略的なキー選択
キーのスキューを防ぐために、プロデューサーはすべてのパーティションに均一なメッセージ分布を生成するキーを選択する必要があります。
- ホットキーの回避: 多数のメッセージにマッピングされる高カーディナリティで頻繁に使用される識別子をキーとして使用する場合は、それらを特定し回避します。
- 適切な場合のランダム性の利用: データセット全体での厳密な順序が必要とされない場合は、ランダム化されたキーまたはハッシュ化されたキーを使用して、パーティション全体により良い分散を強制します。
# 例: 一貫性のある高カーディナリティIDを使用すると均一な分散が保証される
# 悪い例: すべてを 'SYSTEM_WIDE_CONFIG' でキー設定する
# 良い例: ボリュームで均等に分散されている 'user_id' や 'session_id' でキー設定する
既存トピックのリバランスのためのアクション可能な戦略
不均衡が発生した場合、均衡を取り戻すためには特定管理アクションが必要です。
3. パーティション割り当てリバランスの活用(コンシューマーレベル)
コンシューマーグループがリバランスするとき(コンシューマーの参加/離脱による)、Kafkaはそのコンシューマーグループ内のアクティブなメンバー間でパーティションを均等に分散させようとします。
- 設定の微調整: 不要で破壊的なリバランスを防ぐために、特にセッションタイムアウトとハートビートに関して、コンシューマーが正しく設定されていることを確認します。
- スティッキーパーティション割り当て: 最新のKafkaバージョンでは、デフォルトでスティッキーパーティション割り当てが使用されます。これは、コンシューマーが参加または離脱した際にパーティション割り当てを安定させ、データの移動と負荷の急増を最小限に抑え、移動する必要があるパーティションのみを移動させることを目指します。
4. 物理的バランスのためのブローカー再割り当て
問題が、パーティションがブローカー全体で物理的に不均等に配置されていること(例:ブローカーの追加または削除後)である場合、kafka-reassign-partitions.shツールを使用する必要があります。
このプロセスは、データレプリカセットを現在のブローカーから新しいブローカーに移動させ、物理的なストレージ負荷を効果的に再バランスさせます。
手動再割り当ての手順(概念的な例):
- 現在の計画の生成: トピックの現在のパーティション割り当てを決定します。
- 優先レプリカリストの作成: 目的の、バランスの取れた割り当てを定義します(例:負荷の高いブローカーAから利用されていないブローカーBへパーティションを移動)。
- 移動の実行: 生成されたJSON計画を使用して再割り当てツールを実行します。
- 完了の検証: すべてのレプリカがターゲットブローカーに正常に移動するまで、再割り当てツールを監視します。
警告: パーティションの再割り当ては、I/Oおよびネットワーク集約的な操作です。レプリケーショントラフィックが一時的にクライアントのパフォーマンスに影響を与える可能性があるため、これらの操作はメンテナンスウィンドウ中またはトラフィックの少ない時間帯に実行してください。
5. パーティション数の増加(スケールアウト)
パーティション数が現在の負荷を処理するには真に少なすぎる場合(完璧な分散でも高いコンシューマーラグにつながる)、パーティション数を増やす必要があります。
パーティションを安全に増加させる手順:
- 新しいカウントの決定: 新しい合計パーティション数を決定します(例:12から24へ)。
- トピックの変更:
kafka-topics.shツールを使用してカウントを増やします。新しく作成されたパーティションは、現在のブローカーリストに基づいてブローカーに割り当てられます。
kafka-topics.sh --bootstrap-server localhost:9092 --alter --topic my_topic --partitions 24
-
コンシューマーグループのリバランス: 変更をコンシューマーグループに反映させるために、グループはリバランスをトリガーする必要があります(通常はコンシューマーを再起動するか、タイムアウトを待つことによって)。新しいパーティションが既存のコンシューマーに割り当てられ、負荷がより良く分散されます。
-
ブローカー再割り当て(重要なフォローアップ): パーティション数を増やすことは、新しい負荷を分散するだけです。既存の負荷を新しく利用可能になったブローカーのトポロジに分散させるには、ブローカーの再割り当て計画(ステップ4)に従って、元のパーティションを新しいブローカーのトポロジに移動することが必須です。
監視と防止
サービス低下を引き起こす前に不均衡を検出するには、継続的な監視が不可欠です。
追跡すべき主要メトリクス
Prometheus/Grafanaや組み込みのKafkaツールなどの監視ツールを使用して、これらのメトリクスを追跡します。
- パーティションごとのコンシューマーラグ: 最も直接的な指標です。同じコンシューマーグループ内のパーティション間でラグが大きく異なる場合、不均衡が存在します。
- ブローカーのI/Oおよびネットワーク使用率: 同じトピックをホストするブローカー間で利用率に大きなばらつきがある場合、パーティション負荷が偏っていることを示します。
- ブローカーレベルのパーティション数: 特にブローカーのスケーリング(増減)を行った後、各ブローカーでホストされているパーティション数が時間とともに比較的類似したままであることを確認します。
ベストプラクティス: 定期的なヘルスチェック
特に主要なインフラストラクチャ変更(ブローカーの追加や廃止など)の後には、長期的なスキューを防ぐために、パーティション分散の四半期ごとまたは半期ごとのレビューをスケジュールし、積極的に再割り当てを実行します。