关于 scaling-evolution
面向系统设计者的渐进式扩展技能,按当前瓶颈逐步规划架构演进,而非预先构建最终形态。它结合负载与资源诊断,说明何时扩容以及每一步会引入的限制。
主要功能
- 01按瓶颈逐级规划扩展
- 02区分计算、存储与网络压力
- 03比较垂直扩展和水平扩展
- 04识别各阶段的触发条件
- 05考虑扩展带来的故障模式
适用场景
- 01评估流量增长时的下一步架构调整
- 02诊断系统首先触及的容量上限
- 03规划从单机到多节点的演进
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ proyecto26/ system-design-skills --skill scaling-evolution安装后在 Claude Code 中输入/scaling-evolution确认已加载。
附带文件references/scaling-ladder.md
详细介绍
扩展演进
一次解决一个瓶颈,逐步扩展设计。服务 1k 个用户的系统和服务 10M 个用户的系统,采用的是不同的架构,但你不会直接从一种跳到另一种——而是沿着一条路径逐步前进,每一步都移除当前上限,并暴露出下一个上限。判断失误,要么导致第一天就过度构建(为 1k 个用户承担多区域的复杂性),要么当负载翻倍时束手无策,因为设计只是背下来的最终状态,而不是一系列有依据的调整(GUIDE #7)。
何时使用
当负载增加已提上日程(“流量增加 10× 怎么办?”、“扩展到数百万用户”)、用户询问瓶颈在哪里或最先会出什么问题,或者单机设计已经超出一台机器的承载能力时,就该使用此指南。按顺序规划接下来的两三步,而不是一次列出完整路线图。
何时不使用
不要提前构建当前数据尚未要求的步骤(YAGNI)。分片、多区域和消息队列都属于后期措施;对于能在两台机器上运行的系统提出这些方案,正是本指南要避免的过度配置。如果当前负载在一台可纵向扩展的机器加一个副本上就能轻松承载,那就到此为止——这是满足约束条件的成本最低的设计,也是最佳选择。只需一步时却列出后面五个层级,这不是远见,而是危险信号。
先明确情况
扩展路径完全由数据和约束条件决定,因此在采取行动前要先确认以下几点(大多数来自 requirements-scoping 和 back-of-the-envelope):
- 当前规模和目标规模——当前的 QPS/数据量,以及必须达到的倍数(2×?100×?)。倍数决定当前要走几步。
- 读写比例——读密集型系统可通过副本 + 缓存扩展;写密集型系统会触及主节点/存储上限,因此需要更早分片。
- 当前的痛点——症状是计算资源(CPU 饱和)、存储(数据库/磁盘饱和),还是网络(带宽/连接数)?先诊断,再添加资源。
- 一致性和数据陈旧度预算——副本和多区域会以数据新鲜度换取扩展能力;如果读取必须是最新数据,就会限制扩展路径(→
consistency-coordination)。 - 状态——是否有任何状态固定在某台服务器上(会话、本地文件)?有状态的层会阻碍水平扩展。
方法:沿瓶颈阶梯逐级扩展
每一级都会消除一个上限。只应用数据所支持的下一级,而不是攀完整个阶梯。完整的触发条件和具体阈值示例见
references/scaling-ladder.md。
- 单台服务。 将 Web、应用、数据库和缓存放在一台机器上。适用于低流量和早期验证。在以下情况下会失效: 一台机器无法承载负载或数据。
- 拆分各层。 将数据库(之后再将缓存)迁移到独立主机,使 Web 层和数据层可以独立扩展。在以下情况下会失效: 单台 Web 服务器或单个数据库达到饱和,或其中任何一个成为单点故障。
- 垂直扩展 + 读副本。 先向上扩展(更大的机器——简单,无需更改应用),直到达到硬性上限或成本拐点。添加读副本,将读取负载从主库分散出去(→
data-storage负责复制)。在以下情况下会失效: 写入使主库达到饱和,或副本延迟影响数据新鲜度。 - 添加缓存。 一旦数据表明读取占主导,就在数据库前缓存热点读取(→
caching)。这是读密集型系统中杠杆效益最高的举措。在以下情况下会失效: 瓶颈在于写入,或工作集不再能放入缓存。 - 将静态内容/边缘服务移至 CDN。 将图片、JS、CSS 和视频卸载到靠近用户的边缘服务器(→
content-delivery)。在以下情况下会失效: 瓶颈在动态请求,而非静态资源。 - 让 Web 层无状态 + 负载均衡。 将会话/状态迁移到共享存储,使任何请求都能由任意服务器处理;在前端放置负载均衡器,并自动扩缩服务器集群(→
load-balancing)。这是以较低成本实现横向扩展的关键。在以下情况下会失效: 数据层(此时已成为瓶颈)无法跟上。 - 通过异步解耦。 将耗时或突发性工作(上传、编码、扇出)放到队列之后,使生产者和消费者能够独立扩展,并吸收流量峰值(→
messaging-streaming)。在以下情况下会失效: 即使是同步路径或存储也已达到上限。 - 多数据中心 / 多区域。 将用户按地理位置路由到最近的健康数据中心,以降低延迟并抵御灾难;跨区域复制。在以下情况下会失效: 跨区域数据同步、冲突解决,或单个数据集大到无法容纳在一个区域时,就必须迈上最后一级。
- 对数据层分片。 当单个主库无法再容纳写入或数据时,将数据分区到多个节点(→
data-storage负责分片/分区;consistency-coordination负责一致性哈希)。这是最复杂的举措——放在最后,而非第一步。
垂直扩展(向上扩展:增加 CPU/RAM)是早期成本低且无需更改应用的举措,但有明确上限,也没有冗余。横向扩展(向外扩展:增加机器)是更持久的解决方案——可用性更高,扩展空间近乎无限——但要求无状态,并会增加协调成本。先垂直扩展到拐点,再转向横向扩展。
在添加任何内容前,先诊断瓶颈
没有诊断就“增加更多服务”是在猜测(GUIDE #3、#7)。先判断压力来自哪里,再针对对应的资源采取行动:
- 计算受限(CPU/线程满载,延迟随请求速率上升):增加应用服务/自动扩缩容;购买硬件前先检查是否存在 O(n) 热路径。
- 存储受限(数据库 CPU/IO 满载、查询缓慢、副本延迟不断增长):先增加只读副本、缓存,然后再分片。在这种情况下增加 Web 服务只会让情况更糟——会向已经饱和的数据库增加更多连接。
- 网络受限(带宽饱和、连接数达到上限、跨区域 RTT):出站流量使用 CDN、压缩、连接池,并让频繁交互的流量留在同一个数据中心。 常见的失败是:瓶颈在计算,却去拆分数据库——为了修复错误的层级,又引入了一种新的故障模式。读懂症状,指出资源,再选择要迈上的台阶。
把每一级都视为一种假设,而不是终点:“这种设计能支撑到写入量超过 X/某个区域不可用/工作集超出 RAM 为止。”明确说出崩溃点,才能将推理与维护一张架构图区分开来。当约束发生变化(负载翻倍、延迟目标收紧、某个数据中心不可用),重新审视假设并继续攀升——保持冷静,不要把旧架构硬套到已不适用的问题上。
应做和不应做的事
根据阶梯、诊断步骤以及该技术容易产生误导的场景提炼而成。
应做
- 在增加容量前先诊断资源——指出是计算、存储还是网络受限,然后针对对应的层级采取行动。没有症状就说“增加服务器”是在猜测。
- 只采取数据足以证明合理的下一级措施,并明确说出它的崩溃点(“能支撑到写入量超过 X/某个区域不可用为止”)。
- 先纵向扩展,直到到达拐点,再横向扩展——先换更大的机器(无需更改应用),达到上限或成本拐点后再横向扩展。
- 在横向扩展前让 Web 层变为无状态——将会话移至共享存储,避免自动扩缩容时丢失会话。
- 每上一级都要指出它引入的故障模式(缓存惊群、副本提升、区域故障转移、热点分片)→
resilience-failure。
不应做
- 不要把阶梯当作检查清单——它是一份选项列表;大多数系统长期停留在第 4–6 级,从未分片,也运行良好。
- 不要跳过级别,直接给出“令人印象深刻”的答案——直接跳到分片或多区域,说明你只是背熟了架构图,而非确实遇到了扩展上限。
- 不要扩展非瓶颈所在的层级——在数据库已饱和时增加 Web 服务,只会增加连接并放大下游负载。
- 不要将读己之写请求路由到有延迟的副本——副本延迟看起来就像数据丢失;应将这些读取固定路由到主库(→
consistency-coordination)。 - 不要在第一天就构建最终形态——面向 1k 用户的多区域架构,只会增加成本和复杂性,却没有收益。根据今天的规模选择相应级别。
重要数字
数字决定接下来该迈上哪一级;不要复述表格——请阅读 back-of-the-envelope。触发升级的上限:单个 RDBMS 节点大约可处理 1k QPS,键值节点约 10k,缓存节点约 100k–1M;一台约 64 核的机器,在纯计算且不考虑 IO 的情况下,每秒约可处理 64k 个请求。当估算值超过其中任一上限时,这个越界点就是下一个瓶颈。峰值通常约为平均值的 2 倍,因此应按峰值规划容量。一个实用的判断方法是:所需级别大致由目标 QPS 和数据集大小的数量级决定——1k QPS 可由单机承载,约 10k 需要副本和缓存,100k+ 则需要无状态的横向扩展层,而数据集超过单个节点的 RAM 时就必须分片。可用性每增加一个“9”,冗余成本都会大幅上升(副本 → 多可用区 → 多区域)——目标应由需求决定,而非野心(→ back-of-the-envelope、resilience-failure)。
图示
若要并排展示当前架构和领先一级的版本(明确标出瓶颈和下一步行动),请使用插件内的 architecture-diagram 技能。只绘制当前所处的级别和下一级——不要绘制整套阶梯。
相关构件
back-of-the-envelope— 依赖它来确定上限;某个数值一旦突破上限,就意味着出现了下一个瓶颈。data-storage— 相关概念归属此处:复制和分片/分区是其中最复杂的级别。caching— 与此配合,作为缓存级别;负责确定缓存哪些内容,以及缓存如何在负载下失效。load-balancing— 为无状态水平扩展层提供支持,位于该层前端。content-delivery— 与此配合,作为静态内容和地理分布式内容的 CDN/边缘级别。resilience-failure— 与每个级别配合;每个级别都会引入一种故障模式,需要能够优雅降级。consistency-coordination— 相关概念归属此处:副本、多区域和分片带来的新鲜度/协调成本。system-design— 由它编排;此技能会在其“扩展设计”步骤中运行。
参考资料
references/scaling-ladder.md— 完整的逐级阶梯,包含具体的触发阈值、计算/存储/网络诊断清单、纵向与横向扩展决策,以及多区域同步的注意事项。在安排下一步行动或诊断最先出现的故障时阅读。