Day 2: スケーラビリティとパフォーマンス
今日学ぶこと
- 垂直スケーリングと水平スケーリングの違い
- ロードバランシングのアルゴリズム
- ステートレスとステートフルなサービス設計
- CAP定理の理解と適用
- レイテンシとスループットの関係
- 可用性とSLAの設計
垂直スケーリング vs 水平スケーリング
システムの処理能力を向上させる方法は2つあります。
flowchart TB
subgraph Vertical["垂直スケーリング(Scale Up)"]
V1["小さなサーバー\n4 CPU, 16GB RAM"]
V2["大きなサーバー\n64 CPU, 256GB RAM"]
end
subgraph Horizontal["水平スケーリング(Scale Out)"]
H1["サーバー 1"]
H2["サーバー 2"]
H3["サーバー 3"]
H4["サーバー N"]
end
V1 -->|"CPU・メモリ増強"| V2
style Vertical fill:#8b5cf6,color:#fff
style Horizontal fill:#22c55e,color:#fff
| 比較項目 | 垂直スケーリング | 水平スケーリング |
|---|---|---|
| 方法 | サーバーのスペックを上げる | サーバーの台数を増やす |
| 上限 | ハードウェアの限界がある | 理論上は無限に拡張可能 |
| コスト | 高スペックほど指数的に高額 | 比較的線形にコスト増加 |
| ダウンタイム | スペック変更時に必要な場合がある | ローリングアップデート可能 |
| 複雑さ | シンプル | データ整合性など課題が多い |
| 障害耐性 | SPOF(単一障害点)になる | 冗長性が高い |
| 適するケース | 初期段階・小規模システム | 大規模・高可用性が必要な場合 |
面接でのポイント: 「まず垂直スケーリングで始め、必要に応じて水平スケーリングに移行する」という段階的アプローチを説明できると良い評価を得られます。
ロードバランシング
ロードバランサーは、複数のサーバーにリクエストを分散する仕組みです。
flowchart LR
Client["クライアント"] --> LB["ロードバランサー"]
LB --> S1["サーバー 1"]
LB --> S2["サーバー 2"]
LB --> S3["サーバー 3"]
style LB fill:#3b82f6,color:#fff
style S1 fill:#22c55e,color:#fff
style S2 fill:#22c55e,color:#fff
style S3 fill:#22c55e,color:#fff
ロードバランシングアルゴリズム
| アルゴリズム | 仕組み | メリット | デメリット |
|---|---|---|---|
| Round Robin | 順番にリクエストを分配 | シンプル | サーバー性能の差を考慮しない |
| Weighted Round Robin | 重み付きで順番に分配 | 性能差に対応可能 | 重みの設定が必要 |
| Least Connections | 接続数が最少のサーバーに送る | 負荷を均等化 | 接続数の追跡が必要 |
| IP Hash | クライアントIPでサーバーを決定 | 同一クライアントは同一サーバー | 分散が偏る可能性 |
| Consistent Hashing | ハッシュリング上で最近接ノードへ | サーバー追加/削除の影響が小さい | 実装が複雑 |
Consistent Hashing
Consistent Hashingは、サーバーの追加・削除時にデータの再配置を最小限にする手法です。
flowchart TB
subgraph Ring["ハッシュリング"]
direction TB
N1["ノード A\n(位置: 0°)"]
N2["ノード B\n(位置: 120°)"]
N3["ノード C\n(位置: 240°)"]
end
K1["Key 1 → ノード B"] --> N2
K2["Key 2 → ノード C"] --> N3
K3["Key 3 → ノード A"] --> N1
style Ring fill:#3b82f6,color:#fff
style N1 fill:#8b5cf6,color:#fff
style N2 fill:#22c55e,color:#fff
style N3 fill:#f59e0b,color:#fff
ノードの追加時、影響を受けるのはリング上の隣接区間のデータのみです。全体の 1/N 程度のデータだけが移動します。
ステートレス vs ステートフル
flowchart TB
subgraph Stateful["ステートフル"]
C1["クライアント A"] -->|"常に同じサーバー"| SF1["サーバー 1\nセッション保持"]
C2["クライアント B"] -->|"常に同じサーバー"| SF2["サーバー 2\nセッション保持"]
end
subgraph Stateless["ステートレス"]
C3["クライアント"] --> LB2["ロードバランサー"]
LB2 --> SL1["サーバー 1"]
LB2 --> SL2["サーバー 2"]
SL1 --> Store["共有ストア\n(Redis等)"]
SL2 --> Store
end
style Stateful fill:#ef4444,color:#fff
style Stateless fill:#22c55e,color:#fff
| 比較項目 | ステートレス | ステートフル |
|---|---|---|
| セッション管理 | 外部ストア(Redis等) | サーバー内メモリ |
| スケーリング | 容易 | 困難(Sticky Session必要) |
| 障害耐性 | サーバー障害の影響小 | セッション消失のリスク |
| レイテンシ | 外部ストア参照のオーバーヘッド | ローカル参照で高速 |
面接での鉄則: 大規模システムでは常にステートレス設計を推奨しましょう。セッション情報は外部の分散キャッシュ(Redis)に保存します。
CAP定理
分散システムでは、以下の3つの特性のうち同時に2つまでしか保証できません。
flowchart TB
subgraph CAP["CAP定理"]
C["Consistency\n一貫性\nすべてのノードが同じデータを返す"]
A["Availability\n可用性\nすべてのリクエストにレスポンスを返す"]
P["Partition Tolerance\n分断耐性\nネットワーク分断時も動作する"]
end
C --- A
A --- P
P --- C
style CAP fill:#3b82f6,color:#fff
style C fill:#8b5cf6,color:#fff
style A fill:#22c55e,color:#fff
style P fill:#f59e0b,color:#fff
分散システムではネットワーク分断(P)は必ず起きるため、実質的には CP か AP の選択になります。
| 選択 | 特性 | 例 | ユースケース |
|---|---|---|---|
| CP | 一貫性 + 分断耐性 | ZooKeeper, HBase, MongoDB | 金融取引、在庫管理 |
| AP | 可用性 + 分断耐性 | Cassandra, DynamoDB, CouchDB | SNS、ショッピングカート |
CAP定理の実践的な理解
CAP定理は二者択一ではなく、スペクトラムとして理解するのが正確です。
強い一貫性 ←――――――――――――→ 結果整合性
(CP寄り) (AP寄り)
銀行口座 → ショッピングカート → SNSのいいね数 → DNS
レイテンシとスループット
| 概念 | 定義 | 単位 |
|---|---|---|
| レイテンシ | 1リクエストの処理にかかる時間 | ms(ミリ秒) |
| スループット | 単位時間あたりの処理量 | QPS、RPS、TPS |
よく使うレイテンシの目安
| 操作 | レイテンシ |
|---|---|
| L1キャッシュ参照 | 0.5 ns |
| L2キャッシュ参照 | 7 ns |
| メインメモリ参照 | 100 ns |
| SSD読み取り | 150 μs |
| HDD読み取り | 10 ms |
| 同一データセンター内通信 | 0.5 ms |
| カリフォルニア→東京 | 150 ms |
面接での使い方: 「ディスクアクセスはメモリの10万倍遅いため、頻繁にアクセスするデータはキャッシュに載せるべきです」のように、設計判断の根拠として使いましょう。
パーセンタイル
レイテンシは平均値ではなくパーセンタイルで測定します。
| パーセンタイル | 意味 | 目安 |
|---|---|---|
| P50(中央値) | 50%のリクエストがこの時間以内 | 通常の体験 |
| P95 | 95%のリクエストがこの時間以内 | ほぼ全てのユーザー体験 |
| P99 | 99%のリクエストがこの時間以内 | SLA目標に使う |
| P99.9 | 99.9%のリクエストがこの時間以内 | 最悪ケースの監視 |
可用性とSLA
可用性は「ナイン」で表現されます。
| 可用性 | ダウンタイム/年 | ダウンタイム/月 | 用途 |
|---|---|---|---|
| 99%(2ナイン) | 3.65日 | 7.31時間 | 開発環境 |
| 99.9%(3ナイン) | 8.77時間 | 43.8分 | 一般的なWebサービス |
| 99.99%(4ナイン) | 52.6分 | 4.38分 | ECサイト、SaaS |
| 99.999%(5ナイン) | 5.26分 | 26.3秒 | 金融、医療 |
可用性の計算
直列構成:全体の可用性 = 各コンポーネントの可用性の積
Web Server (99.9%) → App Server (99.9%) → DB (99.9%)
全体 = 0.999 × 0.999 × 0.999 = 99.7%
並列構成(冗長化):可用性の向上
1台の可用性: 99.9%
2台並列: 1 - (1 - 0.999)^2 = 99.9999%
まとめ
今日のポイント
| トピック | キーポイント |
|---|---|
| スケーリング | 垂直は簡単だが限界あり、水平はスケーラブルだが複雑 |
| ロードバランシング | 用途に応じてアルゴリズムを選択(面接ではConsistent Hashingが頻出) |
| ステートレス | 大規模システムではステートレス設計が必須 |
| CAP定理 | ネットワーク分断は不可避、CPかAPかはユースケース次第 |
| レイテンシ | パーセンタイル(P99等)で測定、メモリとディスクの差を意識 |
| 可用性 | ナインの数が1つ増えると10倍の努力が必要 |
設計判断のフレームワーク
1. まず垂直スケーリングで対応可能か検討
2. 限界に達したら水平スケーリングへ移行
3. ステートレス設計でスケールアウトを容易に
4. ロードバランサーで負荷を分散
5. CAP定理を意識してデータストアを選択
6. SLA要件に基づいて冗長化レベルを決定
練習問題
基礎レベル
問題: 以下のシナリオで垂直スケーリングと水平スケーリングのどちらが適切か、理由と共に答えてください。
- 個人ブログで月間1万PV
- ECサイトで年末セール時にトラフィックが10倍
- リアルタイム株価表示システム
中級レベル
問題: 可用性99.99%のシステムを設計するために、以下の構成の全体可用性を計算し、目標を達成するためにどのコンポーネントを冗長化すべきか提案してください。
- Webサーバー: 99.9%(2台構成の場合を計算)
- アプリケーションサーバー: 99.95%
- データベース: 99.99%
- キャッシュ: 99.95%
チャレンジレベル
問題: 「Twitterのようなソーシャルメディアプラットフォームを設計してください」という問題が出されました。以下の点について設計を説明してください。
- 読み取りと書き込みの比率は100:1
- DAUは1億人
- ロードバランシング戦略
- ステートレス設計のアプローチ
- CAP定理の観点からの設計判断
参考リンク
- System Design Primer - Scalability
- CAP Theorem Revisited
- Latency Numbers Every Programmer Should Know
次回予告
Day 3: データベース設計とスケーリング では、SQLとNoSQLの使い分け、インデックス設計、レプリケーション、シャーディングなど、データ層の設計について深く学びます。多くのシステム設計問題で核心となるトピックです。