代表的な面接トピック

バックエンド面接:ローリング再起動に Kafka の Static Membership をどのように活用しますか?

バックエンド難しい
Offer.cc 編集チーム公開日 更新日

質問

Kafka コンシューマーグループがローリングデプロイ中にリバランスを繰り返し、レイテンシスパイクを引き起こしています。静的メンバーシップ(Static Membership)がチャーンをどのように削減するのか、また解決できない問題は何かを説明してください。

質問とそれが適用される場面

コンシューマーグループが代替可能なインスタンス上で実行されています。再起動や一時的なネットワークの寸断によってパーティションの再割り当てがトリガーされ、一時停止やレイテンシスパイクが発生します。単一の設定名を挙げるのではなく、静的メンバーの識別情報、コーディネーターの動作、デプロイの順序、タイムアウト、および障害の境界について説明してください。

面接官が評価するポイント

  • 動的メンバー、静的メンバー、およびパーティションアサイナー(partition assignor)の違いを区別できているか。
  • group.instance.id の一意性、セッションタイムアウト、および重複 ID フェンシングのリスクを説明できているか。
  • コンシューマー設定をローリングデプロイ、グレースフルシャットダウン、およびモニタリングと結び付けられているか。
  • トポロジ、タイムアウト、または実際の障害によって、静的メンバーシップでもリバランスが発生するケースを明示できているか。

回答前の明確化のための質問

  1. 各インスタンスには安定した一意の識別情報がありますか、それともランダムに置き換えられますか?
  2. 再起動にはどのくらいの時間がかかりますか?また、session.timeout.ms やブローカーの制限値はどのようになっていますか?
  3. グループは eager アサイナーまたは cooperative アサイナーのどちらを使用していますか?その移行も同時に行う必要がありますか?
  4. 許容される最大停止時間およびラグ回復時間はどのくらいですか?
  5. デプロイメントにおいて、古いインスタンスの ID を再利用する前にそのインスタンスが確実に終了することをどのように保証していますか?

30秒の回答フレームワーク

すべてのコンシューマーに安定した一意の group.instance.id を割り当てます。これにより、セッションタイムアウト内の短時間の再起動であれば、新しいランダムなメンバー ID に対する完全な再割り当てをトリガーすることなくメンバーシップを維持できます。デプロイでは一度に1つのスロットを置き換え、ID を同時に再利用することは決してありません。静的メンバーシップはアサイナーの移行を代替するものではなく、長期の障害を隠蔽するものでもないため、リバランス回数、パーティション利用不能時間、コンシューマーレイテンシ、および重複 ID エラーを検証します。

ステップバイステップの詳細解説

ステップ 1: メンバー識別モデルを確認する

動的メンバーは通常、生成されたメンバー ID で参加しますが、これはプロセスが離脱すると変更されます。静的メンバーは group.instance.id によって識別され、これはグループ内で一意であり、再起動後も永続する必要があります。起動ごとに生成されるランダムな UUID ではなく、StatefulSet の序数(ordinal)、マシンスロット、または制御されたリースから導出します。

ステップ 2: セッションタイムアウトの境界を理解する

ハートビートが停止した後、コーディネーターは静的メンバーをすぐに完全に離脱したとはみなしません。セッションタイムアウト後にそのメンバーを障害と宣言します。タイムアウトが短すぎると通常のデプロイでリバランスが発生し、長すぎると実際の障害発生後の引き継ぎが遅れます。起動時間、ネットワークジッター、およびブローカーの制限内でのビジネス上の一時停止許容時間から設定します。

ステップ 3: 重複 ID を防止する

1つのグループ内の2つのアクティブなインスタンスが同じ group.instance.id を共有することはできません。オーケストレーションは、代替インスタンスを開始する前に古い識別情報を解放する必要があります。両方が実行されている場合、コーディネーターは一方のメンバーを拒否またはフェンシングする可能性があります。重複 ID エラーは、リトライで隠蔽するのではなく、デプロイをブロックするシグナルとして扱います。

ステップ 4: アサイナーとグレースフルシャットダウンを協調させる

静的メンバーシップは識別情報の変動(チャーン)を削減し、アサイナーはパーティションの移動を決定します。アサイナーのアップグレードや cooperative モードの有効化には、個別の互換性チェックが必要です。通常のシャットダウンでは、ポーリングを停止し、安全なオフセットをコミットし、グループを離脱して接続を閉じます。異常停止の場合は、セッションタイムアウトによる引き継ぎに依存します。

ステップ 5: ローリングデプロイを設計する

一度に1つのインスタンスを置き換え、新しいメンバーの参加、パーティションの安定化、およびレイテンシの回復を待ちます。デプロイ前にインスタンスとパーティションのマッピングを記録し、コーディネーターログとコンシューマーラグを観察し、障害発生時には古いバージョンを維持したままバッチを一時停止します。静的メンバーシップは、無制限の並行再起動を許可するものではありません。

ステップ 6: それでもリバランスが発生するケースを特定する

メンバーの追加、セッションタイムアウトの超過、パーティション数やトピック購読の変更、アサイナーの変更、およびコーディネーターの移動はすべて再割り当てをトリガーする可能性があります。静的メンバーシップは一時的な離脱と復帰によるチャーンを削減しますが、トポロジやキャパシティの変更によって引き起こされる調停(coordination)を排除するものではありません。

ステップ 7: メトリクスで利点とリスクを検証する

デプロイごとに、リバランス回数、パーティション利用不能時間、p99 コンシューマーレイテンシ、最大ラグ、重複 ID エラー、セッションタイムアウト、および回復時間を記録します。短時間の再起動、遅延起動、ネットワーク分断、ID 衝突、ブローカー変更などの障害注入を行います。自動一時停止およびロールバックのしきい値を設定します。

質の高い模範解答

デプロイメントの序数または制御されたリースから生成された、安定した一意の group.instance.id を各コンシューマースロットに割り当てます。ローリングデプロイでは一度に1つのスロットを置き換えます。古いメンバーがポーリングを停止してグレースフルに終了し、その後新しいプロセスが同じ ID で参加します。再起動がセッションタイムアウト内に収まる場合、グループはランダムなメンバー ID の変更によって引き起こされるチャーンを回避します。session.timeout.ms は単に増やすのではなく、最大標準起動時間、ネットワークジッター、および許容される一時停止時間から導出します。オーケストレーションは ID の同時再利用をブロックし、重複 ID またはフェンシングエラーが発生した場合はロールアウトを停止します。静的メンバーシップであっても、パーティションの拡張、購読の変更、または実際のタイムアウトには対処できないため、障害注入ロールバックテストとともに、リバランス、p99 レイテンシ、ラグ、利用不能時間、および回復を監視します。

よくある間違い

  • 起動ごとに新しいランダムな group.instance.id を生成すること。
  • 障害引き継ぎ時間を見積もらずにセッションタイムアウトを増やすこと。
  • 同じインスタンス ID で2つのプロセスを同時に起動すること。
  • 静的メンバーシップがすべてのリバランスを排除すると仮定し、トピック、パーティション、または購読の変更を無視すること。
  • アサイナーの互換性とグレースフルシャットダウンを検証せずに設定を変更すること。
  • 平均ラグのみに注目し、デプロイ中の利用不能時間や p99 レイテンシを見落とすこと。

フォローアップの質問と回答

フォローアップ 1: クラッシュしたインスタンスのパーティションはどのくらいで引き継がれますか?

通常、コーディネーターがセッションがタイムアウトしたと判断した後です。ハートビート、ネットワーク状態、およびコーディネーターのステータスも関係します。デフォルト値をそのまま引用するのではなく、目標復旧時間から逆算し、障害注入を用いて測定してください。

フォローアップ 2: 静的メンバーシップと cooperative sticky assignor は同じものですか?

いいえ。静的メンバーシップはメンバーの識別情報を安定させ、短時間の離脱によるチャーンを削減します。cooperative アサイナーはパーティションの移動方法を制御し、移行に伴う停止を削減します。これらは組み合わせることができますが、個別に検証する必要があります。

フォローアップ 3: なぜ重複 ID でデプロイをブロックするのですか?

1つの識別情報をめぐって2つのプロセスが競合すると、フェンシング、パーティションのチャーン、および予測不能な所有権が発生する可能性があります。リトライによって衝突が増幅する可能性があるため、デプロイメントではまず識別情報の割り当てを修正する必要があります。

フォローアップ 4: セッションタイムアウトを数時間に設定することはできますか?

障害発生後にパーティションがそれほど長く待機することをビジネスが許容し、ブローカーの制限がそれを許可する場合に限られます。ほとんどのシステムでは、遅い起動を極端なタイムアウトで隠蔽するのではなく、デプロイの一時停止と障害復旧を分けてモデル化します。

フォローアップ 5: コンシューマーをスケーリングしてもリバランスは発生しますか?

はい。新しいメンバーが追加されるとパーティションの所有権が変更されます。静的識別情報であってもトポロジの変更を防ぐことはできません。トラフィックが少ない時間帯にスケーリングし、移行とラグを観察し、アサイナー戦略とバージョンの互換性を維持してください。

フォローアップ 6: 失敗したデプロイをどのようにロールバックしますか?

それ以上の置き換えを一時停止し、変更されていないインスタンスを維持し、古いバージョンが元の ID で再参加してコンシュームを再開できることを確認します。インシデント対応を継続するか拡大するかを決定する前に、重複 ID、コミットされたオフセット、ラグ、およびコーディネーターログを確認します。

公開情報ソース

関連する質問