出題とスコープ
マルチテナントAPIに (N) 個のバックエンドエンドポイントがあるとします。すべてのテナントをすべてのエンドポイントに送信するのではなく、各テナントに (k) 個のエンドポイントからなるシャッフルシャードを割り当てます。リクエストはそのシャード内でのみルーティングされるため、過負荷になったエンドポイントの影響は、主にそのシャードと重複しているテナントに限定されます。
割り当ての生成と永続化、ノイズの多いテナント(Noisy Tenant)の処理、アベイラビリティゾーン(AZ)をまたぐエンドポイントの分散、リトライとスケーリング、そして単純なシャーディングよりも爆風半径(影響範囲)が小さいことの証明方法を説明してください。AWSはシャッフルシャーディングをワークロードの隔離およびバルクヘッド(隔壁)技術として提示しています。制御された重複により、少ないリソースで多数の隔離された組み合わせを生成できます。
面接官が評価するポイント
- 隔離目標、テナント規模、エンドポイント数、シャードサイズ、リトライバジェットを定量化しているか。
- 重複確率とステートフルな非重複割り当ての違いを理解しているか。
- すべてのテナントに専用のキャパシティを割り当てるのではなく、隔離とコストのバランスを取れているか。
- ノイズの多いテナント、エンドポイントの障害、ゾーン、安定したスケーリングに対処できているか。
- 実験やメトリクスによって実際の影響境界を証明できているか。
優れたシステムデザインの回答では、シャッフルシャーディングをコンシステントハッシング、セル、バルクヘッドと明確に区別します。制御された重複は残りますが、単一の輻輳ポイントが影響を与えるのは少数のテナント群のみに限定される必要があります。
回答前の確認質問
- テナント数、エンドポイント数、シャードサイズ、テナントごとのピーク負荷はどのくらいですか?
- CPU、コネクションプール、キュー、レートクォータ、またはすべてのリソースのうち、何を隔離しますか?
- 1つのテナントがゾーンやリージョンをまたぐことは可能ですか?また、データレジデンシーのルールはありますか?
- 割り当ては一時的に移行可能ですか?また、キャッシュの激変(Churn)を防ぐために安定したマッピングが必要ですか?
- シャード外へのリトライは許可されますか?それによって障害ドメインが拡大しませんか?
30秒の回答フレームワーク
各テナントを (k) 個のエンドポイントにマッピングし、割り当て時にはゾーンの多様性を必須とします。ステートレスな設計では安定したハッシングで候補を生成します。重複制限が重要な場合は、ステートフルなアロケーターを使用して、既存の大規模テナントと過度に重複する組み合わせを拒絶します。リクエストはシャードの予備キャパシティを使用して、そのシャード内でのみリトライします。スケーリング時は新しい割り当てバージョンを発行し、小さなバッチで移行します。重複、キュー、エラー、影響を受けたテナントを監視し、測定された隔離効果がキャパシティコストを上回る場合にのみこのパターンを採用します。
ステップごとの詳細な回答
ステップ 1: リソースプールと隔離単位を定義する
シャードがコネクションプール、キュー、レートリミッター、キャッシュ、または完全なサービスインスタンスのどれを隔離するのかを決定します。すべてのテナントが1つの共有データベースに書き込んでいる状態で、システムがシャッフルシャード化されていると主張しても意味がありません。共有リソースとエンドポイントのすべてに、キャパシティと障害ドメインのメタデータをラベル付けします。
ステップ 2: シャードサイズを選択する
(N) 個のエンドポイントとテナントあたり (k) 個のエンドポイントがある場合、(k) を増やすとテナントあたりの予備キャパシティは増えますが、重複や共通障害の機会も増加します。(k) を減らすと隔離性は向上しますが、ヘッドルーム(余裕)が減少します。固定の2レプリカという前提ではなく、ピークスループット、エンドポイント障害、リトライ回数を考慮して見積もります。
ステップ 3: ステートレスな候補を生成する
テナントID、リソースプールのバージョン、およびキーを使用して再現性のある擬似乱数列を生成し、(k) 個の異なるエンドポイントを選択します。キーのローテーションやエンドポイントセットの変更は結果を変えるため、ルーティングトークンに割り当てバージョンを含めます。ステートレスな生成はエッジで容易に実行できますが、テナント間の最大重複を保証することはできません。
ステップ 4: 必要に応じてステートフルな検索を使用する
重要度の高いテナントやノイズの多いテナントについては、コントロールプレーンで割り当てを永続化し、各候補と既存の割り当てとの共通部分をチェックします。例えば、ゾーンの多様性を確保しつつ、2つの大規模テナントが共有するエンドポイントを最大 (r) 個に制限します。この検索により、確実な隔離境界が得られる代わりに、割り当てコストと状態管理の負荷が増加します。
ステップ 5: ルーティングとリトライを設計する
ルーターはバージョン管理されたテナント割り当てを読み取り、シャード内の健全なエンドポイントを選択します。リトライはトータルバジェット、バックオフ、冪等性の要件を満たした上でシャード内にとどめます。1つのエンドポイントが失敗したからといって、グローバルプールにリトライをブロードキャストしてはいけません。シャードが飽和している場合は、テナントレベルのシグナルを伴う識別可能なスロットリングまたはデグラデーションの結果を返します。
ステップ 6: ノイズの多いテナントとクォータを処理する
ノイズの多いテナントには独立したクォータ、並行性制限、キューバジェットを付与し、シャード内のすべてのリソースを消費できないようにします。それらのテナントは、デュアルリード、短いハンドオフ、ロールバックを備えた専用または大規模なシャードに移動します。クォータはテナントおよびシャード単位で測定します。グローバルな平均が健全に見えても、ローカルなプールが枯渇している場合があります。
ステップ 7: スケーリング、フェイルオーバー、ゾーン間の配置
エンドポイントを追加すると候補の組み合わせが変わります。新しい割り当てバージョンを発行し、新規テナントに適用し、旧バージョンを保持しながら低リスクなテナントを段階的に移行します。キャッシュ、キュー、コネクションの解放を確認します。エンドポイントのラベルにはゾーンを含める必要があり、ゾーンの停止は、無制限のクロスリージョンリトライではなく、シャード内の残りのエンドポイントによって吸収されるべきです。
ステップ 8: 隔離のメリットとコストを検証する
単一エンドポイントの過負荷、キューの閉塞、ゾーン障害、ノイズの多いテナントのトラフィックを意図的に注入(フォールトインジェクション)します。影響を受けたテナント、重複サイズ、復旧時間、シャード間リトライ、予備キャパシティを記録し、単純なシャーディング、セル、または専用プールと比較します。AWSの事例では、シャッフルシャードに4つのエンドポイントを選択することで影響を劇的に削減できることが示されていますが、正確な結果は (N)、(k)、割り当て方法、トラフィック分布に依存します。
モデル回答
コネクションプール、キュー、レートリミッターを、ゾーンごとにラベル付けされたエンドポイントプールにシャーディングします。各テナントにはバージョン管理された (k) 個のエンドポイントが割り当てられます。通常テナントには安定した擬似乱数候補を使用し、ノイズの多いテナントにはステートフルな検索を使用して重複を制限します。リクエストはシャード内でのみリトライし、ノイズの多いテナントには独立したクォータと可逆的な移行を提供します。スケーリングには新しい割り当てバージョンと段階的なロールアウトを使用します。訓練(障害訓練)ではエンドポイント、ゾーン、ノイズの多いテナントの障害をカバーし、影響を受けたテナント、重複の境界、復旧、シャード間リトライ、キャパシティコストを測定して、単純なシャーディングよりも優れているかを判断します。
よくある間違い
- すべてのリクエストをグローバルプールに送信する → 障害隔離ができない → ルーティングとリトライをシャード内に維持する。
- 重複の分析なしに「ランダム」と言う → 爆風半径の証明にならない → (N)、(k)、共通部分、バージョンを定量化する。
- すべてのテナントに専用のエンドポイントを割り当てる → 高コストと断片化を招く → ノイズの多いテナントのみを専用にし、残りは制限付きで共有する。
- 障害時にグローバルにリトライする → 輻輳が広がる → シャードバジェット、バックオフ、冪等性を使用する。
- スケールアウト時に即座にハッシュを再計算する → キャッシュやキューの激変(Churn)が発生する → 割り当てをバージョン管理し、段階的に移行する。
- グローバルな平均値のみを監視する → ローカルテナントが気付かれずに悪影響を受ける → テナント、シャード、障害ドメインのディメンションを監視する。
フォローアップの質問と回答
シャッフルシャーディングはコンシステントハッシングとどう違いますか?
コンシステントハッシングは通常、キーを1つまたは少数のノードにマッピングし、スケーリング中のデータ移動を最小限に抑えます。シャッフルシャーディングはテナントごとにノードのセットを選択し、共通障害やノイズの多いテナントによる重複影響を制限します。
(k) の大きさはどれくらいにすべきですか?
テナントのスループット、エンドポイント障害、リトライバジェット、キャパシティコストに基づいて選択します。(k) が大きいとヘッドルームが増えますが、重複も増加する可能性があります。固定の数値ではなく、負荷テストや障害注入によって決定する必要があります。
割り当てテーブルが利用できない場合はどうなりますか?
バージョン管理されたローカルキャッシュと、検証可能なステートレスフォールバックを維持します。割り当ての変更を一時停止し、既存のテナントを古いバージョンで維持します。ランダムに再計算してスプリットライト(書き込みの分裂)を引き起こしてはなりません。
ノイズの多いテナントがシャードをまたぐことは可能ですか?
独自のバジェット、トラフィック制限、ロールバックを備えた制限付きのキャパシティ戦略としては可能です。無制限に分散させると、隔離の目標が損なわれます。
ゾーン障害はどのように処理しますか?
割り当てにおいてゾーンの多様性を必須とし、シャード内の健全なエンドポイントにのみルーティングします。クロスリージョンのフェイルオーバーには、無限のリトライではなく、明示的なキャパシティと整合性の設計が必要です。
セルアーキテクチャを代わりに選択するのはどのような場合ですか?
完全なデータプレーン、テナントの境界、リリースを完全に独立させる必要がある場合はセルを選択します。低コストな重複で共有リソースとノイズの多いテナントを隔離するだけで十分な場合は、シャッフルシャーディングを選択します。
使用を中止する判断基準となるメトリクスは何ですか?
障害訓練において依然として多くの無関係なテナントに影響が出る場合、シャード間リトライが頻発する場合、移行によって深刻なChurnが発生する場合、またはキャパシティコストが隔離のメリットを上回る場合は使用を中止します。単純なシャーディングまたは専用プールに戻します。