Skip to content

システム設計方法論

はじめに

システム設計はアドリブでアーキテクチャ図を描くことではなく、体系化された方法論に従うものです。 面接でのシステム設計問題であれ、実際の仕事でのアーキテクチャ設計であれ、似た思考フレームワークに従います。まず問題を明確にし、次に規模を見積もり、設計案を作成し、最後に深掘りして最適化します。

この記事で何を学べるのか?

この章を読み終えると、以下のことが身につきます:

  • 設計プロセス:システム設計の4ステップフレームワークを習得する
  • キャパシティ見積もり:「封筒の裏の計算」のテクニックを学ぶ
  • 一般的なパターン:キャッシュ、シャーディング、メッセージキューなどのコアパターンに習熟する
  • トレードオフ思考:アーキテクチャ設計におけるトレードオフの考え方を理解する
  • 実践例:短縮URLサービス、フィードなどを使って設計プロセスを理解する
内容核心概念
第1章設計の4ステップ要件の明確化、キャパシティ見積もり、アーキテクチャ設計、深掘り最適化
第2章キャパシティ見積もりQPS、ストレージ、帯域幅、封筒の裏の計算
第3章コア設計パターンキャッシュ、シャーディング、メッセージキュー、CDN
第4章トレードオフ思考一貫性 vs 可用性、パフォーマンス vs コスト
第5章古典的な例短縮URLサービス、フィード、フラッシュセールシステム

1. システム設計の4ステップ

システム設計は、最初からアーキテクチャ図を描くことではありません。面接でも実践でも、構造化されたプロセスに従うべきです。

Four-Step System Design Method
Click each step to inspect the details
1
Clarify requirements
~5 min
2
Estimate capacity
~5 min
3
Design architecture
~15 min
4
Deep dive
~10 min
Clarify requirements
Do not rush into drawing architecture diagrams. First clarify the problem, scale, core features, and non-functional requirements.
What are the core features? (MVP scope)
Expected user scale? DAU / QPS
Read/write ratio?
Data volume? How much data must be stored?
Availability target? How many nines?
Latency target? What P99 latency is acceptable?
Example: designing a URL shortener
URL shortener: create short links (write) and redirect (read), roughly 100:1 read/write ratio, 100 million redirects per day, links never expire.

なぜまず要件を明確にするのか?

多くの人が問題を受け取った直後に図を描き始め、「正しいが面接官が求めていない」システムを設計してしまいます。5分かけて要件を明確にすれば、その後の30分のやり直しを防げます。

よくある明確化の質問:

  • システムのコア機能は何か?(すべての機能を設計しない)
  • ユーザー規模はどのくらいか?(分散の必要性を決める)
  • 読み書きの比率は?(キャッシュ戦略を決める)
  • データはどのくらい保持するか?(ストレージの設計を決める)

2. キャパシティ見積もり:封筒の裏の芸術

「封筒の裏の計算」(Back-of-envelope estimation)は、システム設計におけるコアスキルです。正確な計算は必要なく、オーダーが分かればよいのです。

Back-of-the-Envelope Estimator
Enter basic numbers to estimate system capacity requirements
Daily requests
2000.0 ten thousand
Average QPS
231
Peak QPS
693
Daily bandwidth
102.4 GB
Peak bandwidth
3.5 MB/s
Common estimation references
1 day86,400 seconds
1 month~2.5M seconds
QPS 1000~1 eight-core server
100M/day~1,200 QPS
Single MySQL node~5,000 QPS
Single Redis node~100,000 QPS

よく使う換算早見表

オーダー換算覚え方
1日86,400秒≒ 約10万秒
1億リクエスト/日≒ 1,200 QPS10万で割る
1 KB × 1億≒ 100 GB1億件の小さなレコード
1 MB × 100万≒ 1 TB100万枚の画像

2-8法則の見積もりへの応用

ほとんどのシステムは80/20法則に従います。20%のデータが80%のリクエストを処理します。つまり:

  • キャッシュサイズ ≒ 総データ量 × 20%
  • ホットスポットQPS ≒ 総QPS × 80%が20%のキーに集中
  • キャッシュヒット率の目標 ≒ 80%以上(これより低いとキャッシュ戦略に問題がある)

3. コア設計パターン

システム設計で繰り返し現れるパターンです。これらを把握すれば、ほとんどのシナリオに対応できます。

3.1 キャッシュパターン

パターン読み取りパス書き込みパス適用シナリオ
Cache-Asideまずキャッシュを検索、ミスならDBを検索してキャッシュに書き戻すまずDBに書き込み、その後キャッシュを削除汎用シナリオ、最も一般的
Read-Throughキャッシュ層が自動的にDBからロードCache-Asideと同じキャッシュフレームワークのサポートが必要
Write-BehindCache-Asideと同じまずキャッシュに書き込み、非同期でDBに書き込む書き込み集中型、データ損失を許容できる場合

なぜ「キャッシュの更新」ではなく「キャッシュの削除」なのか?

キャッシュの更新は並行処理のシナリオでデータの不整合を引き起こしやすくなります。スレッドAとBが同時に更新する際、Aが先にDBに書き込んだのにBが先にキャッシュを更新してしまい、キャッシュにBの古い値が残る可能性があります。キャッシュの削除なら、次回の読み取りリクエストでDBから再ロードされるため、この問題を自然に回避できます。

3.2 シャーディング

単一テーブルのデータ量が千万件を超えるか、単一データベースのQPSがボトルネックに達した場合、シャーディングを検討する必要があります。

戦略やり方メリットデメリット
垂直分割ビジネスドメインごとにデータベースを分割ビジネスの疎結合、独立したスケーリングクロスデータベースのJOINが困難
水平分割同じテーブルをルールに従って複数のテーブルに分割単一テーブルのデータ量をコントロール可能シャードキーの選択が重要
垂直テーブル分割大きなフィールドを独立したテーブルに分割IOの削減、クエリ効率の向上追加のJOINが必要

シャードキーの選択原則

  • 最も頻繁にクエリされるフィールドを選択する(例:user_id)
  • データの分布を均等にし、ホットスポットを避ける
  • 同一ユーザーのデータを同じシャードに配置する(クロスシャードクエリの削減)

3.3 メッセージキュー

メッセージキューは分散システムの「ショックアブソーバー」で、中核的な役割は疎結合、非同期化、ピークの平滑化です。

シナリオキューを使わない場合キューを使う場合
注文後の通知送信注文APIが同期的に通知サービスを呼び出し、通知の失敗が注文の失敗につながる注文成功後にメッセージを送信し、通知サービスが非同期で消費
フラッシュセール瞬間的なトラフィックがデータベースを圧倒リクエストがまずキューに入り、バックエンドが処理能力に応じて消費
データ同期サービスAがサービスBのAPIを直接呼び出すサービスAがイベントを発行し、サービスBが購読して処理

4. トレードオフ思考:銀の弾丸はない

アーキテクチャ設計の本質はトレードオフです。すべての決定には代償があり、代償を理解した上で現在の段階に適した選択をすることが重要です。

トレードオフの軸選択肢A選択肢B判断基準
一貫性 vs 可用性強一貫性(CP)高可用性(AP)ビジネスが一時的な不整合を許容できるか?
パフォーマンス vs コストフルキャッシュオンデマンドキャッシュデータ量と予算
シンプルさ vs 柔軟性モノリスアーキテクチャマイクロサービスチーム規模とビジネスの複雑さ
リアルタイム vs バッチストリーム処理バッチ処理データの即時性の要件
自社構築 vs マネージド自前でMySQLを構築クラウドデータベース(RDS)を利用運用能力とコスト

アーキテクチャ決定記録(ADR)

重要なアーキテクチャの決定はすべて記録すべきです。背景は何か、どの選択肢を検討したか、なぜこれを選んだか、どのような代償があるか。これは責任転嫁のためではなく、後の人が「なぜ当時こう設計したのか」を理解できるようにするためです。

フォーマットはシンプルです:

  • タイトル:XXXをYYYに置き換える
  • 背景:どのような問題に直面したか
  • 決定:どの案を選択したか
  • 理由:なぜこれを選んだか
  • 代償:この決定のデメリットとリスク

よくある誤ったトレードオフ

間違い表れ正しいアプローチ
早すぎる最適化DAU1000でシャーディングを導入まず単一DBを使い、ボトルネックに遭遇してから分割
技術主導「Kafkaを使いたい」ではなく「非同期が必要」が先技術ではなく問題から出発する
運用コストの無視最適な案を選んだがチームが維持できないソリューションはチームの能力に合わせる
完全な一貫性の追求すべてのシナリオで分散トランザクションを使用ほとんどのシナリオでは結果整合性で十分

5. 古典的な例

3つの古典的な例を通じて、これまでに学んだ方法論を統合します。

5.1 短縮URLサービス(TinyURL)

短縮URLサービスはシステム設計面接の古典的な問題で、小さいながらも要素が揃っています。

要件の明確化

  • コア機能:長いURL → 短いURL(書き込み)、短いURL → リダイレクト(読み取り)
  • 読み書き比:約100:1(読み取りが書き込みより遥かに多い)
  • 日平均リダイレクト:1億回
  • 短縮URLは期限切れにならない

キャパシティ見積もり

指標計算結果
書き込みQPS1億 / 100 / 86400≒ 12 QPS
読み取りQPS1億 / 86400≒ 1,200 QPS
ピーク読み取りQPS1,200 × 3≒ 3,600 QPS
5年間のストレージ100万/日 × 365 × 5 × 100B≒ 18 GB
キャッシュ(20%)18 GB × 20%≒ 3.6 GB

アーキテクチャ設計

書き込みパス:クライアント → API Server → IDジェネレータ → Base62エンコード → MySQL + Redisに書き込み
読み取りパス:クライアント → CDN → API Server → Redis検索 → 302リダイレクト
                                    ↓ (cache miss)
                                  MySQL検索 → Redisに書き戻し

主要な設計上の決定

  • 短縮コードの生成:Snowflake分散ID + Base62エンコードでハッシュ衝突を回避
  • キャッシュ戦略:Cache-Aside、ホットな短縮URLはCDNで高速化
  • データベース:単一テーブルで十分(18GBは小さい)、短縮コードでインデックス

5.2 フィードシステム

ソーシャルプラットフォームのフィード(WeChatのモーメンツ、Weiboのホームタイムライン)はもう1つの古典的な問題です。

コアの課題:ユーザーが投稿を公開したとき、すべてのフォロワーにどうやって届けるか?

方式やり方メリットデメリット
プルモデル(Pull)読み取り時にリアルタイムでフォローの投稿を集約書き込みがシンプル、ストレージが少ない読み取りが遅い、フォローが多いとレイテンシが高い
プッシュモデル(Push)投稿時に全フォロワーの受信トレイに書き込む読み取りが極めて高速インフルエンサーの投稿で書き込み拡散が深刻
プッシュ・プル併用一般ユーザーはプッシュ、インフルエンサーはプル読み書きのパフォーマンスのバランス実装が複雑

プッシュ・プル併用の設計

  • フォロワー数 < 1万:投稿時に全フォロワーのフィードキャッシュにプッシュ(プッシュモデル)
  • フォロワー数 > 1万:プッシュせず、フォロワーが読み取り時にリアルタイムで取得(プルモデル)
  • ユーザーがフィードを開いた時:プッシュされた内容 + インフルエンサーのリアルタイム取得内容をマージし、時系列でソート

5.3 フラッシュセールシステム

フラッシュセールのコアの課題は、瞬間的な超高同時アクセスと在庫のオーバーセルを防ぐことです。

トラフィックの特徴

  • イベント開始前:大量のユーザーがページをリロードして待機
  • イベント開始の瞬間:QPSが平常時の100倍以上になる可能性
  • イベント終了後:トラフィックが急速に低下

多段階ピーク平滑化戦略

ユーザーリクエスト → CDN(静的ページ)→ ゲートウェイ(レートリミット)→ メッセージキュー(ピーク平滑化)→ 在庫サービス(引き当て)
戦略効果
フロントエンドボタン無効化 + ランダム遅延 + CAPTCHAボットの排除、リクエストの分散
CDN静的リソースのキャッシュページリクエストの90%を削減
ゲートウェイトークンバケットによるレートリミットシステムが処理可能なトラフィックのみ通過
メッセージキューリクエストをキューに入れ、非同期処理ピークの平滑化、データベースの保護
在庫サービスRedisによる事前引き当て + Luaのアトミック操作オーバーセルの防止、ミリ秒級の応答

フラッシュセールの核心原則

  1. 上流でできるだけブロックする:CDNで止められるものはアプリケーション層に到達させない
  2. 読み書きの分離:商品詳細ページはキャッシュ、注文だけがデータベースにアクセス
  3. 非同期処理:ユーザーが「購入」をクリックしたら直ちに「処理中」を返し、バックグラウンドで非同期処理
  4. フォールバック:レートリミット、サーキットブレーカー、グレードダウン、どの層に問題が発生してもPlan Bを用意

まとめ

システム設計は実践的なスキルであり、構造化された思考とトレードオフの取捨選択が鍵となります。

本章の主要なポイントを振り返りましょう:

  1. 4ステップフレームワーク:要件の明確化 → キャパシティ見積もり → アーキテクチャ設計 → 深掘り最適化。各ステップはスキップできない
  2. 封筒の裏の計算:正確である必要はなく、オーダーが分かればよく、アーキテクチャの決定を導く
  3. コアパターン:キャッシュ、シャーディング、メッセージキュー、CDN、レートリミット・サーキットブレーカーはシステム設計の「積み木」
  4. トレードオフ思考:完璧なソリューションはなく、現在の段階に適したソリューションがあるだけ。すべての決定の理由と代償を記録する
  5. 古典的な例:短縮URLサービスで基礎を練習し、フィードでプッシュ・プルモデルを練習し、フラッシュセールで高同時アクセスを練習する。この3つをマスターすれば応用が利く

関連資料