代表的な面接トピック

システムデザイン面接:パーソナライズされたニュースフィードをどのように設計しますか?

システム設計難しい
Offer.cc 編集チーム公開日 更新日

質問

フォローグラフを基盤とするパーソナライズされたニュースフィードを設計してください。システムは5,000万DAUを抱え、1日あたり1,000万件の新規投稿を受け取ります。ユーザーはテキストや画像の投稿、著者のフォロー、関連度順にランク付けされたホームフィードの閲覧が可能です。API、データモデル、候補生成、fan-out-on-writeとfan-out-on-readの比較、ランキング、ページネーション、一貫性、削除、ホットスポット、復旧、検証について説明してください。

プロンプトと適用コンテキスト

フォローグラフに基づくパーソナライズされたニュースフィードを設計してください。ユーザーはテキストや画像の投稿、著者のフォローやアンフォロー、関連度順にランク付けされたホームフィードの閲覧が可能です。投稿の削除、非公開化、著者のブロック、アンフォローは、その後の読み取りに速やかに反映される必要があります。いいね、コメント、推薦モデルはランキングシグナルとなります。メディアのトランスコーディング、コメントツリー、広告オークション、モデルのトレーニングはスコープ外です。

DAU(1日あたりのアクティブユーザー数)は5,000万と仮定します。各アクティブユーザーは1日に20ページを閲覧し(1ページあたり20件)、システムは1日に1,000万件の新規投稿を受け取ります。フィード読み取りのp99は200ミリ秒未満である必要があります。通常著者の投稿は、p99で5秒以内にアクティブなフォロワーに表示される必要があります。通常著者の対象フォロワー数は平均200人ですが、最大の著者は5,000万人のフォロワーを持ちます。これらの数値および期限は面接上の制約であり、既存の製品に関する主張ではありません。

このプロンプトは、中級からシニアレベルのバックエンド、インフラ、システムデザインの面接に適しています。公開されている面接資料では、書き込みファンアウト、読み取りファンアウト、セレブリティ著者、カーソルページネーション、キャッシング、一貫性について直接問われます。また、一次情報のエンジニアリング事例でも、適切なグレースフルデグラデーションのために実体化されたコンテンツを保持しつつ、候補取得、集約、フィルタリング、マルチパスランキングを分離しています。したがって、優れた回答とは、単一の固定された図を再現するのではなく、明示的なコストと正確性の要件からメカニズムを組み合わせることです。

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

第一に、候補者は読み取りと書き込みの非対称性を定量化できるか?5,000万DAUに20ページを掛けると1日あたり10億回の読み取り、つまり平均で約11,600 QPSになります。5倍のピーク時は約58,000 QPSです。1,000万件の投稿は平均で毎秒約116件の作成に過ぎませんが、200人の対象フォロワーへの書き込みファンアウトにより、1日あたり約20億件のタイムライン参照挿入(平均で毎秒約23,100件)に拡大します。生の投稿QPSのみを比較すると、主要な書き込み負荷が見落とされます。

第二に、プッシュ、プル、ハイブリッドの境界を理解しているか?純粋なfan-out-on-writeは読み取りを軽量化しますが、5,000万人のフォロワーを持つ著者が1人いれば5,000万回の挿入が発生します。純粋なfan-out-on-readは投稿を軽量化しますが、読み取りごとに多数のフォロー中著者をマージする必要が生じます。優れた設計では、通常著者の参照を事前計算し、高ファンアウト著者を読み取り時にプルし、アクティブフォロワー数、投稿頻度、キューの余裕、鮮度の目標からその境界を導き出します。

第三に、投稿の信頼できる情報源(Source of Truth)、候補プール、最終プレゼンテーションを分離できるか?タイムラインには、コピーされた本文ではなく軽量な参照が保存されます。アグリゲーターは、事前計算されたインボックス、高ファンアウト著者の最近の投稿、推薦候補をマージし、認可、削除、ブロック、重複排除を適用した後、ランキングとハイドレーション(詳細データの付加)を行います。モデルのスコアが表示ルールを上書きすることは決してありません。

第四に、ランキングが変動する中で有用なページネーションセマンティクスを維持できるか?エンゲージメントやモデルのバージョンによってスコアが動くため、オフセットやスコアのみでは重複や欠落が発生します。回答では、短期間の固定フィードセッションか、バージョン管理された複合カーソルを提案し、スクロール中に新規投稿、削除、アンフォロー、公開範囲の変更が発生した場合に何が起きるかを説明する必要があります。

最後に、設計は復旧可能であり、検証可能(反証可能)である必要があります。イベントバス、キャッシュ、ファンアウトワーカーは失敗したり作業を繰り返したりする可能性があります。冪等な参照、遅延モニタリング、境界付きソースフォールバック、トゥームストーンフィルタリング、修復スキャンを収束させる必要があります。検証には、セレブリティのバースト、重複や順不同のイベント、アンフォローの競合、削除漏れ、キャッシュ喪失を含める必要があります。

回答前に確認すべき質問

  • ホームページには何が表示されるか? 主にフォローしている著者の投稿で、少数の推薦プールを含みます。広告、グループ、トピックフィードはスコープ外です。
  • ランキングの取り決め(契約)は? 関連度ランキングがデフォルトです。結果は鮮度が高く、意図的にソースを混合する必要がありますが、厳密な時系列順は不要です。
  • 誰が投稿を閲覧できるか? 投稿は全体公開、フォロワー限定、非公開のいずれかです。ブロック、削除、公開制限は、キャッシュヒットやランキングよりも優先されます。
  • 誰にread-your-writes(自分の書き込みの即時読み取り)が必要か? 著者は新規投稿を即座に確認できる必要があります。アクティブな通常フォロワーの可視化目標は5秒です。オフラインのフォロワーは次回のアクセス時に追いつけば問題ありません。
  • ページネーションの安定性はどの程度必要か? 連続スクロールでは、重複や欠落を最小限に抑える必要があります。新規投稿はリフレッシュ時または新しいセッションで表示されます。削除やアクセス権の取り消しは、現在のセッション内でも即座に適用されます。
  • グラフの偏りはどの程度か? 通常著者の対象フォロワー数は平均200人ですが、最大では5,000万人に達します。平均値によってホットスポットを隠してはなりません。
  • どの程度のデータが保持されるか? 各アクティブユーザーに対して最新の候補参照500件を事前計算します。投稿本文は製品ポリシーに従って保持し、古いアイテムは必要に応じて著者インデックスや推薦インデックスから取得します。
  • リージョン要件は何か? 読み取りはローカルで処理し、投稿が著者のホームリージョンでコミットされた後に非同期で複製します。通常の鮮度は数秒で許容されますが、公開制限はより優先度の高い無効化パスを使用します。

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

「信頼できる投稿ストア、フォローグラフ、ユーザーごとの候補インボックスを分離します。作成トランザクションで投稿とアウトボックスイベントを書き込みます。ファンアウトワーカーは通常著者をアクティブフォロワーのインボックスへ冪等に挿入し、高ファンアウト著者は著者最新インデックスにのみ書き込み、読み取り時にプルされます。フィードアグリゲーターは、事前計算された候補、高ファンアウト候補、推薦候補をマージし、認可、削除、ブロック、重複排除を適用した後、取得とランキングを用いて短期間のフィードセッションを作成します。カーソルにはセッションと位置が含まれ、投稿本文は最終アイテムに対してのみハイドレーションされます。削除や公開制限は信頼できるトゥームストーンと高優先度の無効化を書き込み、読み取りごとに再確認されます。キュー遅延時は古い実体化フィードを返し、制限付きのソース読み取りを実行します。投稿から表示までのレイテンシ、重複、削除漏れ、各ステージのp99を監視します。」

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

ステップ1:容量からアーキテクチャの許容枠を導出する

1日あたりのフィード読み取り数は次のとおりです:

text
50,000,000 DAU × 20 pages/day = 1,000,000,000 feed reads/day
1,000,000,000 / 86,400 ≈ 11,574 average read QPS
11,574 × 5 peak factor ≈ 57,870 peak read QPS

投稿作成の平均は10,000,000 / 86,400 ≈ 116 QPSです。通常著者が平均200人のアクティブフォロワーにファンアウトする場合、1日あたり約20億件の候補参照挿入、つまり平均で毎秒2,000,000,000 / 86,400 ≈ 23,148件の挿入が発生します。5,000万フォロワーを持つ著者の1件の投稿は、通常の書き込み許容枠の数秒分を超えるため、同期的なフルファンアウトは安全ではありません。

5,000万人のアクティブユーザーそれぞれに500件の参照を保持すると、250億件の参照になります。大まかな参照がpost_idauthor_id、初期スコア、時間、フラグに64バイトを使用する場合、インデックス、エンジンオーバーヘッド、レプリカを除いた論理的な下限は約1.6 TBになります。したがって、タイムラインにはコピーされた投稿本文ではなく制限された参照を保存し、アクティビティに応じた階層化ストレージを使用する必要があります。

ステップ2:オーナーシップ、API、最小データモデルを定義する

投稿サービスは、本文、著者、作成日時、公開範囲、バージョン、削除トゥームストーンを所有します。ソーシャルグラフサービスは、followingおよびfollowersの隣接インデックスを所有します。フィードサービスは、候補参照、セッション、インプレッションログを所有します。オブジェクトストレージとCDNが画像を保持し、タイムラインにはメディア参照のみが含まれます。コアAPIは次のようになります:

text
POST   /v1/posts                         create a post with Idempotency-Key
DELETE /v1/posts/{post_id}               write a deletion tombstone
PUT    /v1/users/{id}/following/{author} follow an author
DELETE /v1/users/{id}/following/{author} unfollow an author
GET    /v1/feed?cursor=...&limit=20      read one ranked page
GET    /v1/posts/{post_id}               hydrate one visible post

postspost_idによる信頼できる状態と、(author_id, created_at, post_id)上の最新インデックスを保存します。followsは閲覧者ごとにフォロー対象を一覧表示し、著者ごとにフォロワーをシャード化する必要があります。feed_inboxviewer_idでパーティション分割され、そのソートキーには取得スコア、作成日時、post_idが含まれます。feed_sessionsはランキングバージョン、ソート済み候補ID、有効期限を一時的に保存します。インプレッションおよびエンゲージメントイベントは、読み取り中にすべての候補を同期更新するのではなく、特徴量や実験用の個別ログに送信されます。

投稿作成には呼び出し元の冪等性キーを受け取ります。投稿とアウトボックスイベントは1つのデータベーストランザクションでコミットされ、その後著者は投稿の信頼できる情報源から読み取ることができます。バスはat-least-once(少なくとも1回)の配信を提供します。ユニークまたは条件付きの(viewer_id, post_id)書き込みにより、重複ファンアウトを収束させます。イベントには投稿バージョンが含まれるため、古いイベントによって削除済みまたは新たに制限された投稿が復活することはありません。

ステップ3:通常著者と高ファンアウト著者にハイブリッドファンアウトを採用する

通常著者が投稿した後、ファンアウトサービスは対象アクティブフォロワーのシャードを読み取り、各インボックスに軽量な参照を一括挿入(バッチインサート)します。ワーカーはシャードカーソルとイベントIDで進捗を追跡します。タイムアウトしたバッチは、2つ目の候補を作成することなく同じ処理を再試行します。オフラインまたは長期間非アクティブなユーザーは即座に実体化する必要はなく、次回のアクセス時にフォローグラフから最新の候補を再構築できます。

高ファンアウトの投稿は、(author_id, created_at)の最新インデックスとホットキャッシュにのみ送られます。閲覧者がそのような著者をフォローしている場合、アグリゲーターは各著者から制限された数の最新アイテムを並行してプルし、インボックスとマージします。この境界は永続的なフォロワー数の固定値であるべきではありません。eligible_active_followers × posts_per_windowの書き込みコストを見積もり、予想される読み取りマージコスト、キューの余裕、5秒の鮮度目標と比較します。著者の人気が急上昇したり短時間に連続投稿したりした場合、コントロールプレーンはその著者をプルモードに切り替えることができます。すでにキューに入っているバッチは冪等に完了するかキャンセルされますが、両方のパスが無制限に実行されてはなりません。

閲覧者が多数の高ファンアウト著者をフォローしている場合、プルによって依然として高コストな読み取りファンアウトが発生する可能性があります。アグリゲーターは、ソースごとの候補数、同時実行数、期限を制限し、最新著者インデックスをキャッシュし、あるソースがタイムアウトした際には他の適格な候補を返します。リージョンごと、またはフォロークラスタごとの事前集約も可能ですが、測定されたマージコストがボトルネックになって初めて正当化されます。

ステップ4:候補生成、フィルタリング、ランキング、ハイドレーションを分離する

読み取りパスには4つのステージがあります:

  1. 通常著者のインボックスから候補バッチを読み取り、高ファンアウト著者および推薦ソースから制限されたバッチを読み取る。
  2. post_idで重複を排除し、フォロー状況、ブロック、トゥームストーン、現在の公開範囲、リージョンポリシーを確認する。
  3. 軽量なスコアリングでセットを絞り込み、その後、エンゲージメントの可能性、鮮度、ソースの品質、ネガティブフィードバックを考慮した重いモデルを適用し、続いて多様性と頻度の制約を適用する。
  4. 最終的な20件について、本文、著者サマリー、集計カウントを一括ハイドレーションして返却し、インプレッションを非同期でログ記録する。

Metaの公開エンジニアリング事例では、ランキング前に候補、オブジェクト、特徴量を収集し、複数回のモデルパスで計算量を削減するフィードアグリゲーターが説明されています。Pinterestの公開アーキテクチャでも同様に、未閲覧候補プール、コンテンツ生成、実体化フィードを分離しています。面接の設計でいずれかのシステムを完全に模倣する必要はありませんが、これらの事例は、投稿全体をキャッシュにコピーしてその場でソートする手法に重要な境界線が欠けている理由を示しています。

認可と製品制約はランキングの前後で適用されます。初期フィルタリングは無駄な処理を削減し、ハイドレーション中に投稿バージョンを再確認することで、ランキング中に発生した削除や公開制限を遮断します。モデルスコアは順序付けの入力に過ぎず、不可視のコンテンツを再出現させることはできません。エンゲージメント数は結果整合性で構いません。著者、本文、公開範囲、トゥームストーンは、信頼できる投稿バージョンから取得します。

ステップ5:フィードセッションで動的ランキングを安定化する

offsetを使用すると、新規コンテンツの到着やスコアの変動によってアイテムが重複またはスキップされます。(score, post_id)のキーセットのみでも、次のページまでに再ランキングでスコアが変わった場合には不十分です。最初のリクエストで最大500件の候補IDをランク付けし、30分間のfeed_session_idの下に保存できます。不透明な(opaque)カーソルには、セッション、次の位置、クエリフィンガープリント、署名が含まれます。以降のページは位置によって読み取り、公開範囲を再確認し、欠落を埋めます。

新規投稿は、途中に挿入されるのではなく、閲覧者がリフレッシュするか新しいセッションを開始したときに表示されます。削除、ブロック、公開制限は即座に除外されるため、現在のセッションからアイテムが消える場合があります。その際、アグリゲーターはセッション内の後続候補から補充します。セッションキャッシュが失われたり期限切れになったりした場合は、認識可能なカーソル期限切れ結果を返し、クライアントが表示済みのIDを保持したままリフレッシュできるようにします。古い位置を新しいランキングにそのまま適用してはなりません。

500件の固定IDの保存が高コストすぎる場合は、ランキングエポックと複合キーセットを保存し、クライアントに表示済みIDのサマリーを送信させます。この設計はセッションストレージを節約できますが、重複排除、モデル変更、削除時の補充が難しくなります。カーソルのエンコーディングを主たる回答として扱うのではなく、連続スクロールの時間、許容される重複率、セッションの許容コストから選択してください。

ステップ6:フォロー、削除、公開範囲の変更を正確に収束させる

フォローがコミットされた後、閲覧者の次回の読み取りでは、制限付きのバックフィルが非同期で実行されている間に新しい著者の最近の投稿をプルできます。アンフォローとブロックはまず信頼できるグラフを更新し、読み取りパスは即座にその著者を除外してからインボックスを非同期でクリーンアップします。表示を停止するために数百万件の物理削除が完了するのを待つ必要はありません。フォローイベントと投稿イベントが順不同で到着した場合、候補内の関係バージョンは単なる最適化に過ぎません。最終的な公開範囲は常に最新の正式なルールに従います。

投稿を削除または非公開にする際、投稿サービスは新しいバージョン、トゥームストーン、高優先度のアウトボックスイベントを一緒にコミットします。キャッシュの無効化、検索のクリーンアップ、インボックスのクリーンアップは非同期で行われる可能性がありますが、フィードハイドレーションは最新バージョンを一括読み取りしてフィルタリングします。ホットトゥームストーンキャッシュによってチェックが高速化され、永続化された投稿レコードによってキャッシュ喪失後に古いコンテンツが再表示されるのを防ぎます。修復スキャンによって古い参照が削除されますが、物理的なクリーンアップ自体が認可機構というわけではありません。

いいねやコメントによって、スコアが変わるたびに全フォロワーのインボックスを書き換えるべきではありません。エンゲージメントイベントは集計カウントと特徴量を更新し、アクティブな閲覧者は次回の要求時に候補を再ランク付けします。非常にホットなコンテンツは共有特徴量キャッシュを更新できます。これにより、ランキングの一時的な遅れを許容し、各インタラクションが別のグローバルファンアウトになるのを防ぎます。

ステップ7:デグラデーション、復旧、リージョン境界を設計する

ファンアウトキューの遅延時は、まず投稿作成と実体化フィードの読み取りを保護します。フィードは、より古い適格な候補セットを返し、閲覧者が最近アクティブにしたフォロー対象に対して制限付きのソース読み取りを実行できます。鮮度は低下しても構いませんが、認可は低下してはなりません。特定の著者がキューのホットスポットを作成している場合は、その著者をプルモードに切り替え、未完了のバッチを制限します。復旧後は、イベント時刻とバージョンに基づいて冪等に処理を追いつかせます。キューの長さだけでなく、最も古いイベントの経過時間も監視してください。

候補キャッシュで障害が発生した場合は、永続インボックスから読み取る候補数を減らすか、保存されたセッションを返します。ランキングがタイムアウトした場合は、決定論的な鮮度スコアと多様性ルールを使用します。信頼できる投稿ストアまたはグラフストアが利用できない場合は、安全な認可TTL(有効期間)内で事前に検証されたコンテンツのみを提供します。そのTTLを過ぎた後は、アクセス権が取り消された可能性のあるコンテンツを表示するよりは、失敗させるか結果を絞り込みます。

複数リージョンの構成では、著者のホームリージョンが投稿を受け付けてグローバルIDを割り当て、その後イベントが読み取りリージョンに非同期で複製されます。通常のコンテンツは秒レベルの鮮度で構いません。著者はホームリージョンを通じて即座にread-your-writesを取得します。削除、ブロック、公開制限はより優先度の高いレプリケーションを使用し、古いレプリカはグローバルトゥームストーンサービスが状態を確認するまで制限されます。フォローグラフのアクティブ-アクティブ書き込みは関係の競合を引き起こすため、明示的な要件がある場合にのみ導入すべきです。

ステップ8:メトリクスと障害注入で境界を検証する

コアメトリクスには、作成成功率、投稿から最初のフォロワーおよび95%のアクティブフォロワーへの表示時間、シャードごとのファンアウトスループットと最大遅延、高ファンアウトのプルレイテンシ、候補数、重複排除率、フィルター率、取得およびランキングのp99、ハイドレーションバッチサイズ、キャッシュヒット率、カーソル期限切れ、ページ重複、空ページ、削除またはアクセス取り消し済みコンテンツの漏洩が含まれます。最後のメトリクスは常にゼロを維持する必要があり、能動的な合成プローブ(外形監視)が必要です。

障害注入では、重複および順不同の投稿イベント、5,000万フォロワーを持つ著者による連続投稿、ファンアウト途中でプッシュからプルへの切り替え、同時発生するフォロー・アンフォロー・投稿、ページング中の削除または公開範囲変更、トゥームストーンキャッシュの喪失、単一の低速フォロワーシャード、イベントバスの停止と追いつき、ランキングのタイムアウト、フィードセッションノードの喪失、リージョン間レプリケーション遅延を網羅する必要があります。すべてのシナリオにおいて、不正なコンテンツが表示されないこと、参照が収束すること、レイテンシの低下が観測可能であること、復旧によって重複書き込みが増幅しないことを検証します。

高品質な回答例

「5,000万DAUで1日20ページの場合、フィード読み取りは平均で約11,600 QPS、5倍のピーク時で58,000 QPSになります。1日1,000万件の投稿は約116 QPSに過ぎませんが、通常著者1人あたり200人のアクティブフォロワーがいるため、候補挿入は平均で毎秒約23,100件に拡大します。5,000万フォロワーへの1件の投稿に対して同期フルプッシュを使用することはできません。

信頼できる投稿ストア、ソーシャルグラフ、候補インボックスを分離します。作成トランザクションで投稿とアウトボックスを書き込みます。通常著者のイベントは、viewer_id + post_idの冪等性を用いてフォロワーシャードごとにユーザー別インボックスにファンアウトされます。高ファンアウト著者は最新著者インデックスにのみ書き込み、フィード読み取り時にプルしてマージします。プッシュとプルの境界には、アクティブフォロワー数、投稿頻度、キューの許容量、読み取りコストを使用します。タイムラインには参照を保存し、本文とメディアは最終アイテムに対してのみ一括ハイドレーションします。

読み取り時、アグリゲーターはインボックス、高ファンアウトソース、推薦ソースから制限された候補を取得します。安価な取得、重いランキング、多様性、頻度制御の前に、現在のフォロー、ブロック、トゥームストーン、公開範囲に基づいてフィルタリングと重複排除を行います。最初のページでは30分間のフィードセッションに最大500件の候補を固定し、カーソルにはセッションと位置が含まれます。新規投稿はリフレッシュを待ちますが、削除や公開制限はすべてのページでフィルタリングされ補充されます。

削除やプライバシーの変更は、正式なバージョンと高優先度の無効化をコミットします。キャッシュやインボックスのクリーンアップは遅れる可能性がありますが、すべての表示で状態が再確認されます。キュー遅延時は古い実体化フィードを返し制限付きのソース読み取りを行い、ランキングタイムアウト時は鮮度ベースにフォールバックします。認可が低下することは決してありません。投稿から表示までのレイテンシ、最大遅延、各ランキングステージのp99、重複率、取り消し済みコンテンツの漏洩を監視し、セレブリティのバースト、重複イベント、アンフォロー競合、削除、キャッシュ喪失、リージョン障害を注入します。」

よくある間違い

  1. 生の読み取りQPSと書き込みQPSのみを比較する。 投稿は平均約116 QPSですが、フォロワーのファンアウトが書き込みの大半を占めます。増幅率とヘビーテイルなグラフ構造を計算してください。
  2. すべての著者にfan-out-on-writeを使用する。 5,000万フォロワーの著者は5,000万回の挿入を引き起こします。高ファンアウト著者は読み取り時にプルしてください。
  3. セレブリティの閾値を恒久的な固定値にする。 フォロワーのアクティビティ、投稿頻度、キューの余裕は変動します。コストとSLOから分類し、遷移時の安全性を確保してください。
  4. タイムラインに本文全体をコピーする。 編集、削除、公開制限により膨大な無効化対象が発生します。参照を保存し、ハイドレーション中にバージョンを再確認してください。
  5. 動的にランク付けされるページにoffsetを使用する。 挿入や再ランキングによって重複や欠落が発生します。短期間のフィードセッションまたはバージョン管理された複合カーソルを使用してください。
  6. バックグラウンドジョブでのみアンフォローや削除をフィルタリングする。 クリーンアップの遅延によりコンテンツが漏洩します。読み取り時に信頼できるグラフ、トゥームストーン、公開範囲を確認してください。
  7. イベントバスによるエンドツーエンドのexactly-once(厳密に1回)を主張する。 ワーカー、ストレージ、再試行によって依然として重複が発生します。イベントID、投稿バージョン、一意の候補キーを用いて収束させてください。
  8. デグラデーション時に認可チェックをスキップする。 古い順序や候補数の減少は許容される場合がありますが、認可されていない表示は許容されません。安全フィルタリングには独自の許容枠と障害ポリシーを割り当ててください。
  9. 通常トラフィックのみをテストする。 重要なリスクは、高ファンアウト著者、遅延、順序の入れ替わり、認可の競合です。障害注入はこれらの境界を網羅する必要があります。

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

フォローアップ1:通常著者が突然5,000万人のフォロワーを獲得した場合、両方のパスで重複をどのように防ぎますか?

コントロールプレーンがバージョン管理下で著者をプルモードに切り替えます。ファンアウトジョブはそのモードバージョンを読み取り、すでに要求(クレーム)済みの制限されたバッチのみの完了を許可します。候補は(viewer_id, post_id)に対して冪等であるため、プッシュされたコピーとプルされたコピーは1つにマージされます。キューは各著者にクォータを割り当て、移行中の新規投稿は直接高ファンアウトインデックスに送られます。

フォローアップ2:閲覧者が著者をアンフォローした後、古いフィードセッションはどうなりますか?

セッションは順序を固定するものであり、認可を固定するものではありません。各ページのハイドレーションバッチで、現在のフォローおよびブロックグラフが確認されます。アンフォローされたコンテンツは除外され、後続の候補から置き換えられます。非同期のインボックスクリーンアップは容量を節約しますが、即時の認可セマンティクスを提供するものではありません。

フォローアップ3:厳密な時系列順をどのようにサポートしますか?

候補ソースと公開範囲フィルターを再利用し、ソートキーを(created_at, post_id)に変更し、上限スナップショット時刻を指定したキーセットページネーションを使用します。新規投稿はリフレッシュ後に表示されます。高ファンアウトソースと通常のインボックスソースのマージは依然として必要ですが、重いランキングセッションは不要になります。

フォローアップ4:ランキングモデルのリリース後に重複率が増加した場合、どのように原因を特定しますか?

重複排除前後の候補数、セッション生成ID、カーソル位置、インプレッションログをモデルバージョンごとに比較します。重複がソース、ランキング出力、喪失したセッションのどこから入っているかを特定します。ソースのエイリアスを信頼できるpost_idにマッピングします。セッションストレージが不安定(フラッピング)になっている場合、モデルのロールバックは効果がありません。セッションストアを復旧し、クライアントに明示的にリフレッシュさせてください。

フォローアップ5:ハイブリッドファンアウトの境界が正しいことをどのように確認しますか?

実際のフォロワー数とアクティビティの分布をオフラインでリプレイします。各著者の事前計算書き込み、キュー待機、読み取りマージ、キャッシュヒットコストを見積もります。投稿から表示までのp99、フィード読み取りのp99、総ストレージ書き込み、デグラデーション率を観察しながら、オンラインで境界を徐々に移動させます。著者がプッシュモードとプルモードの間を頻繁に行き来しないようにヒステリシス(しきい値の幅)を設けます。

公開情報ソース

関連する質問

関連面接ツール

システム設計の回答には「回答する」を使用

まず要件を明確にし、スケール、アーキテクチャ、コンポーネント選定、トレードオフの順に進めます。

ツールを見る