人人都能学编程
English 开始学习
专项 · 系统设计第 1 课 / 共 5 课免费阅读

粗略估算 · 系统设计

一个有一百万用户的应用需要多少台服务器?

课程目录

为什么需要它

每一次系统设计都从规模开始。一个数据库还是五十个?数据是几个 GB 还是几百 TB?还不存在的系统没法测量,但一次快速的估算通常能把数量级估对,这就足以排除那些根本行不通的设计。面试也会考这个。

直觉理解

从已知推到所需,每次只做一步乘除:

  • 每天请求数 = 日活用户 × 每人请求数
  • 平均每秒 = 每天请求数 / 86,400(一天的秒数)
  • 峰值每秒 = 平均值 × 峰值系数。流量不是一条直线;如果有类似流量的实测系数就用它,没有就自己选一个,并把它写下来
  • 服务器数 = 峰值 / 一台服务器能扛的量,向上取整。「一台服务器能扛的量」来自压力测试,绝不能靠猜
  • 再加一台备用,这样坏一台也扛得住(常写作 N + 1)

存储也是同样的算法:每天的条数 × 每条大小 × 保留天数 × 副本数。

数字保持取整。86,400 接近 100,000,所以每天一百万次请求,大约就是每秒 10 次。重点是又快又大致准确,并且把你的假设写出来,让别人能纠正。

定义

QPS

Queries (requests) per second: the usual unit of load.
每秒查询(请求)数:衡量负载的常用单位。

峰值系数

How much busier the busiest time is than the average.
最忙的时候比平均水平忙多少倍。

N + 1

Running one more server than the load needs, so one failure doesn't overload the rest.
比负载需要的多运行一台服务器,这样坏一台也不会压垮其他的。

示例

从用户数到服务器数

动手试试

一百万日活用户,每人 20 次请求,峰值系数 3,压力测试显示一台服务器每秒能扛 200 次。

import math

daily = 1_000_000 * 20
average = daily / 86_400
peak = average * 3
servers = math.ceil(peak / 200) + 1
print(round(average), round(peak), servers)
输出
231 694 5
逐步执行
  1. L3每天两千万次请求。下划线只是让大数字更好读。
  2. L4平均每秒约 231 次。
  3. L5最忙的时候每秒约 694 次。
  4. L6694 / 200 = 3.47 → 4 台,再加 1 台备用。5

照片的存储

动手试试

每天两百万张照片,每张 2 MB,保存一年,存 3 份。

photos_per_day = 2_000_000
mb_each = 2
days = 365
copies = 3
tb = photos_per_day * mb_each * days * copies / 1_000_000
print(tb, "TB")
输出
4380.0 TB
逐步执行
  1. L5MB → TB 是除以一百万(按十进制单位)。
  2. L6几千 TB:一台数据库服务器肯定不行,需要对象存储。

常见错误

按平均值设计

流量有高峰。按平均值配置的系统,每天晚上都会扛不住。

凭猜测估服务器能力

「一台服务器每秒能扛一万次」完全取决于每次请求要做多少工作。对你自己的服务做压力测试。

忘了副本和增长

备份、副本和明年的增长,常常让存储需求翻好几倍。

小测验

1. 这段代码会输出什么?

per_day = 8_640_000
print(per_day / 86_400)
  1. A
    100.0
  2. B
    1000.0
  3. C
    10.0
查看答案

答案:A

8,640,000 / 86,400 = 每秒 100 次。

2. 为什么在峰值所需之外再多加一台服务器?

  1. A这样坏一台服务器服务也能撑住
  2. B因为服务器只能是奇数台
  3. C为了让负载均衡器更快
查看答案

答案:A

N + 1:任意坏掉一台,剩下的容量也够用。

动手练习

3 道练习,分三层:先预测程序的输出,再按新需求改程序,最后从零写一个。代码在浏览器里运行,提交马上判题。

  1. 预测输出取整的数

    准确写出它打印的内容。

  2. 改需求每一份都要算

    storage_tb 忘了每张照片要存 copies 份。修正它。

  3. 从零写要几台服务器?

    写一个 servers_needed(daily_users, per_user, peak_factor, per_server):

    1. 峰值每秒 = daily_users × per_user / 86,400 × peak_factor
    2. 负载所需的服务器 = 峰值 / per_server,向上取整,但至少 1 台
    3. 返回这个数再加 1 台备用
    servers_needed(1_000_000, 20, 3, 200)   # 5

在互动课里练这一课

打开互动课,这些例子都能直接改、直接运行,练习题提交马上判题。免费开始,不用注册。

本课术语

术语中文英文定义
QPS每秒请求数Requests per second.
Peak factor峰值系数How much busier the peak is than the average.
N + 1N + 1 冗余One spare server beyond what the load needs.