2024-03-10 第十周:搞定系统设计
流水账
- 第一次遇到如此凶猛的回南天,在门窗紧闭的情况下,靠南的房间墙和天花板还是滴水了,被子枕头都湿了。还好周三晚上开始转北风,但周末又开始下雨。后面也许还有回南天,下次得记得先把空调打开。
- 开始学 eBPF 了,看了几天资料,找出老电脑装了一个ubutun来练手,但周末几乎没时间折腾。
- 看了电影 《周处除三害》,既有视觉血浆爽片的观感也有过度解读的深意。在流量,烂片的时代难得的好电影。
- 韶音耳机坏了,淘宝找到一家附近的维修店花了200修好了。说起来这个耳机也用五年了。
- 忙里偷闲踢了一次球,终于进了两个球,还有助攻,好爽。
阅读
《搞定系统设计:面试敲开大厂的门》
- 看过原版,再次看中文版说实话感觉内容比较乏味,说白了就是八股文。可以提供一个基本的思路和方法论,真正要做相关的系统设计还是要复杂得多。
一点想法
- 前面说 《搞定系统设计:面试敲开大厂的门》 乏味,是实话,不过书中第二章第三章也可以给面试和平时工作思考提供一些方法论的。诸如系统设计问题的回答套路,一些指标值的快速估算思路。学到一个概念 Back-of-the-Envelope Estimation ,是 Jeff Dean 提出来的概念,意思是“你想象中的实验和常见性能指标数据结合而得出的一些估算值,这些值使你对何种设计可以满足系统需求有初步的概念。” 翻译成“封底估算” 有点奇怪的感觉,实质上是指粗略估计,寓意是随便找一张废纸(如信封底)来计算即可。
相关性的数据
2 的幂
通过这种估算可以快速换算成我们熟悉存储单位。
2的幂 | 近似值 | 缩写 |
---|---|---|
$2^{10}$ | 1000 | 1 KB |
$2^{20}$ | 1,000,000 | 1 MB |
$2^{30}$ | 1,000,000,000 | 1 GB |
$2^{40}$ | 1,000,000,000,000 | 1 TB |
$2^{50}$ | 1,000,000,000,000,000 | 1 PB |
每个程序员该知道的操作耗时
操作名称 | 耗时 |
---|---|
查询 L1 缓存 | 0.5 ns |
分支预测错误 | 5 ns |
查询 L2 缓存 | 7 ns |
互斥锁定 / 解锁 | 100 ns |
查询内存 | 100 ns |
用 Zippy 压缩 1 KB 数据 | 10,000 ns = 10 us |
通过带宽为1 GB / s 的网络发送 2 KB 数据 | 20,000 ns = 20 us |
从内存中顺序读取 1 MB 数据 | 250,000 ns = 250 us |
数据在同一个数据中心往返一次 | 500,000 ns = 500 us |
在硬盘中查找数据 | 10,000,000 ns = 10 ms |
从网络中顺序读取 1 MB 数据 | 10,000,000 ns = 10 ms |
从硬盘中顺序读取 1 MB 数据 | 30,000,000 ns = 30 ms |
将数据包从加州发送至荷兰,再从荷兰返回加州 | 150,000,000 ns = 150 ms |
可用性相关的数字
这个数据其实也不用记,可以直接计算,比如 4 个 9 每年不可用时间。
365 * 24 * 60 * (100 - 99.99)
可用性(百分比) | 每天不可用时长 | 每年不可用时长 |
---|---|---|
99 % | 14.4 分钟 | 3.65 天 |
99.9 % | 1.44 分钟 | 8.77 小时 |
99.99 % | 8.64 秒 | 52.6 分钟 |
99.999 % | 864.00 毫秒 | 5.26 分钟 |
99.9999 % | 86.4 毫秒 | 31.56 秒 |
总之,熟悉掌握这些数据或者数据的计算方法可以快速估算出一些系统指标。
系统设计面试的框架
书中总结为4个步骤
第一步 理解问题并确定设计边界 (3 - 10 分钟)
- 要构建什么样的功能?
- 该产品有多少用户?
- 公司预计多久要扩展系统?
- 公司的技术栈是什么?有哪些现有服务可以直接用?
第二步 High Level 设计 (10 - 15 分钟)
- 为设计制定一个初始蓝图。
- 在白板或者纸上用关键组件画出框图,可能包括客户端、API、Web 服务、数据存储、缓存、CDN、消息队列等。
- 做封底估算,评估你的初步设计是否满足系统需求。
第三步 设计继续深入 (10 - 25 分钟)
- 就系统的整体目标和功能范围,与面试官达成一致。
- 勾画出系统整体设计的高层级蓝图。
- 从面试官那里得到关于系统高层级设计的反馈。
- 基于面试官的反馈,大概知道自己需要在哪些地方继续深入研究。
第四步 总结 (3 - 5 分钟)
- 展示批判性思维,识别出系统的瓶颈并讨论潜在的改进方案。
- 给面试官复述你的设计方案是有用的。
- 故障场景(如服务器故障、数据包丢失等)值得讨论。
- 运维问题讨论。
- 怎样应对下一次扩展。
- 如果还有时间,可以提出其他改进点。