Table of Contents
Open Table of Contents
概览
系统设计面试往往令人生畏,因为它的题目可能非常模糊。这同时也意味着它具有开放性,最重要的不是拿出一个完美的设计方案,而是在面试的过程中展现出自己的思考过程和解决问题的能力。
面对一个系统设计问题,我们可以按以下几个步骤来应对:
- 理解问题并确定设计的边界
- 提议高层级的设计并获得认同
- 设计继续深入
- 总结
理解问题并确定设计的边界
在系统设计面试中,不假思索快速给出答案并不会为你加分。在没有彻底了解需求之前就回答问题是面试中的大忌,因为面试不是知识问答竞赛,它没有正确答案。
在面试的开始,我们需要理解问题的背景和边界。这个过程中,我们需要问一些问题来澄清问题的背景和边界。比如:
- 我们要构建什么样的具体功能?
- 该产品有多少用户?
- 公司预计多久需要扩展系统?预计3个月、6个月和1年后的系统规模是怎样的?
- 公司的技术栈是什么?有哪些现有服务可以直接用来简化设计
如果我们被要求设计一个新闻流系统,可以先问这几个问题:
- 这是一个移动应用,还是一个网页应用?或者都是?
- 这个产品最重要的功能是什么?
- 系统中的帖子按什么顺序排列?
- 一个用户可以有多少好友?
- 网络流量有多少?
- 帖子中包含什么内容?图片、视频、文字,还是都有?
提议高层级的设计并获得认同
在这一步中,我们需要制定高层级的设计。需要深入到什么粒度取决于具体的问题。如果要设计一个扑克游戏的后端,那没设计方案中可以包含 API 端点的设计。但如果是设计一个很大的系统,例如一个搜索引擎,那么这些内容的层级就太细了。
我们可以制定一个初始蓝图,在白板或者纸上画出关键组件的架构图,并征求面试官的反馈。
可以思考一些具体的用例,通过这些用例我们可能会发现一些之前没考虑到的极端场景。
有时候我们需要使用封底计算来评估系统容量或者性能需求,甚至会影响到我们的技术选型。Jeff Dean 在其2010年的文章中揭示了典型计算机操作的时长,我们可以参考这些数据来进行封底计算:
操作名称 | 耗时 |
---|---|
L1 cache 引用 | 0.5 ns |
分支预测失误 | 5ns |
L2 cache 引用 | 7 ns |
Mutex lock/unlock | 100 ns |
主内存引用 | 100 ns |
使用Zippy压缩1K Byte | 10 μs |
通过1 Gbps网络发送2K字节 | 20 μs |
从内存中按顺序读取1 MB | 250 μs |
同一数据中心内往返 | 500 μs |
磁盘搜索 | 10 ms |
从网络中按顺序读取1MB | 10ms |
从磁盘按顺序读取1 MB | 30 ms |
发送数据包 CA(加利福尼亚州)->荷兰->CA | 150ms |
服务可用性也是一个重要的指标,一般用百分比来衡量,大部分服务的可用性在 99% 到 100% 之间,正常运行时间通常是用小数点后 “9” 的个数来衡量的。“9” 越多则代表可用性越高。下表出了 “9” 的数量与系统预计不可用时长的关系。
可用性(百分比) | 每天不可用时长 | 每年不可用时长 |
---|---|---|
99% | 14.40分钟 | 3.65天 |
99.9% | 1.44 分钟 | 8.77 小时 |
99.99% | 8.64秒 | 52.60分钟 |
99.999% | 864.00毫秒 | 5.26分钟 |
99.9999% | 86.40毫秒 | 31.56秒 |
设计继续深入
在这一步中,我们应该和面试官一起识别架构中的组件及其优先级。我们尽量不要陷入不必要的细节讨论,避免占用太多面试时间,从而无法展示设计可扩展系统的能力。
我们可以针对应用中最重要的用例进行探讨,可能会用到流程图来描述应用的关键组件如何参与到这个用例的流程中。例如新闻流系统中,用户获取新闻流的流程可以这样描述:
- 用户使用浏览器或者移动应用向 DNS 服务查询应用网关地址
- 用户访问应用网关
- 应用网关根据负载均衡机制将请求转发到对应的 web 服务器
- web 服务器根据限流逻辑判断是否放行请求
- web 服务器验证请求身份
- web 服务器访问新闻流缓存
- 如果缓存存在数据则直接返回
- 否则从数据库读取数据加载到缓存中,并返回
总结
最后一步我们需要回答面试官提出的问题,例如:
- 讨论系统中存在的问题、瓶颈以及潜在的改进方案
- 复述我们提出的设计方案如何解决问题
- 针对现有方案如何扩展
- 监控、日志手机、发布系统等运维相关的问题