30 分钟白板演练:用刷榜笔记的思路手写一份短链系统设计
【免费下载链接】system-design-notesNotes of the book System Desgin Interview - An Insider's Guide项目地址: https://gitcode.com/GitHub_Trending/sy/system-design-notes
系统设计面试里,短链(URL Shortener)几乎是出场率最高的"入门级"题目:需求容易理解、边界清晰、却又藏着容量估算、ID 生成、缓存、重定向语义等一连串值得深挖的点。正因为它"看着简单、问起来没底",最适合拿来当白板演练的练习场。
这份仓库把《System Design Interview》拆成了 28 章,每章都是一次完整的"需求澄清 → 高层设计 → 深潜 → 复盘"推演,短链对应其中的 第 8 章。本文就借用这套刷榜笔记的思路,把一次 30 分钟的白板演练完整走一遍:先钉死需求,再算清楚容量,然后做选型对比,最后把方案"讲"出来——每一步都有仓库里的笔记和示意图作支撑,你可以直接照着白板复刻。
一、白板第一笔:先把需求钉死在白板上
面试官抛出"设计一个短链服务"后,最容易犯的错误是立刻画架构图。按照 03. System Design Framework/Readme.md 里的框架,前几分钟应该用来澄清问题、写下假设,而不是动手设计。白板上至少要先出现这几行:
- 功能:长链转短链、短链访问时 302/301 重定向到长链;
- 量级:每天生成 1 亿条短链,支持 10 年容量;
- 读写特征:读:写 = 10:1,这是决定缓存和数据库架构的关键数字;
- 非功能:短链尽量短、全局唯一、高可用、低延迟。
其中"读写比 10:1"这一条尤其重要——它直接决定了后面所有架构决策的方向:读多写少意味着必须上缓存、必须做读路径优化,而写入路径可以做得相对重一些。把假设写在白板上还有个额外好处:面试官会把你当成协作者而不是被考核者,后续讨论就有了共同的语言锚点。
二、容量估算:把 QPS 和存储算到白板上
有了量级,就可以套用 02. Back Of the Envelope Estimation/Readme.md 里教的方法做封底估算。这一步的价值不在"算得准",而在于展示你的量级感和推导过程,所以别用计算器,心算即可。
QPS 估算:
- 写入 QPS = 1 亿 / 86,400 秒 ≈1,160 QPS
- 读取 QPS = 1,160 × 10 ≈11,600 QPS
- 峰值读 QPS 按 2 倍毛估 ≈23,000 QPS
存储估算:
- 每年记录数 = 1 亿 × 365 = 365 亿条
- 10 年累计 =3,650 亿条(仓库笔记里的口径是 365 billion)
- 按每条记录(ID + 短链 + 长链 + 索引开销)约 1KB 毛估,十年总存储 ≈365 TB
估算时"2 的幂"换算能力是基本功,仓库第一章就给出了这张对照表:

缓存估算:读请求 11,600 QPS 意味着每天约 10 亿次访问。按经典的 80/20 规则,大约 20% 的热门短链扛走了 80% 的流量。只要把热点映射(shortURL → longURL,每条约 500B)缓存住,就能把绝大多数读请求挡在数据库之外——缓存 100 万条热点大约只需要 500MB 内存,量级完全可控。这个"算完才知道该缓存多少"的过程,正是刷题笔记里反复强调的"从量级反推组件"的思维。
最后在白板上汇总成一张表,面试官一眼就能看出你对量级有掌控:
| 指标 | 估算值 |
|---|---|
| 写入 QPS | ~1,160 |
| 读取 QPS | ~11,600(峰值 ~23,000) |
| 10 年总记录数 | 3,650 亿条 |
| 10 年总存储 | ~365 TB |
| 热点缓存 | 20% 热门短链,约 500MB 级 |
三、架构选型:为什么是"发号器 + Base62",而不是 UUID
容量算完,白板进入深潜阶段。短链系统最核心的技术决策只有一个:短链怎么生成?仓库 08. URL Shortener/Readme.md 给出了两条经典路线,对比非常清晰:
路线一:哈希截断 + 碰撞解决。对长链取 MD5 / SHA-1 / CRC32,截取前 7 位作为短链。优点是长度固定、不需要 ID 生成器;缺点是哈希会碰撞,需要反复追加字符串重哈希或借助布隆过滤器判重,成本高且不可控。

路线二:发号器 + Base62 编码。由一个全局唯一的 ID 生成器发号,再把十进制 ID 转成 Base62 字符串。62 个字符([0-9, a-z, A-Z])能承载的量级非常可观:7 位 Base62 可表示 62⁷ ≈ 3.5 万亿种组合,覆盖 3,650 亿条记录绰绰有余。仓库笔记里给了个具体例子:ID2009215674938转 Base62 后得到zn9edcu,正好 7 位。
那为什么社区里普遍"否决 UUID"?因为它有三个硬伤,笔记里记得清清楚楚:
- 太长:UUID 是 128 位,标准字符串形式 36 个字符,与"短链要短"的初衷直接矛盾;
- 不可排序:生成无序,无法按时间组织、难以做时间维度的统计与分页;
- 不可预测递增:无法承载"下一个可用短链"这类语义。

那 Twitter Snowflake 呢?它本身是优秀的分布式 ID 方案,但直接用于短链会撞上另一个问题:位数膨胀。Snowflake 的 64 位 ID 转 Base62 后大约有 10~11 位,明显超出 7 位的短链预期;而且其中的数据中心 ID、机器 ID 位对短链业务毫无意义,白白占用编码空间。

所以短链场景的正确答案是"发号器 + Base62"这对组合:唯一性由发号器保证,编码只负责变短。发号器可以是简单可靠的方案——比如集中式 ticket server(一个自增计数器),或者 Redis 的INCR批量取号(一次取一段区间,如[100000, 100999],本地逐号消费),代价小、可控性强。笔记里那句"Collision is not possible"正是这条路线最大的卖点:编码是双射,天然无碰撞,根本不需要判重。
两条路线的完整权衡,仓库里的对比表可以直接搬上白板:
| 维度 | 哈希截断 + 碰撞解决 | 发号器 + Base62 |
|---|---|---|
| 短链长度 | 固定 | 随 ID 增长(初期可保持 7 位) |
| 依赖 | 不需要 ID 生成器 | 需要全局发号器 |
| 碰撞 | 可能,需要额外解决 | 不可能 |
| 可预测性 | 不可预测 | ID 自增时可被枚举(安全考虑) |
四、数据模型与两条核心链路
选型定了,剩下的就是把流程画通。存储上采用关系型数据库保存<shortURL, longURL>映射,表结构非常简单,白板上画三列即可:

CREATE TABLE url_map ( id BIGINT PRIMARY KEY, -- 发号器分配的全局唯一 ID short_url VARCHAR(7) NOT NULL, -- Base62 编码结果 long_url VARCHAR(2048) NOT NULL, UNIQUE KEY uk_short_url (short_url) );链路一:短链生成。请求进来后先查长链是否已存在,存在则直接复用;否则向发号器取 ID、转 Base62、落库。注意"先查重"这一步非常关键——它让同一个长链始终得到同一个短链,避免了数据膨胀:

链路二:短链重定向。用户点击短链后,先查缓存(Redis),未命中再查数据库,拿到长链后返回重定向响应:

这里有个几乎必问的点:301 还是 302?301 表示永久移动,浏览器会缓存结果,后续请求不再打到短链服务,服务端压力小;302 表示临时重定向,每次访问都会经过服务端,方便做点击统计与来源分析。仓库笔记的结论是:如果业务需要分析能力,选 302;如果纯粹为了减负,选 301。这个"二选一"的回答本身不复杂,难的是把背后的取舍逻辑讲清楚——而取舍逻辑正是白板演练要练的核心。
五、白板表达练习:30 分钟讲法拆解
技术方案想清楚了,最后一步也是最容易被忽视的一步:怎么在 30 分钟内把这张白板讲完整。刷榜笔记的思路在这里同样适用——表达节奏也要像笔记目录一样结构化。参考 03. System Design Framework/Readme.md 里的四步框架(45 分钟版本是 3-10 / 10-15 / 10-25 / 3-5 分钟),压缩到 30 分钟可以这样切:
| 阶段 | 时间 | 白板上的内容 | 表达要点 |
|---|---|---|---|
| 澄清需求 | 0-5 min | 功能清单 + 量级假设 + 读写比 | 多问问题,把假设写下来 |
| 高层设计 | 5-12 min | 框图:客户端 → 负载均衡 → 短链服务 → 发号器 → 缓存 → 数据库 | 先整体后细节,主动给出估算 |
| 深潜 | 12-22 min | Base62 与哈希对比、301/302、缓存策略 | 聚焦 1-2 个关键组件,展示权衡 |
| 收尾 | 22-30 min | 瓶颈清单 + 扩展方案 | 主动暴露弱点,给出演进路线 |
四个阶段的表达各有侧重:澄清阶段展示的是"你如何看待模糊需求";高层设计展示的是"你是否有全局观和量级感";深潜阶段展示的是"你是否真的理解技术选型背后的取舍";收尾阶段展示的是"你是否知道这套方案会在哪里崩"。
练到后期,还可以给自己准备一份"追问清单",模拟面试官可能的连招。仓库里各章的 Additional Considerations 就是现成的题库:
- 301 还是 302?—— 重定向语义与统计需求之间的取舍;
- 同一个长链反复提交怎么办?—— 查重复用,代价是每次创建多一次 DB 查询;
- 发号器挂了怎么办?—— ticket server 单点故障,可用 Redis
INCR批量取号或雪崩备选方案兜底; - 短链被暴力枚举怎么办?—— Base62 自增 ID 可被预测,可引入随机偏移/加盐,并叠加限流(对应仓库 04. Rate Limiter/Readme.md);
- 365 TB 单表放不下怎么办?—— 按 shortURL 做一致性哈希分片(对应仓库 05. Consistent Hashing/Readme.md)。
六、复盘:这张白板还能怎么进化
30 分钟结束前,别忘了在白板上补最后一笔:演进路径。单机 + 单表的设计在量级爬坡后必然遇到瓶颈,你要能说出每一步怎么走:
- Web 层:保持无状态,配合负载均衡水平扩容,对应 01. Scaling/Readme.md 里"stateless web tier"的原则;
- 数据层:主从复制扛读流量,再按 shortURL 哈希分片扛容量;
- 可用性:目标 99.9% 意味着每年约 8.8 小时停机预算(02. Back Of the Envelope Estimation/Readme.md 里的可用性数字表),主库故障时需要有从库提升与数据恢复预案;
- 附加能力:按 IP 限流防滥用、点击与来源统计反哺业务。
把这六个部分走完,一次 30 分钟的白板演练就闭环了。回头看整个过程,你会发现它的骨架和仓库笔记的目录几乎一一对应:需求清单 → 容量估算 → 选型对比 → 核心链路 → 追问清单 → 演进复盘。这恰恰是刷题笔记的真正价值——它不给你标准答案,而是把"面对模糊问题时如何系统性地逼近答案"这个过程,拆成可以反复练习的步骤。下次在白板前拿到任何一道系统设计题,都值得先用这套骨架走一遍。
【免费下载链接】system-design-notesNotes of the book System Desgin Interview - An Insider's Guide项目地址: https://gitcode.com/GitHub_Trending/sy/system-design-notes
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考