关于 system-design
system-design 是面向系统架构师与工程师的分布式系统设计框架,适用于新服务设计、架构评审和容量估算。它强调先明确需求,再通过估算、组件取舍及可靠性运维规划形成设计。
主要功能
- 01四步设计流程
- 02容量与资源估算
- 03分布式系统构建模块
- 04数据库扩展策略
- 05常见系统设计模式
- 06可靠性与运维规划
适用场景
- 01规划新服务架构
- 02评审系统设计与取舍
- 03估算容量、存储和带宽
- 04准备系统设计讨论
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ wondelai/ skills --skill system-design安装后在 Claude Code 中输入/system-design确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/building-blocks.mdcommon-designs.mddatabase-scaling.mdestimation-numbers.mdfour-step-process.mdreliability-operations.md详细介绍
系统设计框架
一种用于设计大规模分布式系统的结构化方法。在架构设计新服务、评审设计、估算容量或准备系统设计讨论时,应用这些原则。
核心原则
从需求出发,而不是从解决方案出发。 在了解约束条件之前就开始设计架构,会导致系统过度设计或设计不足。可扩展的系统由充分理解的构建模块(负载均衡器、缓存、队列、数据库、CDN)组合而成——关键在于选择合适的模块,依据估算确定其规模,并承担每项选择带来的权衡。
评分
目标:10/10。 根据八项快速诊断中满足的项数为设计评分——score = round(passed / 8 × 10):9-10 = 全部或几乎全部通过——明确的需求、切实的估算、冗余、明确的数据库扩展与缓存策略、通过队列实现异步处理、监控和部署计划,并说明权衡;5-6 = 设计可行,但缺少估算、冗余或运维方面的内容;<=3 = 在明确需求或估算之前就提出了架构。始终说明当前分数,指出未通过的诊断项,并为每项给出具体的改进措施。
系统设计框架
构建可靠、可扩展的分布式系统的六个方面:
1. 四步流程
核心概念: 每项设计都分为四个阶段:(1)理解问题并明确范围,(2)提出高层设计并获得认同,(3)深入分析关键组件,(4)总结权衡并提出未来改进。
有效原因: 缺乏结构时,设计要么过于抽象,要么陷入过早的细节。四步流程按比例分配时间——先勾勒整体,再深入关键部分。
关键见解:
- 第 1 步(约 5-10 分钟):提出澄清问题,确定功能和非功能需求,以及一致认可的规模(DAU、QPS、存储)
- 第 2 步(约 15-20 分钟):绘制高层架构图,包含 API、服务、数据存储和数据流箭头
- 第 3 步(约 15-20 分钟):详细设计 2-3 个最困难或最关键的组件
- 第 4 步(约 5 分钟):总结权衡、瓶颈和未来改进
- 切勿跳过第 1 步——范围不明确会浪费后续所有工作;务必就假设达成明确共识
代码应用:
| 场景 | 模式 | 示例 |
|---|---|---|
| 新服务启动 | 编码前准备一页涵盖全部四步的设计文档 | 需求、API 契约、数据模型、容量估算,然后开始实施 |
| 架构评审 | 按顺序引导评审者了解各个步骤 | 范围、架构图、风险最高组件的深入分析、待解问题 |
| 事故复盘 | 通过四步视角追溯故障 | 哪项需求被遗漏了?哪个模块发生了故障?我们在哪项权衡上付出了代价? |
端到端开展设计时,请参阅 references/four-step-process.md,了解各阶段的时间分配、澄清问题示例,以及四个步骤各自的实用建议。
2. 粗略估算
核心概念: 在确定架构之前,使用 2 的幂、延迟数据和简单的算术来估算 QPS、存储、带宽和服务器数量。
为什么有效: 估算可以避免过度配置(浪费资金)和配置不足(负载过高时发生故障)。2 分钟的计算就能省去数周的返工。
关键要点:
- 2 的幂:2^10 ≈ 1 千,2^20 ≈ 1 百万,2^30 ≈ 10 亿,2^40 ≈ 1 万亿
- 延迟:内存读取约 100 ns,SSD 读取约 100 us,磁盘寻道约 10 ms,同一数据中心内往返约 0.5 ms,跨洲约 150 ms
- 可用性“几个 9”:99.9% = 每年停机 8.77 小时;99.99% = 每年停机 52.6 分钟
- QPS:DAU x 每日操作次数 / 86,400 秒;峰值通常是平均值的 2-5 倍
- 存储:每日记录数 x 每条记录的大小 x 保留时间
- 大胆取整——目标是估算数量级,而非精确值
代码应用:
| 场景 | 模式 | 示例 |
|---|---|---|
| 容量规划 | 估算 QPS,再乘以增长系数 | 100M DAU x 5 次操作 / 86400 = 平均约 5,800 QPS,峰值约 30K |
| 存储预算 | 单条记录大小 x 数量 x 保留时间 | 每天 500M 条推文 x 300 字节 x 365 天 = 每年约 55 TB |
| SLA 定义 | 将几个 9 换算为允许的停机时间 | 四个 9 = 每年停机约 52 分钟 |
估算系统规模时,请参阅 references/estimation-numbers.md——其中包含完整的延迟表、可用性“几个 9”表,以及 QPS、存储和带宽的计算示例。
3. 构建模块
核心概念: 可扩展系统由一套标准工具组成:DNS、CDN、负载均衡器、反向代理、应用服务器、缓存、消息队列和一致性哈希。
为什么有效: 每个模块都以一种成本换取另一种成本(缓存以牺牲新鲜度换取读取速度;队列以牺牲延迟换取解耦),因此只在出现相应瓶颈时才引入模块——一开始就全部添加,只会增加故障模式。
关键要点:
- 负载均衡器:L4(传输层——速度快、简单)与 L7(应用层——可感知内容并进行路由)
- 缓存层:客户端、CDN、Web 服务器、应用(Redis/Memcached)、数据库查询缓存
- 缓存策略:旁路缓存(由应用管理)、读穿透、直写(同步)、回写(异步)
- 消息队列(Kafka、RabbitMQ、SQS):将生产者与消费者解耦、吸收流量峰值、支持异步处理
- 一致性哈希:在节点发生变化时,以最小的重新分配量将键分布到各节点
代码应用:
| 场景 | 模式 | 示例 |
|---|---|---|
| 读取密集型工作负载 | 在数据库前使用 Redis 旁路缓存 | 使用 TTL 缓存用户资料;写入时使缓存失效 |
| 流量峰值 | 在 API 和工作进程之间使用消息队列 | 将图像调整大小任务加入队列;工作进程按自身速度拉取任务 |
| 全球用户 | 使用 CDN 提供静态资源 | 从边缘节点提供 JS/CSS/图片;源站仅提供 API |
| 负载不均 | 使用一致性哈希分配分片 | 添加一个节点时,只会迁移约 1/n 的键 |
选择组件时,请参阅 references/building-blocks.md——了解 DNS、CDN、负载均衡器、缓存策略、消息队列和一致性哈希各自的工作方式,以及何时引入它们。
4. 数据库设计与扩展
核心概念: 根据数据形态和访问模式选择 SQL 或 NoSQL;先纵向扩展,再在达到纵向扩展上限时进行横向扩展(复制和分片)。
为何有效: 数据库通常是第一个瓶颈。理解复制、分片和反规范化之间的权衡,可以推迟代价高昂的架构重构,并让增长更有计划。
关键要点:
- 纵向扩展更简单,但有上限;横向扩展更复杂,但几乎没有上限
- 复制:读多场景采用主从模式(一主多从);多地域写入采用多主模式
- 分片:基于哈希(分布均匀,但范围查询困难)、基于范围(范围查询容易,但有热点风险)、基于目录(灵活,但需要额外查询)
- SQL 适用于 ACID 事务、联接和结构固定的模式;NoSQL 适用于灵活的模式、横向扩展和极高的写入吞吐量
- 反规范化以存储和写入复杂度换取读取速度——适用于读取占主导且数据很少变化的场景
- 名人/热点问题:一个热点分片需要二次分区或缓存层
代码应用:
| 场景 | 模式 | 示例 |
|---|---|---|
| 读多型 API | 主从模式,搭配只读副本 | 读取请求发往副本,写入请求发往主节点;接受轻微延迟 |
| 大规模用户数据 | 根据 user_id 进行哈希分片 | hash(user_id) % num_shards;分片分布均匀且彼此独立 |
| 分析仪表盘 | 反规范化的物化视图 | 每晚预先联接并聚合;从物化表提供数据 |
当数据库成为瓶颈时,请参阅 references/database-scaling.md,了解复制拓扑、三种分片策略的比较、反规范化的权衡,以及 SQL 与 NoSQL 选择指南。
5. 常见系统设计
核心概念: 大多数系统都是少数几种经典设计的变体:URL 缩短器、速率限制器、通知系统、新闻推送、聊天、搜索自动补全、网络爬虫和唯一 ID 生成器。
为何有效: 在脑海中建立一套经典设计,可以帮助你识别新问题与哪些模式相似,并在此基础上进行调整,而不是从头开始设计。
关键要点:
- URL 缩短器:Base62 编码、键值存储、301 与 302 重定向的权衡(缓存与分析)
- 速率限制器:在网关处使用令牌桶或滑动窗口;返回 429 和 Retry-After
- 新闻推送:写时扇出(发布时推送)与读时扇出(读取时拉取);名人场景采用混合模式
- 聊天:使用 WebSocket 传递实时双向消息,使用队列保证消息送达,使用心跳在线状态服务
- 自动补全:保存热门查询的前 k 项的字典树;预先计算并缓存热门前缀
- 网络爬虫:使用 URL 队列进行广度优先搜索,遵守礼貌规则(robots.txt、按域名限制速率),通过内容哈希去重
- 唯一 ID:UUID(简单,无需协调)与 Snowflake(64 位、按时间排序、支持数据中心)
代码应用:
| 场景 | 模式 | 示例 |
|---|---|---|
| 短链接服务 | 对自增 ID 或哈希进行 Base62 编码 | https://short.ly/a1B2c3 映射到一个键值行 |
| API 防护 | 在网关处使用令牌桶 | 每个密钥每分钟 100 个令牌;持续补充;超限时返回 429 |
| 社交推送 | 混合扇出 | 预先计算粉丝数少于 10K 的账号的推送;在读取时合并名人帖子 |
当问题与经典设计相似时,请参阅 references/common-designs.md,了解 URL 缩短器、速率限制器、新闻推送、聊天、自动补全、网络爬虫和唯一 ID 生成器的完整讲解。
6. 可靠性与运维
核心概念: 系统的好坏取决于它保持运行、恢复故障和接受观测的能力。健康检查、监控、日志记录和部署策略都是一等设计要素,而非事后补充。
为何有效: 生产系统会以架构图无法预见的方式发生故障。运维就绪程度——指标、告警、回滚计划、冗余——决定了一次故障只是短暂波动,还是会造成服务中断。
关键要点:
- 健康检查:存活检查(进程是否还在运行?)和就绪检查(能否处理流量?)——Kubernetes 会同时使用两者
- 可观测性的三大支柱:指标(Prometheus、Datadog)、日志记录(ELK、CloudWatch)、追踪(Jaeger、Zipkin)
- 部署方式:滚动部署(逐步进行)、蓝绿部署(在相同环境间即时切换)、金丝雀发布(先向一小部分用户发布)
- 灾难恢复:RPO(可接受的数据丢失量)和 RTO(可接受的恢复时间)决定备份和故障转移策略
- 多数据中心:主动-被动(故障转移)或主动-主动(需要数据同步和冲突解决)
- 自动扩缩容:根据 CPU、内存、队列深度或自定义指标进行扩缩容;始终设置最小和最大实例数
代码应用:
| 场景 | 模式 | 示例 |
|---|---|---|
| 零停机部署 | 带健康检查门控的蓝绿部署 | 检查通过后切换到绿色环境;保留蓝色环境以便立即回滚 |
| 渐进式发布 | 使用指标对比的金丝雀发布 | 将 5% 的流量导向新版本;对比错误率和延迟;然后继续发布或回滚 |
| 数据安全 | 定义 RPO/RTO,并据此实施 | RPO 为 1 小时 = 每小时备份;RTO 为 5 分钟 = 自动故障转移 |
在为生产环境加固系统时,请参阅 references/reliability-operations.md——其中介绍了健康检查模式、可观测性的三大支柱、部署策略、灾难恢复(RPO/RTO)和自动扩缩容。
常见错误
| 错误 | 失败原因 | 修正方法 |
|---|---|---|
| 先设计架构,再明确需求 | 解决了错误的问题,忽略了约束条件 | 用前 5-10 分钟明确范围:功能、规模、SLA |
| 没有进行估算 | 资源配置可能相差几个数量级 | 选择组件前估算 QPS、存储和带宽 |
| 单点故障 | 一个组件就能导致整个系统瘫痪 | 每一层都要冗余:多服务器、多 AZ、多区域 |
| 过早分片 | 在确有需要前就引入巨大的运维复杂性 | 优先纵向扩展,再使用只读副本并积极缓存,最后才分片 |
| 缓存没有失效机制 | 过期数据会导致错误和混乱 | 定义 TTL;使用旁路缓存,并在写入时显式失效 |
| 所有调用都采用同步方式 | 一个缓慢的服务会将延迟级联到所有调用方 | 对非延迟关键路径使用队列;为同步调用设置超时 |
| 忽略热点 | 某个分片或键负载过重,其他分片或键却处于空闲状态 | 检测热点键;增加二级分区或本地缓存 |
| 没有监控或告警 | 用户会比你更早发现故障 | 从第一天起就采集指标、日志和追踪数据 |
快速诊断
| 问题 | 如果否 | 行动 |
|---|---|---|
| 是否列出了功能和非功能需求? | 设计建立在假设之上 | 记录功能、DAU、QPS、存储、延迟和可用性 SLA |
| 是否估算了 QPS 和存储? | 容量只是猜测 | QPS = DAU x 操作次数 / 86400;存储 = 记录数 x 大小 x 保留时间 |
| 每个组件是否都有冗余? | 存在单点故障 | 为每个组件添加副本、故障转移或多可用区 |
| 是否定义了数据库扩展策略? | 增长后会遇到瓶颈 | 先垂直扩展,再添加只读副本,最后使用明确分片键进行分片 |
| 读密集型路径是否有缓存? | 数据库承受不必要的负载 | 使用 Redis/Memcached 的旁路缓存模式,并定义 TTL |
| 异步路径是否使用队列? | 耦合紧密,容易发生级联故障 | 使用 Kafka/SQS 为任务、通知和分析解耦 |
| 是否有监控和告警计划? | 无法及时发现生产故障 | 定义指标、日志聚合、追踪和告警阈值 |
| 是否定义了部署策略? | 一次性全面发布风险高 | 使用滚动发布、蓝绿发布或金丝雀发布,并自动回滚 |
延伸阅读
如需查看带有详细图表和讲解的完整指南:
- "System Design Interview -- An Insider's Guide",作者 Alex Xu(第 1 卷)
- "System Design Interview -- An Insider's Guide: Volume 2",作者 Alex Xu(第 2 卷)
- "Designing Data-Intensive Applications",作者 Martin Kleppmann(数据系统基础知识)
- ByteByteGo —— Alex Xu 的平台,提供可视化的系统设计讲解
关于作者
Alex Xu 是一名软件工程师,曾在 Twitter、Apple 和 Oracle 工作,也是 ByteByteGo 的创始人。他的两卷本 System Design Interview 系列已售出超过 50 万册,通过结构化思考、估算和清晰沟通,将系统设计变成了一项可学习、可重复掌握的技能。