📝ノート💻テック

システム設計面接: 元Meta スタッフエンジニアと一緒にUberを設計する

Tony Duong

Tony Duong

6月 7, 20261

他の言語:🇫🇷🇬🇧
#system-design#uber#geospatial#quadtree#postgis#dynamodb#interview#distributed-systems
システム設計面接: 元Meta スタッフエンジニアと一緒にUberを設計する

Hello Interviewのシステム設計シリーズの2作目(Design Ticketmasterに続くもの)で、元Metaのスタッフエンジニア兼面接官が解説する。Uberの設計は近接検索系の問題の中でも最難関として紹介されており、これを攻略できればFind My Friends、Yelpなどの類似問題にも対応できる。そしてTesla、Google、Metaでよく出題される。

この動画では、ユーザー向けシステム設計全般に使える再現性のあるロードマップに沿って進める。要件 → コアエンティティ → API → 高レベル設計 → ディープダイブという流れで、最後にディープダイブの時間を確保できるよう、高レベル設計を15分ほどで終えることを目標にする。

要件

  • 機能要件(提供する機能): ライダーは目的地を入力して運賃の見積もりを取得できる。ライダーは配車をリクエストして近くのドライバーとマッチングされる。ドライバーは受諾/拒否を選べ、ライダーのもとへナビゲーションできる。
  • 非機能要件(満たすべき品質): 低レイテンシのマッチング(理想は約1分以内)、絶え間ないドライバー位置更新に対する高スループット、マッチングの強い一貫性(二重予約なし)、そして高可用性。

コアエンティティ

この段階で完全なスキーマを書く代わりに、永続化されるオブジェクト(おおむねテーブル/コレクションと一対一に対応する)をスケッチする。

  • Rider
  • Driver — メタデータ(車種、ナンバープレート、写真)とステータスavailablein_rideoffline)を持つ。
  • Ride
  • Location — すべてのドライバーの最新位置を保持し、マッチングが近接で問い合わせできるようにする。

API

エンティティと機能要件から導いたRESTエンドポイント(運賃見積もり、配車リクエスト、配車受諾、位置更新)で、認証はリクエストヘッダー内のJWT/セッショントークンで行う。

高レベル設計

各APIをシステムの中で順に追っていく。

  • Ride Matching Serviceが近接範囲内のドライバーを見つけ、availableに絞り込み、一人ずつ受諾を打診する。
  • Location Service + Location DBが頻繁なドライバーの位置pingを取り込み、近接クエリに答える。
  • Notification Service(ブラックボックス扱い — それ自体が一つの面接問題)が、ネイティブプッシュ(APNs / Firebase)経由でドライバーに「この配車を受けますか?」というプロンプトを送る。受諾すると、ドライバーのアプリがコールバックしてマッチを確定する。

ディープダイブ

地理空間インデックス(quad tree / PostGIS)

「全ドライバーを走査して距離を計算する」という素朴な方法はあまりにも遅すぎる。そこで地理空間インデックスquad tree — を導入する。これは各セルに収まるドライバーが何らかのK未満になるまで、地図を再帰的に4つの領域に分割するものだ。これにより近接クエリが効率的になる。PostgresではPostGIS拡張機能を通じてこれが利用できる。

位置更新スループットの抑制

すべてのドライバーからの絶え間ないpingは約60万TPSにも達しうるが、これは無駄が多い。動的な位置更新を使おう。ドライバーアプリに、状況に応じて更新頻度を変化させるのだ。速度、車が駐車中かどうか(動いていない → 更新不要)、配車リクエストやホットエリアへの近さ(人里離れた場所では精度はそれほど必要ない)などに基づく。これで書き込み負荷を劇的に削減できる。

マッチングの一貫性

2つの不変条件がある。1人のドライバーが複数の配車を受け持たないこと、そして1つの配車が複数のドライバーに割り当てられないこと。これはマッチング保留中にドライバーにロックをかけることで解決する。きれいな選択肢はDynamoDB(リレーションが少なく、高可用性で、スケールしやすい)で、行にTTLを設定したドライバーロック用テーブルを使い、古くなったロックが自動的に失効するようにする。別途Redisインスタンスを追加するのではなく、同じデータベースをロックとして再利用するのだ。

主な学び

  • ロードマップに従う: 要件 → エンティティ → API → 高レベル設計 → ディープダイブ。ディープダイブにしっかり時間を割けるよう配分する。
  • Driverとは別にLocationエンティティをモデル化して、近接マッチングを高速に保つ。
  • quad tree + PostGISは地理空間/近接検索の定番の答え。
  • 動的で状況に応じた位置更新が書き込みスループット削減の決め手。
  • **ドライバーをロックする(例: TTL付きのDynamoDB)**ことで、二重予約なしにマッチングの一貫性を保つ。
  • この近接検索のパターンはFind My Friends、Yelpなどにも一般化できる。

🌐 Claudeによる翻訳

Tony Duong

著者: Tony Duong

デジタル日記。思考、経験、そして人生についての考え。