系统设计案例

skillgohub.com 中文指南 | 中文版

系统设计案例

系统设计面试淘汰的候选人比算法题还多,但它得到的结构化准备却远远更少。原因在于:设计题考的是判断力,而不是记忆力——你得估算流量、权衡取舍,还要在面试官的反问下守住一套自洽的架构。快速建立这种判断力的最好方式,不是照模板写"设计一个短链接服务",而是逐个复盘那些真实、有名的系统,把背后的工程决策和你自己会做的选择一一对照。本文就带你走完一系列具体案例,以及每个案例背后可迁移的经验。

案例一:设计一个短链接服务(对标 Bitly)

短链接服务看起来很简单,实则暗藏很深。核心决策几乎全是约束驱动的。首先估算读写比例:典型的短链接服务都是重度读为主的,常常高达 100:1 甚至更高,所以写路径和读路径需要不同的形状。写入很少但要全局唯一,读取很频繁必须快且可缓存。

system-design-case-studies illustration

这里能迁移的三条经验是:

出人意料的是,短链接还藏着重定向分析、限流和滥用检测。因为每一条短链都会记录每一次重定向,你实际上在搭一根遥测管道,而不只是一张查询表。这也是它成为"读优化缓存 + 唯一 ID 生成 + 可观测性"绝佳教材的原因。

案例二:一个聊天服务(对标 Slack)

聊天应用会逼你做出设计面试里可能遇到的最重大的架构决策:同步投递(WebSocket / HTTP 长轮询)还是异步投递(消息队列)。这里没有放之四海皆准的正确答案,只有一组能把天平推向某一侧的约束。对顺序要求高的即时消息,你需要有序、低延迟的投递,那就倾向持久化的 WebSocket 连接加每个频道一条只追加日志。对必须扛住流量尖峰、要把生产者和消费者解耦的系统,Kafka 或 SQS 这类队列就更有吸引力。

system-design-case-studies illustration

更深的经验是"隔离"。聊天功能能干净地拆成:消息接入、投递扇出、在线状态、已读回执、搜索、文件附件——这些几乎是彼此独立的子系统。把这条边界画清楚,正是高级候选人的本事:每个子系统都能独立扩容、独立失败。尤其是"在线状态",这是面试官用来考察你在大规模下思连接状态的经典推送 vs 轮询题。

案例三:读密集的信息流(对标 Facebook)

信息流是扇出(fan-out)问题的教科书。用户发一条内容,要送到每个关注者的时间线上。两种经典策略划定了设计空间:写时扇出(push)读时扇出(pull),外加真实系统普遍用的混合方案。纯 push 意味着每次发帖都要向所有关注者的时间线写入——读很快,但对有几百万粉丝的账号来说写太贵。纯 pull 意味着每次读取都重新计算时间线——写简单,但对活跃用户读很慢、缓存压力大。

system-design-case-studies illustration

真实产品里的可行答案是混合:对活跃粉丝用 push,对有巨量粉丝的名人账号回退到读时 pull(通常在请求时把这份"名人浅列表"混进时间线)。这可以说是整个系统设计里最清晰地展示"没有唯一的正确答案,只有按成本做的取舍"的地方。只要内化了 push/pull/混合这套框架,你能把它用到远远超出信息流的范围——任何发布-订阅问题都继承了它。

案例四:一个分布式缓存(对标 Redis)

缓存是系统设计准备里你能带走的最划算的一课,因为它几乎出现在每一块白板上。真正的决策不是"我该不该加缓存",而是一层层往下走:缓存什么、缓存放哪(客户端、CDN、内存还是分布式)、用什么淘汰策略(LRU、LFU、TTL)、以及怎么处理失效。面试官会追问缓存击穿、cache-aside vs write-through vs write-back,而每种都有成本画像,值得你背得滚瓜烂熟。

system-design-case-studies illustration

具体来说,cache-aside(读穿透,应用在未命中时自己填缓存)是最常用的默认值。write-through 保持缓存新鲜但增加写延迟;write-back 改善写延迟却要在宕机时承担丢数据风险。能在一个约束下做出选择——"我们绝不能丢写" 还是 "写很少但读必须瞬间完成"——正是面试官要看的那种判断力。

案例五:大规模流媒体(对标 YouTube)

视频系统教给你:存储和带宽往往在 CPU 之前就主导了设计。关键决策有:一套多层存储策略,让热点数据住进快而贵的存储、冷数据迁到更便宜的分层(配合理性的生命周期策略);一个 CDN 把热门内容推到离用户更近的地方、减轻源站压力;以及一块分块策略,让客户端渐进式流式加载而非索取整个文件。这里的每一步,表面是技术决策,本质都是成本决策。

system-design-case-studies illustration

要提炼的模式是"按数据温度分解":把你的数据分成热、温、冷三档,每一档路由到专门设计的存储。这个单一框架同样出现在数据库设计、搜索索引和媒体管道里。只要你讲得清楚"按访问频率分层",你就能对一整类系统都说得头头是道。

可迁移的技能,以及接下来该怎么练

走完这五个案例,你就拥有了招聘官爱听的那套管语:读密集还是写密集、扇出模型、缓存失效、横向还是纵向扩容、数据分层。但别停在"读"上——凭记忆把每个架构重画一遍,并练习在面试官抛出的某个具体约束下捍卫你的一个设计选择。想先把这些决策背后的基础打牢,先看本站的系统设计基础,再走完完整的系统设计面试实战问答流程。既然很大一部分线上服务都跑在 Linux 上,本站的Docker 入门指南对理解这些设计的部署与运维一侧也很有用。

平台 / 工具核心特点价格(人民币约数)
阿里云 / 腾讯云(对标 AWS)云主机 ECS、对象存储 OSS、托管 Redis、云数据库 RDS、CDN按量付费;新用户常有几个月免费或低至几元/月的轻量套餐
Redis(云托管)内存缓存、淘汰策略、发布订阅、集群免费额度约 30MB;付费版按容量约每月 ¥100 起
Apache Kafka分布式事件日志、有序投递、流处理开源免费;商业托管版有免费额度
腾讯云 / 阿里云 CDN边缘缓存、DDoS 防护、全国节点有免费额度;进阶版每月几十元起
PostgreSQL(自建或云托管)关系存储、事务、JSONB、只读副本水平扩展云托管最低档每月约 ¥50 起;也有免费额度

系统化思维在大厂面试之外的用武之地

赢下设计面试的那套拆解习惯,同样驱动着真实的产品工程:决定什么时候分库分表、什么时候该在服务之间插一条队列、怎么缓存才不会有脏读。你甚至能把系统级思维用到非工程流程上——让媒体管道稳定的分区与优先级逻辑,和人们用来跑合规的个人流程用的是同一套结构。在一个领域建立起设计功力,会让你在所有领域都更敏锐。这些拆解与优先级排序的思路,和本站的数据分析入门里提到的"先定位瓶颈、再逐层调优"是同一种方法论。

常见问题

设计题里,怎么在关系型数据库和 NoSQL 之间做选择?

从你的访问模式出发,而不是从潮流出发。先问:数据有没有严格的关系和事务需求(偏关系型);要不要在高写入量下用灵活 schema(偏文档型);你的访问是不是读为主、主要通过主键查询(键值缓存加数据库就很合适)。很多真实系统都是"关系库当数据源真相 + 缓存或专用存储负责热点访问",所以"二选一"往往是个伪命题。

没给任何数字时,怎么估算流量和存储?

做保守的数量级假设并明确标注。比如没特别说明时按百万级而非十亿级用户估;估算每个用户每天的请求数;用 QPS =(用户数 × 每日请求)/86400,再乘 5~10 倍的峰值系数。存储方面,用单条大小 × 数量并选一个保留周期。面试官看重的更多是你的推理过程和显式假设,而不是精确到位的数字。

快速提升白板系统设计的捷径是什么?

带计时器和模拟面试官做刻意练习,然后对着标准组件清单(负载均衡、缓存、数据库、队列、CDN、服务边界)复盘。闷头做题远不如把你的推理"说"出来并接受挑战有效。数据工程基础里提供的结构化练习思路,能给你这种被追问的练习循环。

设计答案要说多细?

先给大局,只在面试官跟进的地方深入。头几分钟讲清高层架构,然后挑两三个面试官感兴趣的组件展开——通常是缓存、数据存储和某个瓶颈。对不感兴趣的面试官讲太细浪费时间,讲太浅又显得肤浅。跟着面试官的兴趣点走是最强信号。

要不要死记硬背服务器的数量或缓存大小之类的具体数字?

不要背,要推导。具体数值远没有量级和背后的推理重要。面试官想看你能不能估,而不是背了一张参考表。在追问下能基于你的假设当场重算出大概数值,远比背出一个听着精确却没法自圆其说的数字让人印象深刻。

📌 Pinterest 🐦 Twitter 📘 Facebook