Skip to content

系统设计四步分析法与估算

本文是系统设计系统学习系列的 L1 入门篇。前置:无。 学完可以配合面试题食用:01-short-url-service20-system-design-tradeoff-and-limit

为什么系统设计需要"套路"

面试或工作中拿到一个设计题,最常见的反应是"这功能我熟,但先从哪里开始说?"上来就画架构图的人,往往漏掉最关键的前提:需求没对齐、规模没定。

四步分析法把模糊的设计题拆成可执行的步骤:澄清需求 → 估算规模 → 高层架构 → 深挖瓶颈。不是套路,是防漏的 checklist。一个短链系统、一个 feed 流、一个秒杀,都能用这四步走一遍。

第一步:澄清需求——先问再答,别自嗨

需求阶段最容易犯的错是"默认理解"。面试官说"设计一个短链服务",你可以直接问:

  • 用户规模:DAU 多少?100 万还是 1 亿,方案差很远
  • 读写比:写一次短链被读多少次?对标典型的 1:100 还是 1:10000
  • 一致性要求:短链要实时生效吗?还是 TTL 过期后允许短暂不一致
  • 延迟要求:用户点短链,期望多快跳转?200ms 以内还是秒级
  • 预算约束(实战中才有):自建还是用云服务,决定了冗余等级

这些问题也可以反向验证:面试官说"日活 1000 万",那短链每天的写入量大概是多少?用估算来反推。

第二步:估算规模——用拇指法则算数字

估算不追求精确,目的是让后续设计有数据支撑。常用的拇指法则:

指标数量级
内存操作10^7 ops/s(单机)
SSD 随机读10^4 ops/s
网络 RTT(同机房)0.5ms
跨 DC 延迟30-60ms
磁盘顺序写10^5 ops/s

DAU → 请求量的估算公式

  • 日请求数 = DAU × 每日人均请求数 × 峰值系数
  • 峰值系数:3-10 倍,取决于业务波动(短链均匀 3 倍,秒杀可能 10 倍以上)
  • 带宽 = 平均响应大小 × QPS × 8(bit 转换)

案例:日活千万 feed 系统的完整估算

DAU = 1000 万
人均刷 feed 次数 = 50 次/天
每日总请求 = 1000w × 50 = 5 亿次
峰值 QPS = (5亿 / 86400) × 3 ≈ 17000 QPS
存储:每条 feed 消息 2KB,每天新增 500 万条 → 10GB/天
1 年存储 ≈ 3.6TB(冷热分离后热数据约 1.2TB)
带宽:下游响应 50KB(含图片缩略图),17000 × 50KB × 8 = 6.8 Gbps

这组数字告诉你:17000 QPS 单机 Redis 扛不住但加缓存层的 MySQL 集群可以;6.8 Gbps 带宽需要多网卡或负载均衡。数字有了,设计才有依据。

第三步:高层架构——画好组件和交互

先画粗粒度架构,不纠结细节。用一个短链系统来走一遍:

mermaid
flowchart LR
    Client[客户端] --> LB[负载均衡]
    LB --> Web[Web 服务层]
    Web --> Cache[Redis 缓存]
    Web --> DB[(MySQL 集群)]
    Web --> Counter[ID 生成器]
    Counter --> DB

短链的核心流程:

  1. 生成短链:全局 ID 生成器(雪花/号段)拿到 ID,编码成短字符串,写 DB 和缓存
  2. 访问短链:查缓存 → 查 DB → 302 跳转,缓存命中则跳过 DB

第一版架构只画核心组件,不引入 MQ、不引入 ES,等估算出瓶颈再加。

第四步:深挖瓶颈——用数字找薄弱环节

回到前面的估算数据。短链系统日活 1000 万,写入 QPS 约 50(用户每天平均 5 条短链),读取 QPS 约 5000:

  • 写入 QPS 50:单机 MySQL 完全够,优化点在于 ID 生成器不依赖 DB 自增(号段模式就够了)
  • 读取 QPS 5000:Redis 缓存命中率 99% 的情况下,后端 DB 只有 50 QPS,毫无压力
  • 瓶颈在哪:短链跳转的 302 请求本身,Web 层需要足够长的连接?不,短链是 stateless 的,水平扩展即可
java
// 短链 ID 生成:号段模式(每批次预取 1000 个 ID)
public class SegmentIdGenerator {
    private final DataSource dataSource;
    private final AtomicLong currentId = new AtomicLong(0);
    private final AtomicLong maxId = new AtomicLong(0);
    private final int step = 1000;

    public synchronized long nextId() {
        if (currentId.get() >= maxId.get()) {
            // 从 DB 取下一批号段
            try (Connection conn = dataSource.getConnection();
                 PreparedStatement ps = conn.prepareStatement(
                     "UPDATE id_segment SET max_id = max_id + ? WHERE biz_tag = ?")) {
                ps.setInt(1, step);
                ps.setString(2, "short_url");
                ps.executeUpdate();
                // 重新读取
                try (Statement stmt = conn.createStatement();
                     ResultSet rs = stmt.executeQuery(
                         "SELECT max_id FROM id_segment WHERE biz_tag = 'short_url'")) {
                    rs.next();
                    long newMax = rs.getLong(1);
                    currentId.set(newMax - step);
                    maxId.set(newMax);
                }
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }
        }
        return currentId.getAndIncrement();
    }

    public String encode(long id) {
        // Base62 编码:0-9a-zA-Z 共 62 字符
        String chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
        StringBuilder sb = new StringBuilder();
        while (id > 0) {
            sb.append(chars.charAt((int) (id % 62)));
            id /= 62;
        }
        return sb.reverse().toString();
    }
}

号段模式的好处:DB 压力极小(每 1000 个 ID 才一次 DB 写),且 ID 生成服务重启不丢号段。配合 Base62 编码,6 位字符能覆盖约 568 亿个短链,完全够用。

数字速查卡——面试时随手用

以下数字不需要背,但要有"数量级直觉":

操作延迟单机 QPS 上限
内存读(Redis)0.1ms10 万+
本地内存读0.01ms100 万+
SSD 随机读2-5ms1 万
MySQL 简单查询(非缓存)5-10ms5000
同机房 RPC0.5-2ms1 万+
跨 DC RPC(同区域)10-30ms3000
磁盘顺序写0.1ms10 万+

常见误区与小结

  • 误区 1:估算数字精确到个位。估算本质是"数量级论证",17000 QPS 和 18000 QPS 不影响设计;但 1700 和 17000 差一个数量级,方案完全不同
  • 误区 2:上来就画复杂架构。Redis + MQ + ES + 分库分表全上,面试官直接问"你确定你的规模需要这些?"防止过度设计的最好方法就是先有估算数字
  • 误区 3:需求阶段不问人。实战中这是最致命的,一个月后返工;面试中不问会扣"沟通能力"分
  • 误区 4:把估算只当面试技巧。线上真实项目的容量规划比面试更严格,从 0 到 1 的估算习惯能帮你避免上线就 OOM
  • 误区 5:忽视带宽估算。存算分离架构下,网络带宽往往先于 CPU 成为瓶颈——6.8 Gbps 的流量需要万兆网卡支持

小结:四步分析法不是银弹,它是一个防漏 checklist。拿到任何设计题,先用这四步走一遍,方向对了再深入细节。下一篇进入系统设计核心组件,看负载均衡、缓存、消息队列和 CDN 各自解决什么问题,以及什么规模才值得引它们。

参考

参考:《Designing Data-Intensive Applications》- Martin Kleppmann(第六章分区与第九章一致性与共识的估算方法) 参考:系统设计面试 01 短链服务 - 四步法的完整走读案例

手撕 → 框架 → 生产化,一步步把 AI Agent 工程化搞透。
粤ICP备2026104257号-1