コンテンツにスキップ

API秒間1万リクエスト対応:面接問題と解答アプローチ

問題

Interviewer: Your API is getting 10,000 requests per second. Server is choking. Users are complaining. You have 15 minutes to fix it. What do you do?

解答

即座に取れる対応(15分以内):

  1. レートリミットを設ける — Redis や API Gateway のレートリミット機能を有効化し、1クライアントあたりの RPS を制限する
  2. キャッシュを挟む — よく読まれるレスポンスを Redis/Memcached に乗せ、DB・アプリへのヒットを減らす
  3. 水平スケールアウト — ロードバランサー配下にアプリサーバーを追加してインスタンスを増やす
  4. 重い処理を非同期化 — キューに積んで即座に 202 Accepted を返し、ワーカーで後処理する

解説

なぜこの順番か

優先度 アクション 理由
1 レートリミット 悪意あるクライアントや暴走クライアントを即座に遮断
2 キャッシュ 読み取り系クエリが多い場合に劇的に負荷が落ちる
3 スケールアウト AWS/GCPなら数分で追加可能、CPU ボトルネック解消
4 非同期化 書き込み・重い処理を切り離す根本対策

キャッシュ戦略の選択

# Cache-Aside パターン(最も一般的)
def get_user(user_id):
    cached = redis.get(f"user:{user_id}")
    if cached:
        return json.loads(cached)

    user = db.query("SELECT * FROM users WHERE id = ?", user_id)
    redis.setex(f"user:{user_id}", 300, json.dumps(user))  # TTL 5分
    return user

レートリミットの実装例(Token Bucket)

# Redis を使った Token Bucket
def is_allowed(client_id, limit=100, window=60):
    key = f"rate:{client_id}"
    current = redis.incr(key)
    if current == 1:
        redis.expire(key, window)
    return current <= limit

トレードオフ

  • キャッシュ: 読み取り負荷には効くが、データ整合性の問題(Cache Invalidation)が発生しうる
  • スケールアウト: コストが増大する。ステートレスな設計(セッションを外出し)になっていることが前提
  • 非同期化: UX が変わる(即座の結果を返せない)。冪等性の担保が必要

面接でのポイント

  • 問題を分解して話す: まずボトルネックを特定(CPU? DB? ネットワーク?)してから対策を提案する姿勢を見せる
  • 即時対応と恒久対応を区別する: 「今すぐ15分でやること」と「中長期でやること」を分けて話す
  • 数字を使う: 「キャッシュヒット率を80%にすれば DB の負荷は1/5になる」など定量的な根拠を示す
  • トレードオフを述べる: 完璧な解法はないので、なぜこの選択をしたかの理由を添える