コンテンツにスキップ

Backend Interview: ドライバーのリアルタイム位置情報システム設計

問題

何千ものドライバーが毎秒位置情報を更新している。何千もの乗客がリアルタイムで近くのドライバーを探している。このシステムをどう設計するか?

要件の整理

機能要件

  • ドライバーが現在地をリアルタイム送信(例: 5秒ごと)
  • 乗客が指定範囲内(例: 半径5km)のドライバー一覧を取得
  • ドライバーの位置情報は最新のもので十分

非機能要件

  • ドライバー数: 例100万人がオンライン
  • 書き込み: 100万 ÷ 5秒 = 20万 writes/sec
  • 読み込み: 検索QPS × 1,000万乗客 → 数万〜数十万 reads/sec
  • レイテンシ: 位置更新は数秒の遅延まで許容、検索は100ms以内

アーキテクチャ設計

位置情報の書き込みパス

ドライバーアプリ
    ↓ WebSocket or HTTP
Location Update Service
    ↓ 書き込み
Redis (Sorted Set / Geo)
    ↓ 非同期
DB(履歴用)

なぜRedisか? - 20万 writes/secに耐えられる(インメモリで高速) - GEOADD コマンドで緯度経度を扱える - GEORADIUS / GEOSEARCH で範囲検索が O(N+log M) でできる

# ドライバーの位置を登録/更新
GEOADD drivers:locations 139.6917 35.6895 "driver:42"

# 渋谷駅から5km以内のドライバーを取得
GEORADIUS drivers:locations 139.7016 35.6581 5 km ASC COUNT 10

乗客の検索パス

乗客アプリ
    ↓ HTTP/REST
Query Service
    ↓ GEORADIUS
Redis Cluster
    ↓ レスポンス
乗客アプリ

スケールアウト戦略

書き込みのスケール: - Location Update Serviceを複数インスタンスに - ロードバランサーでドライバーIDをハッシュ → 同じドライバーは同じインスタンスへ(スティッキーセッション不要でWebSocket管理が楽) - Redisはクラスタ構成、ドライバーIDでシャーディング

読み込みのスケール: - Query ServiceはステートレスなのでHPA(Horizontal Pod Autoscaler)で増減 - Redis Clusterのread replicaから読む

古い位置情報の削除

ドライバーがオフラインになったら位置情報を削除する。

ドライバーがオフライン通知
Location Update Service
ZREM drivers:locations "driver:42"

または、TTL付きのキーを使って一定時間更新がなければ自動削除。

ボトルネックと改善点

問題 解決策
Redisの書き込みホットスポット Geohashでエリア分割、エリアごとにRedisインスタンス
大都市圏での検索遅延 QuadTree / S2 Geometryで空間インデックスを別途構築
WebSocket接続の維持 Connection Service + メッセージキュー(Kafka)で切り離す

面接でのポイント

  1. まず規模を計算する(writes/sec、reads/sec)
  2. なぜRedisを選んだか説明できる(GEO系コマンド、インメモリ速度)
  3. 単一障害点(Single Point of Failure)を意識してクラスタ構成を提案
  4. データの鮮度(位置情報は古くて良い?)とトレードオフを議論