scaling-evolution
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseScaling Evolution
扩展演进路径
Grow a design one bottleneck at a time. A system that serves 1k users and one
that serves 10M users are different architectures, but you do not jump between
them — you walk a path where each step removes the current ceiling and exposes
the next. Getting this wrong means either over-building day one (paying multi-
region complexity for 1k users) or freezing when load doubles because the design
was a memorized end-state, not a sequence of justified moves (GUIDE #7).
一次解决一个瓶颈来演进设计。服务1000用户的系统和服务1000万用户的系统架构截然不同,但你无需直接跳跃到终态架构——而是沿着一条路径逐步演进,每一步都突破当前的性能上限,暴露下一个瓶颈。如果做错这一点,要么第一天就过度设计(为1000用户承担多区域架构的复杂度),要么当负载翻倍时陷入停滞,因为设计是死记硬背的终态,而非一系列有理有据的演进步骤(GUIDE #7)。
When to reach for this
何时使用此Skill
A load increase is on the table ("what if traffic 10×?", "scale to millions"),
the user asks where the bottleneck is or what breaks first, or a single-box
design has outgrown one machine. Reach here to sequence the next two or three
moves — never the whole roadmap at once.
当面临负载提升(比如“如果流量增长10倍怎么办?”“扩展至百万级”)、用户询问瓶颈位置或首先会出什么问题,或者单节点设计已经超出单台机器的承载能力时,使用此Skill规划接下来的2-3步——切勿一次性规划整个路线图。
When NOT to
何时不使用
Do not pre-build steps the numbers do not yet demand (YAGNI). Sharding,
multi-region, and a message queue are late moves; proposing them for a system
that fits on two boxes is the over-indexing this skill defends against. If the
current load fits comfortably on a vertically-scaled box with a replica, stop —
that is the cheapest design that meets the constraint, and it wins. Naming the
next five tiers when only one is needed is a red flag, not foresight.
不要提前构建当前数据规模不需要的步骤(YAGNI原则)。分片、多区域和消息队列都是后期步骤;如果系统在两台服务器上就能运行,却提出这些方案,就属于过度设计,而此Skill正是要避免这种情况。如果当前负载在垂直扩容的服务器加副本后仍能轻松承载,就停止——这是满足约束条件的最廉价设计,也是最优解。当只需要一个步骤时却列出接下来的五个层级,这不是远见,而是危险信号。
Clarify first
先明确关键信息
The path is driven entirely by numbers and constraints, so pin these down before
moving (most come from and ):
requirements-scopingback-of-the-envelope- Current and target scale — today's QPS/data and the multiple you must hit (2×? 100×?). The multiple decides how many steps you take now.
- Read:write ratio — read-heavy systems scale with replicas + cache; write- heavy systems hit the master/storage ceiling and need sharding far sooner.
- Where it hurts now — is the symptom compute (CPU saturated), storage (DB/disk saturated), or network (bandwidth/connections)? Diagnose before adding.
- Consistency and staleness budget — replicas and multi-region trade freshness
for scale; if reads must be current, that constrains the path (→ ).
consistency-coordination - State — is anything pinned to a server (sessions, local files)? Stateful tiers block horizontal scaling.
演进路径完全由数据和约束条件驱动,因此在行动前需明确这些信息(大部分来自和):
requirements-scopingback-of-the-envelope- 当前和目标规模——当前的QPS/数据量,以及需要达到的倍数(2倍?100倍?)。倍数决定了现在需要执行多少步骤。
- 读写比——读密集型系统通过副本+缓存实现扩展;写密集型系统会更快触及主节点/存储上限,需要更早进行分片。
- 当前痛点——症状是计算(CPU饱和)、存储(数据库/磁盘饱和)还是网络(带宽/连接数不足)?在添加任何组件前先诊断清楚。
- 一致性和过期容忍度——副本和多区域架构以数据新鲜度换取扩展性;如果读取必须是实时的,这会限制演进路径(→ )。
consistency-coordination - 状态——是否有任何内容绑定到服务器(会话、本地文件)?有状态层会阻碍水平扩展。
The method: walk the bottleneck ladder
方法:沿着瓶颈阶梯逐步演进
Each rung removes one ceiling. Apply the next rung the numbers justify, not
the whole ladder. Full triggers and worked thresholds are in
.
references/scaling-ladder.md- Single server. Web, app, DB, cache on one box. Correct for low traffic and early validation. Breaks when one machine can't hold the load or the data.
- Split the tiers. Move the database (and later cache) onto its own host so web and data scale independently. Breaks when the single web box or single DB saturates, or either becomes a single point of failure.
- Vertical scale + replicate for reads. First scale up (bigger box — simple,
no app changes) until the hard limit or cost knee. Add read replicas to spread
reads off the primary (→ owns replication). Breaks when writes saturate the primary, or replica lag breaks freshness.
data-storage - Add a cache. Put hot reads in front of the DB once a number shows reads
dominate (→ ). Highest-leverage move for read-heavy systems. Breaks when writes are the bottleneck, or the working set no longer fits.
caching - Push static/edge to a CDN. Offload images/JS/CSS/video to edge servers
close to users (→ ). Breaks when the bottleneck is dynamic requests, not static assets.
content-delivery - Make the web tier stateless + load-balance. Move session/state to a shared
store so any request hits any server; put a load balancer in front and
autoscale the fleet (→ ). This is the unlock for cheap horizontal scale. Breaks when the data tier (now the bottleneck) can't keep up.
load-balancing - Decouple with async. Move slow/bursty work (uploads, encoding, fan-out)
behind a queue so producers and consumers scale independently and spikes are
absorbed (→ ). Breaks when even the sync path or storage is the limit.
messaging-streaming - Multi-DC / multi-region. Geo-route users to the nearest healthy data center for latency and disaster survival; replicate across regions. Breaks when cross-region data sync, conflict resolution, or a single dataset too big for one region forces the last rung.
- Shard the data tier. Partition data across nodes when one primary can no
longer hold the writes/data (→ owns sharding/partitioning;
data-storageowns consistent hashing). The most complex move — last, not first.consistency-coordination
Vertical scaling (scale up: more CPU/RAM) is the cheap early move with no app
changes but a hard ceiling and no redundancy. Horizontal scaling (scale out:
more boxes) is the durable answer — better availability, near-unlimited headroom —
but demands statelessness and adds coordination cost. Climb vertically until the
knee, then go horizontal.
每一级阶梯突破一个性能上限。只应用数据规模证明合理的下一级阶梯,而非整个阶梯。完整的触发条件和验证阈值见。
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)是早期低成本举措,无需修改应用,但有硬件上限且无冗余。水平扩容(向外扩展:增加服务器)是持久化解决方案——可用性更高,几乎有无限的扩展空间——但要求无状态架构,且增加协调成本。先进行垂直扩容直到成本拐点,再转向水平扩容。
Diagnose the bottleneck before adding anything
在添加任何组件前先诊断瓶颈
"Add more servers" without a diagnosis is guessing (GUIDE #3, #7). Classify the
pressure first, then act on that resource:
- Compute-bound (CPU/threads pegged, latency rises with request rate): add app servers / autoscale; check for an O(n) hot path before buying hardware.
- Storage-bound (DB CPU/IO pegged, slow queries, replica lag growing): add read replicas, cache, then shard. Adding web servers here makes it worse — more connections onto an already-saturated DB.
- Network-bound (bandwidth saturated, connection limits, cross-region RTT): CDN for egress, compression, connection pooling, keep chatty traffic in one DC. The classic failure is sharding the database when the bottleneck is compute — a new failure mode added to fix the wrong layer. Read the symptom, name the resource, then pick the rung.
Treat each rung as a hypothesis, not a destination: "this design holds until
writes exceed X / a region is lost / the working set outgrows RAM." Saying the
breaking point out loud is the move that distinguishes reasoning from defending a
diagram. When a constraint changes (load doubles, latency target tightens, a DC
is lost), revisit the assumption and climb — calmly, not by patching the old
shape onto a problem it no longer fits.
“添加更多服务器”却不进行诊断就是盲目猜测(GUIDE #3, #7)。先归类压力类型,再针对对应资源采取行动:
- 计算瓶颈(CPU/线程满载,延迟随请求率上升):添加应用服务器/自动扩缩容;在购买硬件前检查是否存在O(n)的热点路径。
- 存储瓶颈(数据库CPU/IO满载,查询缓慢,副本延迟增加):添加读副本、缓存,然后进行分片。在此处添加Web服务器会使情况更糟——更多连接会加重已饱和数据库的负载。
- 网络瓶颈(带宽饱和,连接数受限,跨区域RTT过高):使用CDN减少出口流量,开启压缩,使用连接池,将频繁通信的流量限制在同一数据中心内。 典型的错误是当瓶颈是计算时却对数据库进行分片——为了解决错误层级的问题而引入新的故障模式。先观察症状,明确资源类型,再选择对应的阶梯层级。
将每一级阶梯视为一个假设,而非终点:“此设计在写请求超过X / 某个区域故障 / 工作集超出RAM之前可以正常运行”。明确说出失效点是区分理性分析和死硬维护架构图的关键。当约束条件变化(负载翻倍,延迟目标收紧,某个数据中心故障)时,重新审视假设并继续演进——冷静应对,而非将旧架构硬套在不再适配的问题上。
Dos and don'ts
注意事项
Distilled from the ladder, the diagnosis step, and where the technique misleads.
Do
- Diagnose the resource before adding capacity — name compute vs storage vs network, then act on that tier. "Add servers" without a symptom is guessing.
- Apply only the next rung the numbers justify, and state its breaking point out loud ("holds until writes exceed X / a region is lost").
- Climb vertically until the knee, then go horizontal — bigger box first (no app changes), scale-out once the ceiling or cost knee is hit.
- Make the web tier stateless before scaling it out — move sessions to a shared store so autoscaling can't drop them.
- Pair every rung with the failure mode it adds (cache stampede, replica
promotion, region failover, hot shard) → .
resilience-failure
Don't
- Don't treat the ladder as a checklist — it is a menu; most systems live happily at rung 4–6 forever and never shard.
- Don't skip rungs to the "impressive" answer — jumping to sharding or multi-region signals a memorized diagram, not a crossed ceiling.
- Don't scale the layer that isn't the bottleneck — more web servers onto a saturated DB just adds connections and amplifies the load downstream.
- Don't route read-your-writes to a lagging replica — replica lag reads like
data loss; pin those reads to the primary (→ ).
consistency-coordination - Don't build the end-state on day one — multi-region for 1k users is cost and complexity with no payoff. Match the rung to today's number.
从阶梯演进、诊断步骤和技术误区中提炼而来。
应该做
- 在添加容量前先诊断资源瓶颈——明确是计算、存储还是网络瓶颈,再针对对应层级采取行动。“添加服务器”却没有明确症状就是盲目猜测。
- 只应用数据规模证明合理的下一级阶梯,并明确说出其失效点(“在写请求超过X / 某个区域故障之前可以正常运行”)。
- 先垂直扩容直到成本拐点,再转向水平扩容——先使用更大的服务器(无需修改应用),达到上限或成本拐点后再向外扩展。
- 在向外扩展前使Web层无状态——将会话迁移到共享存储,这样自动扩缩容不会导致会话丢失。
- 为每一级阶梯匹配其引入的故障模式(缓存击穿、副本晋升、区域故障转移、热点分片)→ 。
resilience-failure
不应该做
- 不要将阶梯视为检查清单——它是一个选项菜单;大多数系统会在第4-6级阶梯稳定运行,永远不需要分片。
- 不要跳过阶梯直接选择“令人印象深刻”的方案——直接跳到分片或多区域架构说明你是在死记硬背架构图,而非突破当前的性能上限。
- 不要扩展非瓶颈层级——在数据库已饱和时添加更多Web服务器只会增加连接数,加重下游负载。
- 不要将“读自己写的数据”请求路由到延迟较高的副本——副本延迟会让人误以为数据丢失;将这些请求固定到主节点(→ )。
consistency-coordination - 不要在第一天就构建终态架构——为1000用户搭建多区域架构只会增加成本和复杂度,却没有任何回报。让阶梯层级匹配当前的数据规模。
Numbers that matter
关键数据
Numbers decide which rung is next; don't restate the tables — read
. The ceilings that trigger a climb: a single RDBMS node
handles roughly 1k QPS, a key-value node ~10k, a cache node
~100k–1M; one ~64-core box is ~64k req/s of pure compute before IO. When
an estimate crosses one of these, that crossing is the next bottleneck. Peak is
typically ~2× average, so size to peak. A useful framing: the rung you need is
roughly set by the order of magnitude of target QPS and dataset size — 1k QPS
fits one box, ~10k wants replicas and a cache, ~100k+ forces a stateless
horizontal tier, and a dataset past one node's RAM forces sharding. Each extra
"nine" of availability costs a disproportionate jump in redundancy (replicas →
multi-AZ → multi-region) — tie the target to the requirement, not ambition
(→ , ).
back-of-the-envelopeback-of-the-enveloperesilience-failure数据决定了下一级阶梯是什么;不要重复表格内容——请阅读。触发演进的性能上限:单个RDBMS节点大约能处理1k QPS,键值对节点约10k QPS,缓存节点约100k–1M QPS;一台约64核的服务器在IO受限前能处理约64k req/s的纯计算请求。当估算值超过这些阈值时,就意味着下一个瓶颈出现了。峰值流量通常是平均流量的~2倍,因此按峰值流量规划。一个有用的框架:所需的阶梯层级大致由目标QPS和数据集大小的数量级决定——1k QPS适合单节点,~10k QPS需要副本和缓存,~100k+ QPS需要无状态水平扩展层,数据集超过单节点RAM时需要分片。每增加一个“9”的可用性,冗余度都会不成比例地增加(副本 → 多可用区 → 多区域)——将目标与需求绑定,而非盲目追求高可用(→ , )。
back-of-the-envelopeback-of-the-enveloperesilience-failureDiagram
架构图
To visualize the current architecture and the one-rung-ahead version side by
side (so the breaking point and the next move are explicit), use the in-plugin
skill. Sketch only the rung you're on plus the next one —
not the whole ladder.
architecture-diagram为了直观对比当前架构和下一级阶梯的架构(明确失效点和下一步行动),使用插件内的 Skill。只绘制当前所在的阶梯层级和下一级——而非整个阶梯。
architecture-diagramRelated building blocks
相关组件
- — depends on it for the ceilings; a number crossing one names the next bottleneck.
back-of-the-envelope - — owned-concept lives there: replication and sharding/partitioning, the heaviest rungs.
data-storage - — pairs with this as the cache rung; owns what to cache and how it fails under load.
caching - — feeds into the stateless horizontal tier; sits at its front.
load-balancing - — pairs with this as the CDN/edge rung for static and geo-distributed content.
content-delivery - — pairs with every rung; each one adds a failure mode to degrade gracefully.
resilience-failure - — owned-concept lives there: the freshness/coordination cost of replicas, multi-region, and shards.
consistency-coordination - — orchestrated by it; this skill runs at its "scale the design" step.
system-design
- —— 依赖它确定性能上限;当数据超过某个阈值时,就明确了下一个瓶颈。
back-of-the-envelope - —— 相关概念归属此处:副本和分片/分区,这是最复杂的阶梯层级。
data-storage - —— 与此Skill配合使用,对应缓存阶梯层级;负责缓存策略和负载下的故障处理。
caching - —— 为无状态水平扩展层提供支持;位于其前端。
load-balancing - —— 与此Skill配合使用,对应CDN/边缘阶梯层级,处理静态和地理分布式内容。
content-delivery - —— 与每一级阶梯配合使用;每一级都会引入一种故障模式,需要实现优雅降级。
resilience-failure - —— 相关概念归属此处:副本、多区域和分片的新鲜度/协调成本。
consistency-coordination - —— 由它统筹;此Skill在其“扩展设计”步骤中运行。
system-design
References
参考资料
- — the full rung-by-rung ladder with concrete trigger thresholds, the compute/storage/network diagnosis checklist, the vertical-vs-horizontal decision, and the multi-region sync gotchas. Read when sequencing the next moves or diagnosing what breaks first.
references/scaling-ladder.md
- —— 完整的阶梯层级说明,包含具体的触发阈值、计算/存储/网络诊断清单、垂直vs水平扩展决策,以及多区域同步的陷阱。在规划下一步行动或诊断首先会出什么问题时阅读。
references/scaling-ladder.md