关于 back-of-the-envelope
帮助系统设计者进行数量级估算的技能,将流量、存储和带宽等模糊规模转化为可用于架构决策的近似数字。附带 Python 计算脚本,用于核对估算链中的算术。
主要功能
- 01估算 QPS 与峰值负载
- 02计算存储量和带宽
- 03推算服务器数量与内存
- 04记录假设并统一单位
- 05使用脚本核验计算
适用场景
- 01判断单节点数据库是否够用
- 02评估缓存或分片需求
- 03估算数据保留期所需容量
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ proyecto26/ system-design-skills --skill back-of-the-envelope安装后在 Claude Code 中输入/back-of-the-envelope确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
expected_outputs/twitter_scale.jsonreferences/estimation-recipes.mdnumbers-to-remember.mdscripts/botec.pytest_botec.py详细介绍
粗略估算(BOTEC)
把模糊的规模描述(如“高流量”“海量数据”)转化为几个能够决定设计的具体数字。BOTEC 是快速、近似的计算,用于可行性检查,而非追求精确。重点在于计算过程和方向是否正确:它们能告诉你何时单个数据库不够用、何时必须缓存,以及写入峰值何时需要队列。
面向 1k QPS 的设计和面向 1M QPS 的设计是两种不同的系统。10 GB 可以放进 RAM;10 TB 则需要分布式存储。先估算,再选择。
何时使用
在任何设计的第 2 步(紧接需求之后)使用;每当某个选择取决于规模时也要使用:例如确定读写路径的容量、决定采用分片还是单节点、说明缓存的必要性,或检查拟议组件能否承受负载。
何时不使用
不要追求精确,也不要为每个微服务都建模——这与该方法背道而驰。不要估算不会影响决策的内容(YAGNI)。大胆取整:“99,987 / 9.1”就是“100,000 / 10”。务必标注单位并写明假设。
先明确条件
估算的质量取决于输入。先确定:
- DAU/MAU,以及其中每天活跃的比例。
- 每位用户每天的操作数(发帖、读取、消息……)。
- 读写比例——哪条路径占主导。
- 对象大小——每条记录和每个媒体文件的大小。
- 保留期限——数据保存多久(决定总存储量)。
- 峰值系数——峰值通常约为平均值的 2 倍;某些工作负载的波动更大。
核心估算(计算方法)
每项都用一组乘除法完成计算。完整的计算示例和 CPU 时间推导见 references/estimation-recipes.md。
- QPS =
DAU × actions_per_user_per_day ÷ 86,400。峰值 QPS ≈ 2 × QPS (注明峰值系数)。 - 每日存储量 =
writes_per_day × avg_object_size。总量 =storage/day × retention_days(注意十进制与二进制的区别;存储按十进制单位出售)。 - 带宽 =
QPS × payload_size(分别计算读和写;通常出口流量占主导且会产生费用)。 - 服务器数量 =
peak_QPS ÷ per_server_QPS。用下文的单服务器速率作为除数。 - 并发连接数 / 内存 =
concurrent_users × per_connection_cost; 检查工作集能否放入 RAM(否则就是受 IO 限制、依赖磁盘的设计)。
重要数值
这些是值得记住的参考值,让你无需查资料也能进行估算。延迟、服务器规格、请求类型、2 的幂次和 9 的数量等完整表格见
references/numbers-to-remember.md——需要具体数值时再查阅。
最影响决策的两个参考值:
| 项目 | 经验法则 |
|---|---|
| 单个 SQL/RDBMS 节点 | ~1,000 QPS |
| 键值存储节点 | ~10,000 QPS |
| 缓存服务器(Redis/Memcached) | ~100,000–1M QPS |
| 一个现代 CPU 核心 | ~1,000 个简单请求/秒 → 一台 64 核机器约为 64k 请求/秒 |
| 读取 1 MB:内存、SSD、磁盘 | ~μs vs tens–hundreds of μs vs ms(内存 ≫ SSD ≫ 磁盘) |
关注数量级,而非精确数值。 CPU 密集型操作耗时约为基准的 1 倍,内存密集型约为 10 倍,IO 密集型约为 100 倍。影响架构选择的是这个比例,而非小数点后的数值。
注意事项
根据这些示例以及估算容易产生误导的方式提炼而成。
应该
- 应该将数字四舍五入到 1 位有效数字,并按数量级进行推理——比例(1× / 10× / 100×)才会影响架构,而不是小数位。
- 应该按峰值而非平均值进行容量规划。 在选择容量前,先说明峰值倍数(≈2× 是常见默认值;突发性工作负载的倍数会更高)。
- 应该分别估算读和写——95% 的读请求比例与写入峰值会将设计引向截然不同的方向。
- 应该标注单位并写下假设,避免“GB”含义不明,并确保输入变更时能够重新核对整个计算过程。
不应该
- 不要保留虚假的精度。 小数位暗示了输入数据无法支撑的置信度;“99,987”就是“100,000”。
- 不要把单台服务器的处理速率当成通用标准。“SQL 每秒 1k 次查询”是针对点查询的经验法则;范围扫描、连接和较大的负载可能会差 10×——可用它估算数量级,之后再用实际基准测试验证。
- 不要混淆二进制与十进制。 RAM 使用二进制单位;存储和网络的营销标示使用十进制单位——用于估算时两者足够接近,但前提是明确标注单位。
- 不要计算那些不会影响决策的内容。 如果一个数字不会改变架构,就跳过它(YAGNI)。
图示
估算通常用表格呈现,而不是图示——将数字和假设直接列出。当推导出的数字迫使结构发生变化时(例如,“300k QPS > 单个 DB → 分片 / 添加副本”),应将其纳入架构图本身;绘制这些数字所支持的设计时,请使用 architecture-diagram 技能。
相关构建模块
requirements-scoping— 本技能依赖它提供输入(DAU、操作速率、比例、SLA),并将这些输入转化为数字。data-storage— 本技能的结果会输入到它:此处计算的存储总量和分片数会影响它对 SQL/NoSQL 和分区方式的选择。caching— 本技能的结果会输入到它:此处估算出的高读请求比例或热点工作集,是使用缓存的理由。scaling-evolution— 本技能的结果会输入到它:当估算值超过单节点上限时,该上限就是接下来需要规划应对的瓶颈。system-design— 推理循环的所属概念在此处;它负责协调,并在第 2 步调用本技能。
参考资料
references/numbers-to-remember.md— 速查表:延迟表、典型服务器规格、单服务器 QPS 速率、受 CPU/内存/IO 限制的请求类型、2 的幂次、可用性 9。需要具体数值时查阅。references/estimation-recipes.md— 完整示例(Twitter 规模的 QPS + 存储、64 核 → 64k req/s 的 CPU 时间推导、带宽和服务器数量估算)。可查看完整的端到端推导过程。
脚本
如需确定性地检查容量规划计算链(精确计算真正派上用场的地方),请运行计算器,而不是手动计算:
scripts/botec.py—python3 scripts/botec.py --dau 150e6 --actions 2 --peak 2 --obj-bytes 1e6 --media-frac 0.10 --retention-days 1825 --server-qps 1000 --json→ QPS、峰值、每日及总存储量、带宽、服务器数量。每服务器 QPS 的默认值遵循上述经验法则(可通过--server-qps覆盖)。scripts/test_botec.py— 断言计算器的结果与expected_outputs/twitter_scale.json(完整的 Twitter 示例)一致,确保说明中的计算方法与数学计算结果不会偏离。