規模の見積もり — 設計は数字から始まる
「1 日 10 万人が使うサービスを設計してください」と言われたとき、最初にやることは構成図を描くことではありません。数字を出すことです。
秒あたり何リクエストか。データは 1 年で何ギガバイトになるか。これが出ると、議論が終わります。キャッシュが要るかどうかも、データベースを分けるかどうかも、数字が決めるからです。数字を出さずに構成を並べると、必要のない部品を足した設計になります。
この章で学ぶこと
- 利用者数から秒あたりのリクエスト数を導く手順
- ピークは平均の何倍かの置き方
- 読み書きの比が構成を分けること
- 1 レコードの大きさからデータ量と帯域を出す
- 桁が合っていればよいという精度の考え方
- 「1 台で足りる」と言い切れる条件
計算量 の「桁で考える」発想を前提にします。あちらが手数の桁を数えたのに対し、この章では負荷とデータ量の桁を数えます。
この章で扱わないこと
見積もった負荷をどう捌くかは次章以降が扱います。台数を増やす方向は スケールの方向、壊れたときの話は 可用性と冗長化、データを分ける話は データの分散 です。
クラウドの具体的なインスタンス選定と料金試算は AWS 実践ガイド が扱います。
なぜ数字から始めるのか
「キャッシュを入れるべきか」という問いには、それだけでは答えられません。秒あたり 5 リクエストなら要りません。5,000 なら要ります。同じ問いの答えが、数字によって逆になります。
設計の議論が長引くときは、たいてい全員が別の規模を想像しています。数字を先に置くと、その食い違いが消えます。
見積もりの目的は当てることではありません。構成の選択肢を減らすことです。
秒あたりのリクエスト数を出す
出発点は利用者数です。ここから 3 段階で降ります。
| 段階 | 求めるもの | 計算 |
|---|---|---|
| 1 | 1 日のリクエスト数 | 1 日の利用者数 × 1 人あたりの回数 |
| 2 | 平均のリクエスト毎秒 | 1 日のリクエスト数 ÷ 86,400 |
| 3 | ピークのリクエスト毎秒 | 平均 × ピーク倍率 |
1 日は 86,400 秒です。この数字だけは覚えておくと計算が速くなります。
const SECONDS_PER_DAY = 86_400;
type Workload = {
dailyUsers: number; // 1 日の利用者数
actionsPerUser: number; // 1 人が 1 日に起こすリクエスト数
peakFactor: number; // ピークが平均の何倍か
};
function requestsPerSecond(w: Workload) {
const perDay = w.dailyUsers * w.actionsPerUser;
const average = perDay / SECONDS_PER_DAY;
return { perDay, average, peak: average * w.peakFactor };
}
const r = requestsPerSecond({ dailyUsers: 100_000, actionsPerUser: 20, peakFactor: 10 });
console.log(`1 日 ${r.perDay.toLocaleString()} リクエスト`);
console.log(`平均 ${r.average.toFixed(1)} rps / ピーク ${r.peak.toFixed(0)} rps`);
1 日 2,000,000 リクエスト
平均 23.1 rps / ピーク 231 rps
1 日 10 万人という数字の印象に対して、平均は毎秒 23 リクエストです。この規模なら、アプリケーションサーバー 1 台でも処理できる範囲に入ります。判断が変わるのはピークの側です。
ピークは平均の何倍か
利用が 24 時間均等に散ることはありません。消費者向けのサービスなら夜に寄り、業務システムなら平日の日中に寄ります。
**倍率は測れるなら測ります。**既存サービスならアクセスログの時間帯別集計がそのまま使えます。新規で測れないときは、仮定を明示したうえで置きます。
| 状況 | 置き方 |
|---|---|
| 利用が 1 日に広く散る (業務システム) | 平均の 3 倍程度 |
| 特定の時間帯に寄る (消費者向け) | 平均の 5〜10 倍 |
| 開始時刻が決まっている (チケット販売、抽選) | **平均は意味を持たない。**秒あたりの上限を別に見積もる |
**この表の倍率に出典はありません。**置き始めの値として使い、実測が取れたら差し替えます。1 時間の平均でならした値と、その中の 1 分間の山でも数字は変わるので、どの粒度でならしたかも一緒に書きます。
3 行目が重要です。売り出し開始と同時に全員が来る種類の負荷では、1 日の平均から掛け算しても実態に届きません。「何人が同じ 1 秒に来るか」を直接置きます。
倍率を置いたら、**それが仮定であることを設計文書に書きます。**後から実測とずれたとき、どの前提が外れたのかを追えるようにするためです。
読み書きの比を出す
同じリクエスト毎秒でも、読み取りと書き込みでは逃がし方が違います。
- **読み取りは散らせます。**キャッシュに載せられますし、複製したデータベースへ振り分けられます
- **書き込みは散らせません。**正しい順序で 1 か所に集める必要があります
だから合計だけでなく比率を出します。閲覧中心のサービスなら読み書きは 100 対 1、あるいはそれ以上に読み取りへ偏ります。
先ほどのピーク 231 rps が 100 対 1 なら、書き込みは毎秒 2.3 リクエストです。この数字が見えると、「書き込みのために何かする必要はまだない」と言い切れます。
読み取りをどう散らすかは スケールの方向、書き込みを分けたくなったときに何が崩れるかは データの分散 が扱います。
データ量と帯域を出す
負荷の次はデータです。1 レコードの大きさ × 件数で求めます。
**行が増える速さは、書き込みリクエストの数とは限りません。**業務データの行は書き込みの回数だけ増えますが、1 リクエストにつき 1 行のアクセスログを残すなら、そちらは読み取りも含めた総数だけ増えます。対象ごとに分けて数えます。
const KB = 1_000;
const GB = 1_000_000_000;
function storagePerYear(rowsPerDay: number, bytesPerRow: number, overhead: number) {
const rawPerYear = rowsPerDay * bytesPerRow * 365;
return { rawGB: rawPerYear / GB, actualGB: (rawPerYear * overhead) / GB };
}
// 業務データ: 書き込み 1 日 2 万件 (200 万リクエストの 1%)、1 行 1 KB
const biz = storagePerYear(20_000, 1 * KB, 3);
// アクセスログ: 全リクエストを 1 行ずつ、1 行 0.5 KB
const log = storagePerYear(2_000_000, 0.5 * KB, 3);
console.log(`業務データ 素 ${biz.rawGB.toFixed(1)} GB/年 → 実容量 ${biz.actualGB.toFixed(0)} GB/年`);
console.log(`アクセスログ 素 ${log.rawGB.toFixed(0)} GB/年 → 実容量 ${log.actualGB.toFixed(0)} GB/年`);
業務データ 素 7.3 GB/年 → 実容量 22 GB/年
アクセスログ 素 365 GB/年 → 実容量 1095 GB/年
**50 倍違います。**同じサービスの中でも、対象によって容量計画は別の話になります。業務データは 1 台に載りますが、ログは保存期間を決めないと増え続けます。
**素のデータ量をそのまま容量計画に使わないでください。**インデックス、複製、バックアップ、断片化で膨らみます。ここでは 3 倍を掛けています。この倍率に出典はなく、構成しだいで変わりますが、2〜3 倍を見ておくと大きく外しません。インデックスが容量を食う仕組みは インデックス が扱っています。
帯域も同じ形で出ます。応答が 1 件 50 KB なら、ピーク 231 rps で毎秒 11.6 メガバイト、およそ 92 メガビット毎秒です。画像や動画を返すサービスでは、この数字が最初に頭打ちになることがあります。
桁が合っていればよい
見積もりの精度をどこまで上げるかには基準があります。判断が変わる粒度までです。
- **2 倍の誤差は設計を変えません。**231 rps が実は 400 rps でも、構成は同じです
- **10 倍の誤差は設計を変えます。**231 rps と 2,300 rps では、要る台数もキャッシュの要否も変わります
だから「1 人が 1 日に 20 回か 25 回か」で悩む意味はありません。20 と 200 のどちらかを間違えないことに労力を割きます。
この感覚は 計算量 と同じです。O(n) と O(n²) の差は決定的でも、2n と 3n の差は判断を変えません。係数ではなく桁を見ます。
「1 台で足りる」と言い切れる条件
見積もりの成果は、足りない構成を見つけることだけではありません。要らない構成を捨てられることも同じくらい価値があります。
次の 3 つがすべて満たされるなら、1 台構成で始められます。
| 見るもの | 目安 |
|---|---|
| ピークの負荷 | 1 台の処理能力に対して余裕があるか。使い切る前提で組まない |
| データ量 | 1 台のディスクに載るか。載っても、増加の速度で何年もつか |
| 止まってよい時間 | 落ちたときに復旧まで待てるか。ここが待てないなら、負荷とは無関係に冗長化が要ります |
3 行目に注意してください。**台数を増やす理由は負荷だけではありません。**負荷の面では 1 台で足りていても、止められない要件があるなら 2 台になります。これは可用性の問題で、可用性と冗長化 が扱います。
**「将来増えるかもしれない」は、今から分散させる理由になりません。**必要なのは、増えたときに水平に増やせる形にしておくことです。作っておくことと、今そうしておくことは別です。
判断の手順
見積もりを求められたら、この順に埋めます。
- 利用者数と 1 人あたりの回数を置く — どちらも仮定でよい。ただし仮定だと明示する
- 平均のリクエスト毎秒を出す — 1 日の合計 ÷ 86,400
- ピーク倍率を掛ける — 測れるなら測る。開始時刻が決まっている負荷は平均から掛けない
- 読み書きの比を出す — 読み取りと書き込みで打ち手が変わる
- データ量を出す — 1 レコードの大きさ × 件数 × 2〜3 倍
- 1 台で足りるかを判定する — 負荷・容量・止まってよい時間の 3 つを見る
- 足りない箇所だけ構成を足す — 足りている箇所には足さない
**7 が結論です。**見積もりは、構成を足すためではなく、どこに足さないかを決めるために行います。
よくある誤解
「見積もりは正確でなければ意味がない」 — 目的は当てることではなく選択肢を減らすことです。桁が合っていれば、要る構成と要らない構成は分かれます。正確さを求めて時間を使うより、仮定を明示して先へ進みます。
「ピークは平均の 2 倍くらい」 — 分野によりますが、消費者向けでは 5〜10 倍になることがあります。しかも 1 時間の平均でならした値と、その中の 1 分間の山はさらに違います。どの粒度でならした数字かを意識してください。
「利用者数が 10 倍になったら台数も 10 倍」 — 比例するのはリクエストを処理する部分だけです。データベースは容量と書き込みで先に限界が来ますし、キャッシュが効けばむしろ台数は 10 倍要りません。部位ごとに別の曲線を描きます。
確認問題
問 1. 1 日の利用者が 30 万人、1 人あたり 1 日 10 リクエスト、ピークは平均の 6 倍とします。ピーク時のリクエスト毎秒はおよそいくつですか。
およそ 210 rps です。
- 1 日のリクエスト数 = 30 万 × 10 = 300 万
- 平均 = 300 万 ÷ 86,400 ≒ 34.7 rps
- ピーク = 34.7 × 6 ≒ 208 rps
桁で答えれば十分です。「200 前後」と言えていれば、この先の議論は変わりません。
**ただし、この数字だけでは台数を決められません。**1 台が何リクエスト毎秒を捌けるかは、1 リクエストあたりの処理時間で決まります。10 ミリ秒で終わる処理と 500 ミリ秒かかる処理では 50 倍違います。見積もりで出るのは要求の側の桁で、供給の側は測って初めて分かります。
問 2. 上の見積もりで、読み書きの比が 50 対 1 でした。書き込みのピークはいくつで、この数字から何が言えますか。
書き込みのピークはおよそ 4 rps です (208 ÷ 51 ≒ 4)。
言えることは 2 つあります。
- **書き込みのために分散の仕組みを入れる必要はありません。**毎秒 4 件は、ふつうのデータベース 1 台にとって小さい負荷です
- **手を打つなら読み取り側です。**残り 204 rps が読み取りなので、効果が出るのはキャッシュや複製です
合計だけを見ていると、この判断ができません。「208 rps だからデータベースを分割しよう」は、書き込みが 4 rps だと分かった時点で不要になります。
問 3. 「今は小規模だが、3 年後には 100 倍になる見込みがある」と言われました。今どう設計しますか。
今は今の規模で組み、増えたときに水平に増やせる形にしておきます。
100 倍を前提にした構成を今作ると、使われない部品の運用コストを 3 年払うことになります。それでも今やっておく価値があるのは、あとから変えるのが高くつく決定だけです。
| 今やること | 理由 |
|---|---|
| サーバーに状態を持たせない | あとから状態を追い出すのは、台数を増やすより手間がかかる |
| データを分ける基準になりうるキーを決めておく | 分割の設計はデータの持ち方に依存する |
| 負荷とデータ量を計測できるようにする | 100 倍が本当に来るのかを判断する材料になる |
逆に、台数を増やす・複製を足す・キャッシュを挟むといった操作は、必要になってからで間に合います。
まとめ
- 設計は数字から始めます。同じ問いの答えが規模によって逆になるからです
- 利用者数 × 1 人あたりの回数 ÷ 86,400 で平均のリクエスト毎秒が出ます
- **ピーク倍率は仮定として明示します。**開始時刻が決まっている負荷は平均から掛けません
- 読み書きの比を出します。読み取りは散らせて、書き込みは散らせません
- データ量は素の値の 2〜3 倍を見ます。インデックスと複製が乗るからです
- **精度は桁が合っていれば足ります。**2 倍の誤差は設計を変えず、10 倍は変えます
- 見積もりの成果は、要らない構成を捨てられることです