提交 f4e5f004 编写于 作者: W wizardforcel

2023-05-03 14:56:06

上级 7e668085
......@@ -27,127 +27,11 @@
+ [CEH↗](https://github.com/apachecn/interview-books/tree/master/CEH)
+ [PMP↗](https://github.com/apachecn/interview-books/tree/master/PMP)
+ [职位数据库↗](https://github.com/apachecn/interview-books/tree/master/%E8%81%8C%E4%BD%8D%E6%95%B0%E6%8D%AE%E5%BA%93)
+ [面试译文集↗](https://itvw.apachecn.org)
+ [牛客面试题库↗](https://github.com/apachecn/interview-books/tree/master/NowCoder)
+ [GitHub快速入门](docs/GitHub/README.md)
+ [技术面试手册](docs/tech-inter-hb/README.md)
+ [介绍](docs/tech-inter-hb/01.md)
+ [软件工程师面试:你需要准备的一切](docs/tech-inter-hb/02.md)
+ [获得面试机会](docs/tech-inter-hb/03.md)
+ [为 FAANG 撰写软件工程师简历实用指南](docs/tech-inter-hb/04.md)
+ [编码面试准备](docs/tech-inter-hb/05.md)
+ [编码面试:你需要准备的一切](docs/tech-inter-hb/06.md)
+ [使用哪种编程语言编写面试代码](docs/tech-inter-hb/07.md)
+ [编写面试学习计划——根据剩余时间学习和练习什么](docs/tech-inter-hb/08.md)
+ [编码面试备忘单:事前、事中和事后的最佳实践](docs/tech-inter-hb/09.md)
+ [处理和解决编码面试问题的顶级技巧](docs/tech-inter-hb/10.md)
+ [软件工程师最佳模拟编码面试平台](docs/tech-inter-hb/11.md)
+ [顶尖科技公司如何在编码面试中评估候选人](docs/tech-inter-hb/12.md)
+ [系统设计面试准备](docs/tech-inter-hb/13.md)
+ [软件工程师系统设计面试指南](docs/tech-inter-hb/14.md)
+ [行为面试准备](docs/tech-inter-hb/15.md)
+ [软件工程师的行为面试:如何准备](docs/tech-inter-hb/16.md)
+ [30 个最常见的软件工程师行为面试问题](docs/tech-inter-hb/17.md)
+ [软件工程师面试:打造完美的自我介绍](docs/tech-inter-hb/18.md)
+ [软件工程师面试:面试结束时最好问的问题](docs/tech-inter-hb/19.md)
+ [薪金和聘用谈判准备](docs/tech-inter-hb/20.md)
+ [了解薪酬](docs/tech-inter-hb/21.md)
+ [谈判](docs/tech-inter-hb/22.md)
+ [谈判的十大规则](docs/tech-inter-hb/23.md)
+ [在公司之间选择](docs/tech-inter-hb/24.md)
+ [算法研究备忘单](docs/tech-inter-hb/25.md)
+ [数据结构和算法研究编码面试备忘单](docs/tech-inter-hb/26.md)
+ [基础](docs/tech-inter-hb/27.md)
+ [用于编码面试的数组备忘单](docs/tech-inter-hb/28.md)
+ [用于编码面试的字符串速查表](docs/tech-inter-hb/29.md)
+ [用于编码面试的散列表清单](docs/tech-inter-hb/30.md)
+ [编码面试的递归备忘单](docs/tech-inter-hb/31.md)
+ [为面试编码排序和搜索备忘单](docs/tech-inter-hb/32.md)
+ [数据结构](docs/tech-inter-hb/33.md)
+ [编码面试的矩阵备忘单](docs/tech-inter-hb/34.md)
+ [编码面试的链接列表备忘单](docs/tech-inter-hb/35.md)
+ [用于编码面试的队列备忘单](docs/tech-inter-hb/36.md)
+ [用于编码面试的堆栈备忘单](docs/tech-inter-hb/37.md)
+ [编码面试的间隔备忘单](docs/tech-inter-hb/38.md)
+ [高级数据结构](docs/tech-inter-hb/39.md)
+ [编码面试的树形清单](docs/tech-inter-hb/40.md)
+ [用于编码面试的图表备忘单](docs/tech-inter-hb/41.md)
+ [为编码面试堆备忘单](docs/tech-inter-hb/42.md)
+ [编码面试的备忘单](docs/tech-inter-hb/43.md)
+ [附加项](docs/tech-inter-hb/44.md)
+ [编码面试的动态编程备忘单](docs/tech-inter-hb/45.md)
+ [编码面试的二进制备忘单](docs/tech-inter-hb/46.md)
+ [编码面试的数学备忘单](docs/tech-inter-hb/47.md)
+ [编码面试的几何备忘单](docs/tech-inter-hb/48.md)
+ [杂项](docs/tech-inter-hb/49.md)
+ [顶级公司的面试形式](docs/tech-inter-hb/50.md)
+ [备忘单(面试官)](docs/tech-inter-hb/51.md)
+ [前景](docs/tech-inter-hb/52.md)
+ [工程水平](docs/tech-inter-hb/53.md)
+ [最佳编码面试课程](docs/tech-inter-hb/54.md)
+ [最佳实践问题](docs/tech-inter-hb/55.md)
+ [前端面试手册](docs/fe-inter-hb/README.md)
+ [介绍](docs/fe-inter-hb/01.md)
+ [琐碎问题](docs/fe-inter-hb/02.md)
+ [编码](docs/fe-inter-hb/03.md)
+ [前端面试中的 JavaScript 实用函数编码](docs/fe-inter-hb/04.md)
+ [前端访谈中的用户界面编码](docs/fe-inter-hb/05.md)
+ [前端面试中的编码算法](docs/fe-inter-hb/06.md)
+ [系统设计面试](docs/fe-inter-hb/07.md)
+ [前端系统设计面试概述](docs/fe-inter-hb/08.md)
+ [前端系统设计面试-用户界面组件](docs/fe-inter-hb/09.md)
+ [前端系统设计面试-应用](docs/fe-inter-hb/10.md)
+ [行为面试](docs/fe-inter-hb/11.md)
+ [简历准备](docs/fe-inter-hb/12.md)
+ [公司面试问题](docs/fe-inter-hb/13.md)
+ [谷歌前端面试问题](docs/fe-inter-hb/14.md)
+ [亚马逊前端面试问题](docs/fe-inter-hb/15.md)
+ [Microsoft 前端面试问题](docs/fe-inter-hb/16.md)
+ [苹果前端面试问题](docs/fe-inter-hb/17.md)
+ [Airbnb 前端面试问题](docs/fe-inter-hb/18.md)
+ [字节舞/titok 前端面试问题](docs/fe-inter-hb/19.md)
+ [Dropbox 前端面试问题](docs/fe-inter-hb/20.md)
+ [LinkedIn 前端面试问题](docs/fe-inter-hb/21.md)
+ [Lyft 前端面试问题](docs/fe-inter-hb/22.md)
+ [Salesforce 前端面试问题](docs/fe-inter-hb/23.md)
+ [Twitter 前端面试问题](docs/fe-inter-hb/24.md)
+ [优步前端面试问题](docs/fe-inter-hb/25.md)
+ [系统设计面试的行家指南](docs/sys-design-inter/README.md)
+ [零、序言](docs/sys-design-inter/00.md)
+ [一、从零扩展到数百万用户](docs/sys-design-inter/01.md)
+ [二、信封背面估计](docs/sys-design-inter/02.md)
+ [四、设计速率限制器](docs/sys-design-inter/03-1.md)
+ [三、系统设计面试的框架](docs/sys-design-inter/03.md)
+ [五、设计一致哈希](docs/sys-design-inter/04.md)
+ [六、设计键值存储](docs/sys-design-inter/05.md)
+ [七、设计分布式系统中的唯一 ID 生成器](docs/sys-design-inter/06.md)
+ [八、设计 URL 缩短器](docs/sys-design-inter/07.md)
+ [九、设计网络爬虫](docs/sys-design-inter/08.md)
+ [十、设计通知系统](docs/sys-design-inter/09.md)
+ [十一、设计新闻订阅系统](docs/sys-design-inter/10.md)
+ [十二、设计聊天系统](docs/sys-design-inter/11.md)
+ [十三、设计搜索自动补全系统](docs/sys-design-inter/12.md)
+ [十四、设计 YouTube](docs/sys-design-inter/13.md)
+ [十五、设计谷歌云盘](docs/sys-design-inter/14.md)
+ [十六、继续学习](docs/sys-design-inter/15.md)
+ [十七、后记](docs/sys-design-inter/16.md)
+ [方十字应试](docs/方十字应试/README.md)
+ [方十字学习观(精简版)[本质论,认识论,方法论]](docs/方十字应试/01.md)
+ [方十字应试学习观(完整版)[本质论,认识论,方法论]](docs/方十字应试/02.md)
+ [思维导图的本质与全内容思维导图[认识论,方法论]](docs/方十字应试/03.md)
+ [应试数学的5级习题训练体系[应试方法论]](docs/方十字应试/04.md)
+ [基于艾宾浩斯记忆曲线的学习日志说明书[应试方法论]](docs/方十字应试/05.md)
+ [一种便捷的错题本制作方法[应试方法论]](docs/方十字应试/06.md)
+ [方十字主观实践认识论[认识论]](docs/方十字应试/07.md)
+ [一个简单的应试英语(阅读,单词)学习方法[应试方法论]](docs/方十字应试/08.md)
+ [高考/考研数学的5级习题评级系统配套的模块化刷题策略[应试方法论]](docs/方十字应试/09.md)
+ [【总论】方十字应试学习矛盾分析体系](docs/方十字应试/10.md)
+ [方十字应试学习体系总介绍](docs/方十字应试/11.md)
+ [方十字应试学习管理方案](docs/方十字应试/12.md)
+ [方十字参考主义计划观](docs/方十字应试/13.md)
+ [如何在应试学习中理解信息](docs/方十字应试/14.md)
+ [第五版记忆曲线学习日志使用说明书](docs/方十字应试/15.md)
+ [导师评价网备份↗](https://rms.apachecn.org/#/)
+ [校招污点公司记录↗](https://github.com/ShameCom/ShameCom)
+ [独立开发/自由职业/远程工作/数字游民知识库↗](https://idw.apachecn.org/#/)
+ [贡献者名单](CONTRIBUTORS.md)
+ [GitHub快速入门](docs/GitHub/README.md)
+ [导师评价网备份↗](https://rms.apachecn.org/#/)
+ [校招污点公司记录↗](https://github.com/ShameCom/ShameCom)
+ [独立开发/自由职业/远程工作/数字游民知识库↗](https://idw.apachecn.org/#/)
+ [贡献者名单](CONTRIBUTORS.md)
# 介绍
> 原文:<https://www.frontendinterviewhandbook.com/introduction/>
## 这是什么?[](#what-is-this "Direct link to heading")
与典型的软件工程师工作面试不同,前端面试不太强调算法,更多的问题是关于前端领域的复杂知识和专业知识——HTML,CSS,JavaScript,等等。
许多前端面试高度关注领域知识,并将它们应用到现实世界的场景中。你可能会发现,当你面试一个前端职位的时候,光是埋头苦读并不足够,但这是一件好事!前端面试倾向于测试更实用的概念,并与真实世界前端开发相关。但这并不意味着你不需要熟悉基本的数据结构和算法概念——只是不太强调它们,可能你会得到更简单的算法问题。
虽然有一些现有的资源可以帮助前端开发人员准备面试,但它们不像软件工程师面试的材料那样丰富。在现有的资源中,最有帮助的题库可能是[前端开发人员面试问题](https://github.com/h5bp/Front-end-Developer-Interview-Questions)。不幸的是,这些问题在网上没有太多完整和令人满意的答案。这本手册回答了这些琐事式的问题,以及其他前端面试形式的信息和指导。
然而,我最近使用并评论了 [Great Front End](https://www.greatfrontend.com?utm_source=frontendinterviewhandbook&utm_medium=referral&utm_content=introduction&fpr=frontendinterviewhandbook) ,一个自称为“前端面试 LeetCode”的平台。它包含由前 FAANG 高级工程师编写的前端面试问题和答案,并有各种格式的问题和答案:编码和琐事风格的前端问题。我发现它非常有用,我强烈推荐你去看看!
## 前端面试的一般技巧[](#general-tips-for-front-end-interviews "Direct link to heading")
不管给你的是哪种形式,有一件事是真的——你需要在你的前端基础上非常强大,并不断向你的面试官展示你对它们的掌握。
非常熟悉以下概念:
* CSS:特异性,盒子模型,布局,定位
* JavaScript: `this`关键字、原型、闭包、异步代码、承诺、定时器(`setTimeout``setInterval`)
* JavaScript 设计模式:观察者模式、模块模式
* HTML:事件委托(几乎在每个面试中都很有用)、DOM 遍历、DOM 操作、表单验证和提交
* 至少是普通的 JS 或 jQuery。并不是所有的面试都允许你使用 React,因为他们希望看到对基础知识的掌握
在 Glassdoor 上寻找公司的面试问题。前端问题并不丰富,但仍然可以找到一些。很多公司都用类似的问题。
## 前端面试格式[](#front-end-interview-formats "Direct link to heading")
与软件工程面试不同,前端面试的形式不太为人所知,在整个行业中也没有标准化。我们努力在网上搜索热门公司提出的前端面试问题,有些问题经常出现。一般来说,您应该熟悉以下问题和格式:
### 琐事问题[](#trivia-questions "Direct link to heading")
测试你的知识并有清晰的非主观答案的简短问题。招聘人员通常会问这些问题,因为即使是非技术人员也可以验证答案的准确性。以下是一些例子:
* Java Script 语言
* 什么是终结?
* 承诺和回拨有什么区别?
* 解释 JavaScript 中的`this`关键字。
* 半铸钢ˌ钢性铸铁(Cast Semi-Steel)
* CSS 盒子模型是什么?
* 各种 CSS `position`属性及其差异。
[**阅读更多关于前端琐事提问→**](/trivia/)
### JavaScript 编码[](#javascript-coding "Direct link to heading")
这是 LeetCode 风格的算法题的前端版本。在 JavaScript 中实现一个函数,可以是 Lodash/下划线中的实用函数(如`throttle`),也可以是 JavaScript 语言/DOM API 的 polyfill(如`Array.prototype.filter``Promise.all``document.getElementsByClassName()`)。
* 实现`Array.prototype`功能:`map``reduce``filter``sort`
* 实现 DOM API:`getElementsByClassName`
* `debounce` / `throttle`
* 实现承诺/承诺相关 API:`Promise``Promise.all`
### 用户界面编码[](#user-interface-coding "Direct link to heading")
使用 HTML、CSS 和 JavaScript 构建用户界面(可以是 UI 组件、应用程序或游戏)。
* 成分
* 自动完成(**非常流行**)
* 图片库
* 图像传送带
* 工具提示组件
* 星级小工具
* 应用程序
* 构建井字游戏
* 用可移动的棋子搭建棋盘
[**了解更多前端编码问题→**](/coding/algorithms/)
### 算法编码[](#algorithm-coding "Direct link to heading")
LeetCode 风格的算法编码问题,评估你的核心数据结构和算法技能。你可以被问到任何关于 LeetCode 的问题,可能会被要求用 JavaScript 解决这些问题。
### 系统设计[](#system-design "Direct link to heading")
描述并讨论你将如何构建一个 UI 组件/应用/游戏及其架构。这是系统设计问题的前端版本。例如,描述您将如何在聊天应用程序中构建表情符号自动完成功能,它将具有哪些 API,该功能有哪些组件,如何确保它具有良好的性能,UX 等。
* 设计一个图像转盘组件。
* 设计一个电子邮件客户端应用程序。
[**了解更多前端系统设计→**](/front-end-system-design/)
Be interview-ready with Great Front End
[大前端](https://www.greatfrontend.com/?fpr=frontendinterviewhandbook)有各种前端面试问题的问答,[学习计划](https://www.greatfrontend.com/get-started?fpr=frontendinterviewhandbook),还有[庞大的题库](https://www.greatfrontend.com/questions/coding?fpr=frontendinterviewhandbook)
## 公司面试格式[](#company-interview-formats "Direct link to heading")
通过广泛的研究,以下是公司在前端面试的技术回合中询问的不同类型的格式。如果你在面试某些公司的前端工程职位,做好相应的准备!
*图注:✅:问过,❌:没问过,⚠️:没有数据*
| 公司 | 琐事 | 算法 | JavaScript 编码 | UI 编码 | 系统设计 |
| :-- | :-: | :-: | :-: | :-: | :-: |
| [**Airbnb**](/companies/airbnb-front-end-interview-questions/) | -好的 | 981 号房 | 981 号房 | 981 号房 | -好的 |
| [**亚马逊**](/companies/amazon-front-end-interview-questions/) | 981 号房 | 981 号房 | 981 号房 | 981 号房 | 981 号房 |
| [**苹果**T3】](/companies/apple-front-end-interview-questions/) | ⚠️ | ⚠️ | 981 号房 | 981 号房 | ⚠️ |
| [**【字节舞/tik Tok】**](/companies/bytedance-tiktok-front-end-interview-questions/) | 981 号房 | 981 号房 | 981 号房 | 981 号房 | -好的 |
| [**收纳箱**](/companies/dropbox-front-end-interview-questions/) | -好的 | ⚠️ | 981 号房 | 981 号房 | 981 号房 |
| Facebook/Meta | 981 号房 | -好的 | 981 号房 | -好的 | 981 号房 |
| Flipkart | ⚠️ | 981 号房 | ⚠️ | ⚠️ | ⚠️ |
| [**谷歌**](/companies/google-front-end-interview-questions/) | 981 号房 | 981 号房 | 981 号房 | 981 号房 | 981 号房 |
| [**领英**T3】](/companies/linkedin-front-end-interview-questions/) | 981 号房 | ⚠️ | 981 号房 | 981 号房 | ⚠️ |
| [升升](/companies/lyft-front-end-interview-questions/) | -好的 | -好的 | 981 号房 | 981 号房 | ⚠️ |
| [**微软**T3】](/companies/microsoft-front-end-interview-questions/) | 981 号房 | 981 号房 | 981 号房 | 981 号房 | ⚠️ |
| [**sales force**T3】](/companies/salesforce-front-end-interview-questions/) | 981 号房 | ⚠️ | ⚠️ | ⚠️ | ⚠️ |
| [**推特**](/companies/twitter-front-end-interview-questions/) | 981 号房 | ⚠️ | 981 号房 | 981 号房 | ⚠️ |
| [**优步**](/companies/uber-front-end-interview-questions/) | ⚠️ | ⚠️ | 981 号房 | 981 号房 | ⚠️ |
# 琐碎问题
\ No newline at end of file
# 编码
原文:[https://www.frontendinterviewhandbook.com/coding/](https://www.frontendinterviewhandbook.com/coding/)
\ No newline at end of file
# 前端面试中的 JavaScript 实用函数编码
> 原文:<https://www.frontendinterviewhandbook.com/coding/javascript-utility-function/>
这些是 LeetCode 问题的前端版本,但不太强调复杂的算法,更专注于实际用例。然而,它们也可能是简单的 LeetCode 问题,但是需要用 JavaScript 来回答。
几乎所有现有的实用函数都存在于 JavaScript 语言或著名的第三方库中,如 Lodash/下划线,其中最著名的是`debounce``throttle`。然而,Lodash 的实现是极度过度工程化的——重用了许多抽象函数,并支持旧浏览器的怪异和晦涩的用例,你不应该在采访中产生这样的复杂程度。
## 基本示例[](#basic-examples "Direct link to heading")
* 实现`Array.prototype`功能:`map``reduce``filter``sort`
* 实现承诺/承诺相关 API:`Promise``Promise.all`
* 实现 Lodash 功能:`debounce()``throttle()``cloneDeep()``groupBy()`
* 洛达什的`chunk()` / `map()`,接着是`mapAsync` ( `Promise.all`),然后是`mapWithChunksAsync`
* 将对象中的所有键转换为 snake_case/camelCase
* `document.querySelectorAll`(仅限于标签选择器)
* [观察者模式](https://addyosmani.com/resources/essentialjsdesignpatterns/book/#observerpatternjavascript)
最好的准备方式是亲自动手实现它们,并为它们编写测试用例。
虽然这类问题的焦点不在算法上,但也要注意数据结构的选择和时间复杂度。如果在哈希映射的帮助下可以很容易地用 O(n)编写一个函数,那么就不要编写一个在 O(n <sup>2</sup> 中运行的函数。
候选人预计会花大约 10-15 分钟来回答一个基本问题。如果你知道你收到了一个基本问题,试着在建议的时间内完成,不要故意花整个面试时间来做一个问题。在大多数情况下,你需要回答另一个编码问题。
## 进阶范例[](#advanced-examples "Direct link to heading")
高级问题通常是给更高级的候选人,预计大约 25-30 分钟完成或达成一个最低限度的工作解决方案。
* 编写一个模板引擎,执行变量替换和简单的条件。
* 执行`JSON.stringify()`
* 从 HTML 页面生成目录/大纲(类似于 Google Docs 自动生成的大纲)。
Practice questions on Great Front End
不确定如何开始?[大前端](https://www.greatfrontend.com/?fpr=frontendinterviewhandbook)有前端面试[学习计划](https://www.greatfrontend.com/get-started?fpr=frontendinterviewhandbook)和一个[编码题的庞大题库](https://www.greatfrontend.com/questions/coding?fpr=frontendinterviewhandbook)。今天就开始练习吧!
## 提示[](#tips "Direct link to heading")
* 始终努力编写纯函数,也就是不依赖于函数外部状态并且不会产生副作用的函数。
* 如果你正在写一个递归函数,问问是否有最大堆栈深度限制。
* 一些嵌套的数据结构可以递归引用自身。一定要澄清对象中没有自我参照/循环/询问你是否需要处理它们(通常答案是“没有”)。
# 前端访谈中的用户界面编码
> 原文:<https://www.frontendinterviewhandbook.com/coding/build-front-end-user-interfaces/>
许多前端工程师花费大量时间构建 UI,构建 UI 组件是评估某人对前端三个最大方面(HTML、JavaScript、CSS)熟悉程度的好方法。
问这种问题的公司通常会要求应聘者用以下三种方式之一进行编码:
* 带预览功能的在线编辑器:你可以在浏览器中编写 HTML、CSS、JavaScript,并看到页面的即时预览。常用的平台有 [CodePen](https://codepen.io)[CodeSandbox](https://codesandbox.io/dashboard)
* 没有预览的在线编辑器:与上面类似,但是你看不到页面的任何视觉输出。一个常见的平台是 [CoderPad](https://coderpad.io/) 。过去,谷歌使用谷歌文档😱。
* BYOE(自带环境):考生自带开发环境/笔记本电脑,可以自由选择是使用自己的编辑器进行本地开发,还是使用 CodePen 或 CodeSandbox 等在线环境。这是对候选人有利的最理想的情况,但通常只在现场进行。您通常可以使用 JavaScript 框架/库,在这种情况下,建议您使用工具来帮助您搭建一个全新的应用程序,您可以立即开始编码(例如`create-react-app``vue-cli`)。你不想在面试中花时间做不必要的准备工作,因为这不会给你的面试官额外的有用信号。
* 白板:考生要把所有需要的 HTML,JS,CSS 都写在白板上。没有预览,没有自动完成,没有在线文档来帮助你;你完全靠自己了。到目前为止,脸书和谷歌是仅有的两家让候选人在前端面试中写在白板上的公司。
## 例题[](#examples "Direct link to heading")
* 成分
* 制表符
* 手风琴
* 图片库
* 其他可能的组件- [参考 Bootstrap 列表](https://getbootstrap.com/docs/4.0/components/)
* 应用程序
* 可排序的数据表(带有过滤扩展)
* 所有列表
* 看板
* 比赛
* Tic-tac-toe
* 打地鼠
* 沃尔多
* 俄罗斯方块(高级)
* 蛇(高级)
Practice questions on Great Front End
不确定如何开始?[大前端](https://www.greatfrontend.com/?fpr=frontendinterviewhandbook)有前端面试[学习计划](https://www.greatfrontend.com/get-started?fpr=frontendinterviewhandbook)和一个[编码题的庞大题库](https://www.greatfrontend.com/questions/coding?fpr=frontendinterviewhandbook)。今天就开始练习吧!
## 注意事项[](#considerations "Direct link to heading")
完成问题后(甚至开始前),思考这些潜在的问题(如果相关的话)。你可能需要也可能不需要处理它们,所以你可以在开始之前和面试官澄清一下,这样你就不会写太多/太少的代码。
### 前端最佳实践[](#front-end-best-practices "Direct link to heading")
* 避免编写全局变量。将你的代码包装在一个[生命](https://developer.mozilla.org/en-US/docs/Glossary/IIFE)中,不要污染全局范围。
* 如果您需要在页面上有该组件的多个实例,该怎么办?
* 您的代码能让您做到这一点吗?
* 你是否使用了任何全局变量使你很难做到这一点?
* 在同一个页面上有多个组件会互相影响吗?他们应该是独立的!
* 你有一个方便的 API 来实例化带有可配置选项的独立组件吗?在 React 出现之前,老派的 jQuery UI 组件就是很好的例子。
### 性能和可扩展性[](#performance-and-scalability "Direct link to heading")
您的组件是否可扩展(延迟、性能、UI、UX 等)?
* 网络退东西时间太长怎么办?网速慢怎么测试?提示:Chrome Devtools 网络标签。
* 字符串太长怎么办?提示:CSS `word-break`属性。
* 图像太大怎么办?
* 组件可以包含任意数量的子项吗?示例:支持照片库组件中灵活数量的缩略图或选项卡导航组件中的项目。
* 如果这些项目太少或太多,布局会变得混乱吗?
* 物品太多怎么办?提示:设置最大高度或分页。
* 如果没有项目,你会显示什么?提示:显示一个空状态,表示没有内容。不要显示任何内容。
* 如果页面上的元素太多,性能会受到什么影响?你是怎么解决的?提示:[虚拟列表](https://medium.com/outsystems-engineering/virtualizing-the-virtual-dom-pushing-react-further-d76a16e5f209)
* 您是否硬编码了任何值,使得将来很难扩展到不断变化的需求?你设计了可扩展性吗?
### 网络请求[](#network-requests "Direct link to heading")
* 组件是否处理网络/异步请求中的竞争条件?例如,在返回对先前请求的响应之前,启动新的网络请求。
* 如果请求超时或出错怎么办?如何优雅地从中恢复?
* 如何提高组件的性能?你能利用缓存、延迟加载、预取/预加载吗?
* 如果需要加载大量数据/图像怎么办?你能延迟加载它们吗?您能批量获取数据以减少 API 端点的垃圾邮件吗?
### 用户体验[](#user-experience "Direct link to heading")
* 该组件是移动友好的吗?该组件能适应不同的屏幕宽度吗?如何让它变得对移动设备友好?
* 该组件容易安装吗?如何改变设计来迎合 i18n?你的组件支持 RTL 语言吗?
* 您的组件是否存在任何潜在的 UX/可访问性(a11y)问题?
* 有哪些常见的可访问性技术和陷阱?
* [https://medium . com/@ addyosmani/accessible-ui-components-for-the-web-39e 727101 a67](https://medium.com/@addyosmani/accessible-ui-components-for-the-web-39e727101a67)
* 您可以使用哪些工具来检查可访问性?
* 如果你不熟悉 a11y,你可能没有太多时间成为 a11y 的专家。你至少可以承认 a11y 中的知识缺口,并尝试将 a11y 纳入你的答案中。你至少应该了解基本的 a11y 实践,如文本大小、颜色对比、可聚焦元素、标签聚焦顺序等。a11y 知识是初级工程师和高级工程师之间的区别因素之一。
### 安全[](#security "Direct link to heading")
* XSS 的弱点。每当你需要呈现用户输入时,面试官都会特别留意这一点。你几乎不需要使用`.innerHTML`或者 jQuery 的`$.html()`。有`.textContent``$.text()`。如果您必须呈现原始 HTML,请确保首先对内容进行转义。
* 显示在 URL 中的用户输入也必须首先进行编码,否则也有可能造成损害。
### 未来[](#future "Direct link to heading")
最后,提到如果你有更多的时间,并且正在编写你需要维护的产品代码,你会如何做不同的事情。也许使用 Sass 而不是 CSS,使用 React 而不是 jQuery 以获得更好的可维护性,使用 Babel 为旧浏览器编译代码,使组件移动友好并在不同的屏幕宽度上测试,添加键盘快捷键,等等。
# 前端面试中的编码算法
> 原文:<https://www.frontendinterviewhandbook.com/coding/algorithms/>
前端工程师毕竟也是软件工程师,前端工程师应该具备算法和数据结构方面的基本能力。在你的前端面试中,你将被要求解决算法问题,这是可能的,也是合理的,而且最有可能的是,你将被期望使用 JavaScript。
树是前端开发中经常遇到的数据结构,因为 DOM 是一棵树,所以如果你必须区分优先级,一定要专注于擅长树数据结构和树的通用算法,比如广度优先搜索和深度优先搜索。
《技术面试手册》详细介绍了如何准备算法问题。
[Go to Tech Interview Handbook  →](https://www.techinterviewhandbook.org/algorithms/study-cheatsheet/)
## 算法课程[](#algorithm-courses "Direct link to heading")
### [AlgoMonster](https://shareasale.com/r.cfm?b=1873647&u=3114753&m=114505&urllink=&afftrack=)[T3】](#algomonster "Direct link to heading")
AlgoMonster 旨在帮助你在最短的时间内通过技术面试。由谷歌工程师开发的 AlgoMonster 使用数据驱动的方法来教你最有用的关键问题模式,并有内容帮助你快速修改基本的数据结构和算法。最重要的是,AlgoMonster 不是基于订阅的——支付一次性费用,就可以获得**终身访问**[**检查一下→**](https://shareasale.com/r.cfm?b=1873647&u=3114753&m=114505&urllink=&afftrack=)
### [寻找编码面试:编码问题的模式](https://designgurus.org/link/kJSIoU?url=https%3A%2F%2Fdesigngurus.org%2Fcourse%3Fcourseid%3Dgrokking-the-coding-interview)[](#grokking-the-coding-interview-patterns-for-coding-questions "Direct link to heading")
这个由设计大师设计的课程扩展了推荐练习题中的问题,但是从问题模式的角度来进行练习,这是一个我也同意的学习方法,我个人也使用这个方法来更好地编写面试代码。本课程允许你用 Java、Python、C++、JavaScript 来练习选定的问题,并提供这些语言的示例解决方案。**学习和理解模式,而不是背答案!** [**结账→**](https://designgurus.org/link/kJSIoU?url=https%3A%2F%2Fdesigngurus.org%2Fcourse%3Fcourseid%3Dgrokking-the-coding-interview)
## JavaScript 课程[](#javascript-courses "Direct link to heading")
如果你想练习更多针对 JavaScript 的结构化算法,可以看看下面的课程。
| 课程 | 复习 | 持续时间 | 价格 | 内容 |
| :-- | --- | --- | --- | --- |
| [掌握编码面试:数据结构+算法](https://fxo.co/DQpY) | 4.6/5 | 19.5 小时 | $ | 基本数据结构和算法,工作申请,行为面试,谈判 |
| [JavaScript 数据结构和算法大师班](https://fxo.co/DQpZ) | 4.5/5 | 45 小时 | $ | 基本和高级数据结构和算法 |
| [Ace JavaScript 编码面试](https://www.educative.io/path/ace-javascript-coding-interview?aff=x23W) | - | 87h | $ | 基本数据结构和算法、系统设计、面向对象设计 |
# 系统设计面试
\ No newline at end of file
# 前端系统设计面试概述
> 原文:<https://www.frontendinterviewhandbook.com/front-end-system-design/>
前端系统设计资源少得惊人,可能是因为前端工程师候选人的需求和供应都较低。
这里的“系统”通常是指前端系统,它与软件工程面试中典型的分布式系统设计问题有很大的不同。所提的问题可能与[“构建用户界面”格式](/coding/build-front-end-user-interfaces/)中的问题非常相似,但更侧重于架构和设计。它们之间有大量的重叠——当你构建 UI 时,你可能需要做一些设计(数据模型,API ),还需要做一些编码来说明你的想法/应用状态格式。
本节与[“构建用户界面”格式](/coding/build-front-end-user-interfaces/)的区别在于,这里的问题通常更大。如果会议只有半个小时,候选人应该谈论设计权衡,可能的实现,而不是编码出来。因为系统设计问题通常涉及多个组件和跨 web 堆栈的知识,所以考生通常不必非常深入每个组件的较低级别的细节,并且可以将讨论保持在较高的级别,关于客户端和服务器之间的 API 设计,以及组件之间的 API。
[“构建用户界面”格式](/coding/build-front-end-user-interfaces/)中提到的许多主题也与前端系统设计相关——API 设计、可伸缩性、性能、用户体验、i18n、可访问性、安全性等。候选人应该主动提出这些话题,引导与面试官的讨论。性能、可访问性和 i18n 等更高级的主题是高级候选人与初级候选人的区别。
两种主要的前端系统设计面试是 UI 组件和应用程序。
## 例题[](#examples "Direct link to heading")
* 用户界面组件
* 自动完成([阅读前端示例解决方案](https://www.greatfrontend.com/questions/system-design/autocomplete)
* 图像转盘([阅读前端示例解决方案](https://www.greatfrontend.com/questions/system-design/image-carousel)
* 应用程序
* 新闻提要([阅读伟大前端](https://www.greatfrontend.com/questions/system-design/news-feed-facebook)上的示例解决方案)
* 视频观看网站
* 聊天应用程序
Read front end system design case studies
[出色的前端](https://www.greatfrontend.com/?fpr=frontendinterviewhandbook)向您展示如何通过前端系统设计指南和案例研究进行前端系统设计面试。今天就开始阅读吧!
## RADAD 框架[](#radad-framework "Direct link to heading")
系统设计面试问题往往是开放式的和模糊的,给你留下了很多探索的空间。如果面试官告诉你应该关注哪些具体领域,那就太好了!否则,这里有一个框架,你可以用它来给面试官一个大纲,告诉他你将要涵盖的内容,这在工作中处理新的前端项目时也很有帮助。
这个框架被称为 **RADAD** ,它由每一步的第一个字符组成。你可以把这个结构写在白板/在线编辑器上,这样你就不会忘记。
1. **<u>R</u> 需求澄清/调整**——询问系统的需求。
2. **<u>一个</u>架构**——勾勒出系统的架构(可能是 UI 组件,也可能是 app,取决于问题)。在相关的地方画图表。
3. **<u>D</u> ata 模型** -组件如何存储传递给它的任何数据?使用什么数据结构?
4. **<u>A</u> PI 设计**——使用这个组件的 API 是什么?组件上允许哪些选项?
5. **<u>D</u>eep dive**——用户体验(UX)、性能、可访问性(a11y)、国际化(i18n)、多设备支持、安全性
如何处理应用程序和 UI 组件的系统设计问题可能会有很大的不同,我们将在随后的章节中详细讨论这些问题。
## [](#things-you-would-not-have-to-do-probably "Direct link to heading")你本来不必做的事情(大概)
因为前端系统设计面试侧重于前端,所以您可能不必:
* 设计数据库模式
* 了解使用哪种数据库(SQL 还是 NoSQL)
* 扩展您的服务器和数据库(分片、垂直/水平扩展)
* 谈论可用性、容错、延迟等
阅读更多关于[前端与后端系统设计面试](/blog/front-end-vs-back-end-system-design-interviews/#differences)的不同之处。
Read front end system design case studies
[出色的前端](https://www.greatfrontend.com/?fpr=frontendinterviewhandbook)向您展示如何通过前端系统设计指南和案例研究进行前端系统设计面试。今天就开始阅读吧!
# 前端系统设计面试-用户界面组件
> 原文:<https://www.frontendinterviewhandbook.com/front-end-system-design/ui-components/>
## 例题[](#examples "Direct link to heading")
* 自动完成([阅读前端示例解决方案](https://www.greatfrontend.com/questions/system-design/autocomplete)
* 图像转盘([阅读前端示例解决方案](https://www.greatfrontend.com/questions/system-design/image-carousel)
* 通过网络加载选项的选择器
Read front end system design case studies
[出色的前端](https://www.greatfrontend.com/?fpr=frontendinterviewhandbook)向您展示如何通过前端系统设计指南和案例研究进行前端系统设计面试。今天就开始阅读吧!
## 框架[](#framework "Direct link to heading")
在系统设计面试中,候选人应该引导对话。这里有一个框架,你可以用它来给面试官一个大纲,告诉他你将要涵盖的内容。这个框架被称为 **RADAD** ,它由每一步的第一个字符组成。你可以把这个结构写在白板/在线编辑器上,这样你就不会忘记。
1. **<u>R</u> 需求澄清/调整**——询问系统的需求。
2. **<u>一个</u>架构**——在相关的地方概述组件中子组件的架构。
3. **<u>D</u> ata 模型** -组件如何存储传递给它的任何数据?使用什么数据结构?
4. **<u>A</u> PI 设计**——使用这个组件的 API 是什么?组件上允许哪些选项?
5. **<u>D</u>eep dive**——用户体验(UX)、性能、可访问性(a11y)、国际化(i18n)、多设备支持、安全性
### 需求澄清[](#requirements-clarification "Direct link to heading")
每一次系统设计面谈(即使对于非前端也是如此)都应该从需求收集/澄清关于问题的需求开始,这通常是故意留下的。建议您至少花几分钟时间来阐明这些要求。在明确需求之前,不要开始绘制架构!
幸运的是,组件有定义良好的范围,不会试图做太多的事情。您自己可能已经使用过这样的组件,并且可能知道您需要从这样的组件中得到什么。
一些注意事项:
* 系统应该支持哪些设备?桌面网络、移动网络等
* 用户访问系统的主要设备是什么?
* 我们应该支持哪些浏览器?
* 我们需要支持国际化吗?
* 我们希望允许多少样式定制?
### 架构[](#architecture "Direct link to heading")
前端面试的架构通常集中在客户端架构,而不是涉及数据库、负载平衡器和服务器的大规模分布式系统。
对于组件,列出其中存在的各种子组件,以及每个组件之间传递的数据。
让我们以图像轮播为例。图像转盘中的子组件包括:
* 主图像-显示焦点照片的图像
* 缩略图-下面更小的图像(会有缩略图吗?您只有在之前澄清需求时才会知道)
* 图像存储-显示照片列表的客户端缓存
如果你有一个白板/在线绘图工具,画图表来说明实体和它们之间的关系也会很有帮助。当发生用户交互时,哪个子组件与哪个子组件进行通信。
Read front end system design case studies
[出色的前端](https://www.greatfrontend.com/?fpr=frontendinterviewhandbook)向您展示如何通过前端系统设计指南和案例研究进行前端系统设计面试。今天就开始阅读吧!
### 数据模型[](#data-model "Direct link to heading")
组件的数据模型将引用组件状态。大多数使用过 React、Angular、Vue、Svelte 等前端 UI 库/框架的前端开发人员应该对状态的概念很熟悉。在所有这些库/框架中,状态是一个常见的概念。
决定将哪些数据放入状态对于做好这一部分至关重要。在决定什么进入组件状态时,需要考虑几个因素:
* 在组件的生命周期中,状态可以随着时间的推移而改变,这通常是用户交互的结果。
* 每个组件应该保持它自己的独立状态,这允许组件的多个实例共存于一个页面上。组件实例的状态不应该影响另一个实例的状态。
* 状态中的字段越少,组件越容易推理(读取/理解)。我们应该努力减少所需的国家数量。如果一个组件使用一个可以从另一个状态中派生出来的值,那么这个值很可能不属于这个状态。例如,如果您的组件正在呈现一个项目列表,并且您希望在没有项目要呈现时显示一条消息,那么就不应该有额外的`isEmpty`状态,因为它可以从`items`的长度中派生出来。
* 如果一个组件有多个子组件,最好是能够将状态合并到顶层,而其余的组件是纯的和无状态的。
### API 设计[](#api-design "Direct link to heading")
组件背后的关键思想是让它们被重用和抽象复杂性。好的组件设计得很好,可以在多种场景中重用,用户在使用它们之前不必知道它们内部是如何工作的。对于组件,API 指的是组件开发人员向其他开发人员公开以指定的配置选项。
* 您允许组件有哪些配置选项?(`props` in React)。什么是合理的违约?
* 遵循[打开-关闭原则](https://en.wikipedia.org/wiki/Open%E2%80%93closed_principle) -组件应该为扩展而打开,为修改而关闭。
* 如果你的组件是一个 UI 库的一部分,它不关心外观,把样式留给用户,那么在设计道具时要格外小心,允许用户定制组件的外观和感觉。在 React 中有几种方法可以做到这一点:
* [Composition](https://reactjs.org/docs/composition-vs-inheritance.html) - Props 接受 React 组件,这也促进了代码重用。
* [渲染道具](https://reactjs.org/docs/render-props.html)是组件用来知道渲染什么的功能道具。它还有助于重用行为,而不必担心外观。
* `className``style`props——允许用户向内部 DOM 元素注入类名和/或样式属性。这可能会产生负面影响,但仍然是允许用户定制组件外观的常用方法。
* 可能的配置选项:
* 生命周期/事件挂钩- `onClick``onChange``onBlur``onFocus`等。
Read front end system design case studies
[出色的前端](https://www.greatfrontend.com/?fpr=frontendinterviewhandbook)向您展示如何通过前端系统设计指南和案例研究进行前端系统设计面试。今天就开始阅读吧!
### 深潜[](#deep-dives "Direct link to heading")
在了解了组件的基础知识之后,我们可以深入到组件可能需要特别关注的特定领域。请注意,几乎肯定没有足够的时间来涵盖每个领域,并且不是每个领域都与手边的组件非常相关。
表现出对这些领域的了解并能够深入研究这些领域是高级前端工程师的特征。
#### 用户体验(UX)[](#user-experience-ux "Direct link to heading")
UX 可能不属于工程,但良好的前端工程师有很好的理解 UX 和建设与伟大的 UX 用户界面。有太多的 UX 实践需要注意,但最常见的/容易实现的是:
* 向用户反映组件的状态——如果有未决的后台请求,显示一个微调器。如果有错误,一定要显示出来,而不是静静地失败。
* 如果列表中没有项目,则显示空状态,而不是不呈现任何内容。
* 破坏性的行动应该有一个确认步骤,尤其是不可逆的。
* 如果交互式元素触发异步请求,则禁用它们!防止在意外双击的情况下重复触发事件(对于有运动障碍的人来说是可能的)。
* 如果涉及到搜索输入,每次击键都不应该触发网络请求。
* 处理极端情况
* 字符串可以很长/很短,在这两种情况下你的 UI 都不应该看起来很奇怪。对于长字符串,它们的内容可以被截断并隐藏在“查看更多”按钮后面。
* 如果一个组件中有很多条目要显示,它们不应该同时显示在屏幕上,这样会使页面变得非常长/宽。对项目进行分页或将它们包含在具有最大宽度/高度的容器中。
* 键盘友好性——这包括确保组件是键盘友好的
* 添加快捷方式,使只使用键盘的用户更容易使用该组件
* 确保元素可以聚焦,并且组件中的 tab 键顺序正确
* 可访问性是 UX 的一部分,但将在后面的章节中讨论
#### 性能[](#performance "Direct link to heading")
在前端,性能通常是指几件事——加载速度、UI 响应用户交互的速度、组件所需的内存空间(堆)。
* 加载速度——组件包含的 JavaScript 越少,浏览器加载组件所需下载的 JavaScript 就越少,网络请求时间也就越短。模块化组件并允许用户仅下载其用例所需的必要 JavaScript 模块也很重要。
* 对用户交互的响应
* 如果用户交互导致显示必须通过网络加载的数据,则在用户交互和 UI 更新之间会有延迟。最小化延迟或完全消除延迟是提高响应能力的关键。
* 浏览器中的 JavaScript 是单线程的。浏览器一次只能执行一行代码。当用户在页面上做一些事情时,组件需要做的工作(JavaScript 执行、DOM 更新)越少,组件更新 UI 以响应变化的速度就越快。
* 内存空间——你的组件在页面上占用的内存越多,浏览器的运行速度就越慢,用户的体验也会变得迟钝。如果您的组件必须呈现数百/数千个项目(例如,转盘中的图像数量、选择器中的项目数量),内存空间可能会变得很大。
**优化提示**
* 只呈现屏幕上显示的内容——例如,在选择器中,即使列表可以包含数百个元素,也只向用户显示几个项目。将它们全部呈现在浏览器中会浪费处理能力和内存空间。我们可以利用一种叫做窗口/虚拟化的技术来模拟一个包含许多元素的列表,同时尽可能地只渲染少数元素,以使最终结果看起来好像没有进行优化(尤其是保留滚动高度)。点击阅读关于虚拟化[的更多信息。](https://web.dev/virtualize-long-lists-react-window/)
* 惰性加载/只加载必要的数据——例如,在一个照片库组件中,一个用户可能有成百上千的照片,但是急切地加载所有的照片是不可行的。最有可能的是,用户不会在那个会话中浏览所有的内容。优化可以是只加载用户可能查看的内容,或者在视口内的内容(我们称之为“折叠之上”)。其余的照片可以按需加载,这会导致响应延迟,但下一篇技巧文章将帮助您解决这个问题。
* 提前预加载/预取数据——例如,在一个图像轮播中,有太多的图像需要预先加载,优化可以是在用户仍在当前图像上时提前加载下一个图像,这样当用户单击“下一个”按钮时,就不需要网络延迟,因为下一个图像已经被加载了。这种技术也可以修改为加载接下来的 N 个图像,以处理用户快速连续点击“下一个”的情况。
Read front end system design case studies
[出色的前端](https://www.greatfrontend.com/?fpr=frontendinterviewhandbook)向您展示如何通过前端系统设计指南和案例研究进行前端系统设计面试。今天就开始阅读吧!
#### [可达性(a11y)](#accessibility-a11y "Direct link to heading")
易访问性(a11y)是指让尽可能多的人可以使用你的网站。
* 颜色对比(例如色盲)
* 键盘友好性(例如精细运动控制能力有限的人)
* 视觉障碍(如失明)
* 音频抄本(如聋人)
不是每个人都以同样的方式上网;有的人专门用屏幕阅读器和键盘(没有鼠标)!以下是在 UI 组件中实现 a11y 的一些基本技巧:
* 前景色应该与背景色有足够的对比
* 为语义使用正确的 HTML 标签,或者正确的`aria-role`属性
* 可点击的项目应该有`tabindex`属性(以便它们是可聚焦的)和“光标:指针”样式来表示它们可以被点击
* 图像应该有`alt`文本,它将被屏幕阅读器读出,并作为图像加载失败时的后备描述
* 这有助于为非视觉用户不明显的元素提供上下文。例如,一个内部没有任何文本标签的图标按钮应该有一个`aria-label`属性,这样对于看不到图标的用户来说,意图就很清楚了
a11y 是最常被忽视的领域之一,因为大多数时候它们对开发人员来说是不可见的。展示 a11y 的知识并拥有创建易访问组件的技能肯定会给你带来好的影响。更多关于[网页可访问性](https://www.w3.org/WAI/fundamentals/accessibility-intro/)的阅读。
#### 国际化(i18n)[](#internationalization-i18n "Direct link to heading")
国际化(i18n)是一种产品、应用程序或文档内容的设计和开发,它使文化、地区或语言不同的目标受众能够轻松地进行本地化。通常,组件不应该担心 i18n,除非在少数特定情况下:
* 组件使用字符串-组件中使用的字符串不应该硬编码为特定的语言(例如,照片库组件控件中的“Prev”/“Next”)。字符串可以被指定为一个属性,默认为英文版本
* 内容的顺序很重要——你的组件支持 RTL(从右到左)语言吗,比如阿拉伯语和希伯来语?
#### 多设备支持[](#multi-device-support "Direct link to heading")
该组件有望在移动 web 上使用吗?移动设备有独特的限制——它们的硬件功能较弱,而且视窗尺寸较小。因此,可以用不同的方式来让组件在移动设备上更好地工作——有意识地努力:
* 不要使用太多内存——使用太多内存会使设备运行速度变慢
* 增加交互元素的点击量——手指可以更轻松地点击正确的元素
#### 安全[](#security "Direct link to heading")
大多数时候,组件不会暴露在安全漏洞之下,但这种情况仍然会发生。以下是您应该了解的更常见的安全漏洞:
* XSS -你的组件容易受到跨站点脚本(XSS)的攻击吗?例如,您是否通过`.innerHTML``dangerouslySetInnerHTML`(特定于 React)呈现用户输入?
* CSRF(跨站点请求伪造)
* 点击劫持
* [T2`rel=noopener`](https://mathiasbynens.github.io/rel-noopener/)
Read front end system design case studies
[出色的前端](https://www.greatfrontend.com/?fpr=frontendinterviewhandbook)向您展示如何通过前端系统设计指南和案例研究进行前端系统设计面试。今天就开始阅读吧!
# 前端系统设计面试-应用
> 原文:<https://www.frontendinterviewhandbook.com/front-end-system-design/applications/>
Read front end system design case studies
[出色的前端](https://www.greatfrontend.com/?fpr=frontendinterviewhandbook)向您展示如何通过前端系统设计指南和案例研究进行前端系统设计面试。今天就开始阅读吧!
## 例题[](#examples "Direct link to heading")
* 社交网络
* 视频观看网站
* 聊天应用程序
* 邮件应用程序
## 框架[](#framework "Direct link to heading")
1. 需求澄清/调整
2. 体系结构
3. 数据模型
4. API 设计
5. 深潜
* 用户体验(UX)
* 表演
* 可访问性(a11y)
* 国际化(i18n)
* 多设备支持
* 安全性
### 需求澄清[](#requirements-clarification "Direct link to heading")
每次系统设计面试都应该从澄清问题的需求开始,这通常是有意留下的模糊信息。一些注意事项:
* 系统应该支持哪些设备?桌面网络、移动网络等
* 用户访问系统的主要设备是什么?
* 我们应该支持哪些浏览器?
* 我们需要支持国际化吗?
* app 需要离线工作吗?
### 架构[](#architecture "Direct link to heading")
前端面试的架构通常集中在客户端架构,而不是涉及数据库、负载平衡器和服务器的大规模分布式系统。
对于应用程序,常见的架构包括模型-视图-控制器、模型-视图-视图模型、Flux、N 层(其中数据层在客户端)等。
Read front end system design case studies
[出色的前端](https://www.greatfrontend.com/?fpr=frontendinterviewhandbook)向您展示如何通过前端系统设计指南和案例研究进行前端系统设计面试。今天就开始阅读吧!
### 数据模型[](#data-model "Direct link to heading")
客户端应用程序状态,它是服务器状态(数据库)和真实客户端状态(非持久化到服务器)的组合。
### API 设计[](#api-design "Direct link to heading")
应用程序的 API 设计将参考 HTTP/网络 API 参数和响应的形状。
### 深潜[](#deep-dives "Direct link to heading")
在介绍了应用程序的架构基础之后,我们可以深入到应用程序可能需要特别关注的特定领域。请注意,几乎肯定没有足够的时间来涵盖每个领域,并且不是每个领域都与手边的组件非常相关。
表现出对这些领域的了解并能够深入其中是高级开发人员的特征。
* 用户体验(UX)
* 表演
* 可访问性(a11y)
* 国际化(i18n)
* 多设备支持
* 安全性
## 有帮助的文章[](#helpful-articles "Direct link to heading")
许多公司在博客中讲述了他们在前端领域面临的技术挑战,这些都是了解更多前端系统设计的绝佳内容。
* [构建 Google 相册网络用户界面](https://medium.com/google-design/google-photos-45b714dfbed1)
* [Twitter Lite 和 High Performance 对渐进式网络应用做出大规模反应](https://medium.com/@paularmstrong/twitter-lite-and-high-performance-react-progressive-web-apps-at-scale-d28a00e780a3)
* [网飞网络性能案例研究](https://medium.com/dev-channel/a-netflix-web-performance-case-study-c0bcde26a9d9)
* [Tinder Progressive Web App 性能案例研究](https://medium.com/@addyosmani/a-tinder-progressive-web-app-performance-case-study-78919d98ece0)
* [Pinterest 渐进式网络应用性能案例研究](https://medium.com/dev-channel/a-pinterest-progressive-web-app-performance-case-study-3bd6ed2e6154)
* [反应和预测渐进式 Web 应用性能案例研究:Treebo](https://medium.com/dev-channel/treebo-a-react-and-preact-progressive-web-app-performance-case-study-5e4f450d5299)
* [为新 Facebook.com 重建我们的技术体系](https://engineering.fb.com/2020/05/08/web/facebook-redesign/)
Read front end system design case studies
[出色的前端](https://www.greatfrontend.com/?fpr=frontendinterviewhandbook)向您展示如何通过前端系统设计指南和案例研究进行前端系统设计面试。今天就开始阅读吧!
# 行为面试
> 原文:<https://www.frontendinterviewhandbook.com/behavioral/>
行为面试侧重于候选人的软技能——他们如何与他人合作,他们过去如何处理情况。对于全面的行为面试内容,[技术面试手册](https://www.techinterviewhandbook.org/behavioral-interview/)涵盖了这些内容以及顶级公司的常见行为面试问题。
[Go to Tech Interview Handbook  →](https://www.techinterviewhandbook.org/behavioral-interview/)
## 脸书在行为面试中寻找什么[](#what-facebook-looks-for-in-behavioral-interviews "Direct link to heading")
* 讨论你简历上的任何内容,包括当前的项目和细节
* 提供具体的例子,说明你做了什么以及产生的影响
* 批判自己,分享你从过去的经历中学到的东西
* 谈谈你喜欢你目前的角色和/或作为一名开发人员的什么
* 讨论你为什么想要做出改变
*来源:[在脸书](https://www.facebook.com/careers/swe-prep-onsite)准备现场面试*
## 课程[](#courses "Direct link to heading")
我真的不认为一个人需要参加行为面试的课程,但你的里程可能会有所不同。我见过一些应聘者因为没有通过行为测试而被拒绝,尽管他们在编码和系统设计面试中做得非常好。如果你想参加行为面试课程,你可以看看 Educative 的[探索行为面试](https://www.educative.io/courses/grokking-the-behavioral-interview?aff=x23W)课程。
# 简历准备
> 原文:<https://www.frontendinterviewhandbook.com/resume/>
简历在工作申请过程中经常被忽视,但却极其重要,因为它能决定你申请的成败。科技面试手册包含更多关于如何写一份杀手简历的细节,这也将有利于前端工程师候选人。
[Go to Tech Interview Handbook  →](https://www.techinterviewhandbook.org/resume/guide)
## 推荐简历工具[](#recommended-resume-tools "Direct link to heading")
### 1.使用简历模板[](#1-use-resume-templates "Direct link to heading")
如果可以使用模板,为什么要浪费时间从头开始创建自己的简历呢?!你可以在网上找到很多免费的简历模板,或者你也可以购买高质量的。 [FAANG Tech Leads](https://www.faangtechleads.com?utm_source=frontendinterviewhandbook&utm_medium=referral&utm_content=ats_template&aff=1e80c401fe7e2) 目前在**以 70%的价格**提供简历模板和推荐信。
他们的模板:
* 是由前 FAANG 招聘经理根据从数百份候选人申请中收到的顶级简历创建的
* 通过 FAANG ATS 保证可读性
* 迎合不同的经验水平
他们还提供了已经收到 FAANG 公司多份聘书的候选人的简历示例/参考资料,这有助于帮助你制作符合相同要求的内容。[来看看](https://www.faangtechleads.com?utm_source=frontendinterviewhandbook&utm_medium=referral&utm_content=ats_template&aff=1e80c401fe7e2)
### 2.使用行业标准 ATS [](#2-test-readability-with-industry-standard-ats "Direct link to heading")测试可读性
使用免费的 ATS 简历扫描测试你简历的可读性和格式。大多数大公司都使用这样的简历扫描仪。
### 3.纯文本文件测试[](#3-the-plain-text-file-test "Direct link to heading")
只需从简历中复制内容并粘贴到纯文本文档中即可!在以下情况下进行编辑:
* 你的原始简历中缺少一些要点
* 纯文本中的字符显示不正确
* 各部分杂乱无章
# 公司面试问题
原文:[https://www.frontendinterviewhandbook.com/company-interview-questions/](https://www.frontendinterviewhandbook.com/company-interview-questions/)
\ No newline at end of file
# 谷歌前端面试问题
> 原文:<https://www.frontendinterviewhandbook.com/companies/google-front-end-interview-questions/>
因为是谷歌,候选人可以期待测试基本的计算机科学概念以及他们的前端知识/技能。
## JavaScript[](#javascript "Direct link to heading")
* 实现 Google 文档的大纲视图。
* HTML 节点上的 DFS。
* 执行`throttle`
* [大前端练习题](https://www.greatfrontend.com/questions/javascript/throttle)
* 如何做一个每 50 毫秒只调用输入函数 f 的函数?
* [大前端练习题](https://www.greatfrontend.com/questions/javascript/throttle)
* 怎么做一个带 f 的函数,超时返回一个调用 f 的函数?
* [大前端练习题](https://www.greatfrontend.com/questions/javascript/debounce)
* 给定一条时间线,编写 JavaScript 来选择时间线选择范围内的所有节点。
## 用户界面编码[](#user-interface-coding "Direct link to heading")
* 设计一个滑块组件。
* 设计一个井字游戏/设计一个井字游戏的算法。
* 实现嵌套复选框(当父复选框被选中时,子复选框也被选中,反之亦然。使用`<input type="checkbox">`)。类似于[不确定的复选框](https://css-tricks.com/indeterminate-checkboxes/)
* 使用 JavaScript 设计一个网页,当你到达页面底部时可以自动加载新文章。您可以使用 AJAX 和 JavaScript 事件监听器。
* 使用 HTML、CSS、JavaScript 编写一个 UI,允许用户在表单的文本输入字段中输入行数和列数,并呈现一个表格。
例如:行数:4,列数:5,“提交”按钮。点击“提交”按钮将显示下表(忽略样式):
| one | eight | nine | Sixteen | Seventeen |
| --- | --- | --- | --- | --- |
| Two | seven | Ten | Fifteen | Eighteen |
| three | six | Eleven | Fourteen | Nineteen |
| four | five | Twelve | Thirteen | Twenty |
## 琐事[](#trivia "Direct link to heading")
* 解释 CSS 盒子模型。
* [在大前端阅读答案](https://www.greatfrontend.com/questions/quiz/css/explain-your-understanding-of-the-box-model-and-how-you-would-tell-the-browser-in-css-to-render-your-layout-in-different-box-models)
* 当你在浏览器中输入一个 URL 并点击回车会发生什么?
* 给定网页上的一些文本,有多少种方法可以让这些文本消失?
* 如何在不刷新页面的情况下将数据从网页发送到服务器?
* [在大前端阅读答案](https://www.greatfrontend.com/questions/quiz/javascript/what-are-the-advantages-and-disadvantages-of-using-ajax)
## 系统设计[](#system-design "Direct link to heading")
* 设计 JS Bin。
* 你如何创建一个网页使用的谷歌分析软件开发工具包?
* 设计表情自动完成。
## 算法[](#algorithm "Direct link to heading")
* 扫雷舰问题。编写一个函数`reveal()`,当用户点击一个图块时,输出显示的图块数量。每个区块显示其相邻的炸弹数量。如果用户点击一个炸弹,游戏就结束了。如果该图块为 0,则显示其所有邻居。
* 给你四个数字(int 类型),有四个基本的数学运算符供你使用(+、-、x、/)。给定任意的方法对数字进行分组,并使用任何运算符,判断是否可以从四个数字中得到 24。这些数字必须按照它们出现的顺序进行处理。
* 寻找 k 个最近点。
*来源: [Glassdoor Google 前端软件工程师面试问题](https://www.glassdoor.sg/Interview/Google-Front-End-Software-Engineer-Interview-Questions-EI_IE9079.0,6_KO7,34.htm)、 [Google |前端工程师](https://leetcode.com/discuss/interview-question/271736/google-front-end-engineer-onsite-interview)、T5】*
# 亚马逊前端面试问题
> 原文:<https://www.frontendinterviewhandbook.com/companies/amazon-front-end-interview-questions/>
众所周知,亚马逊非常关注行为问题及其领导原则。因此,在非技术方面也要做好准备。
## 琐事[](#trivia "Direct link to heading")
* CSS 盒子模型是什么?
* [在大前端阅读答案](https://www.greatfrontend.com/questions/quiz/css/explain-your-understanding-of-the-box-model-and-how-you-would-tell-the-browser-in-css-to-render-your-layout-in-different-box-models)
* 什么是 JavaScript 闭包?
* [在大前端阅读答案](https://www.greatfrontend.com/questions/quiz/javascript/what-is-a-closure-and-how-why-would-you-use-one)
* 当你在浏览器中输入 URL 并按回车键时会发生什么?
## JavaScript[](#javascript "Direct link to heading")
* 实现`map``reduce``filter``sort``Array.prototype`功能。
* [大前端练习题](https://www.greatfrontend.com/questions/coding)
* 给定一个对象和一个过滤函数,编写一个递归过滤该对象的函数,当用过滤函数调用时,只返回返回`true`的值(类似于`Array.prototype.filter`,但用于对象)。
* 实现一个函数`getElementsByStyle(property, value)`,返回 DOM 中匹配该样式的所有元素。
* 例如`getElementsByStyle("color", "#fff")`会用白色文本返回 DOM 中的所有元素。
* 许诺一个功能。
## 用户界面编码[](#user-interface-coding "Direct link to heading")
* 使用 HTML/CSS 和 JavaScript 通过搜索和排序从一组对象中实现一个数据表。
* [大前端练习题](https://www.greatfrontend.com/questions/javascript/data-selection)
* 实现自动建议的材料用户界面芯片。当发送电子邮件时,自动推荐人,并把他们转换成一个芯片,他们的头像在右边
* 实现一个 Like 按钮。[来源](https://leetcode.com/discuss/interview-question/1719943/Amazon-or-Phone-Screen-or-FEE-L5-or-Like-Button)
* 编写一个分页的地址小部件。想象一下,你是一个卖家,有一个地址列表,你需要查看他们每页 5 个地址,并有可能去上一页和下一页。[来源](https://leetcode.com/discuss/interview-question/1984996/Amazon-Virtual-Onsite-April-2022-FrontEnd-Engineer-II-(L5)Vancouver-Offer)
* 使用 HTML,CSS 和 JavaScript 实现一个搜索栏。
* 实现一个星级小部件。
* [大前端练习题](https://www.greatfrontend.com/questions/user-interface/star-rating)
* 实施井字游戏。
* 使用 flexbox 重新创建自适应布局。确保无障碍。
* 用可移动的棋子实现棋盘。
* 如何在横幅图像上呈现文本?
* 给定一个嵌套的 JSON 对象,呈现一个目录树。
## 系统设计[](#system-design "Direct link to heading")
* 设计一个餐馆列表应用程序,用户可以通过添加额外的东西,如浇头,沙拉等来订购和定制他们的订单。[来源](https://leetcode.com/discuss/interview-question/1984996/Amazon-Virtual-Onsite-April-2022-FrontEnd-Engineer-II-(L5)Vancouver-Offer)
* 设计一个手风琴组件。
## 算法[](#algorithm "Direct link to heading")
亚马逊确实会通过问 LeetCode 式的问题来评估你的计算机科学基础。一定要做好准备。
*来源: [Glassdoor 亚马逊前端工程师面试问题](https://www.glassdoor.sg/Interview/Amazon-Front-End-Engineer-Interview-Questions-EI_IE6036.0,6_KO7,25.htm)*
# Microsoft 前端面试问题
> 原文:<https://www.frontendinterviewhandbook.com/companies/microsoft-front-end-interview-questions/>
## JavaScript[](#javascript "Direct link to heading")
* 使用普通 JavaScript、HTML 和 CSS 实现井字游戏。
* 创建一个像微软团队一样的聊天界面。
* 用 OOP 实现一个象棋游戏。
## 用户界面编码[](#user-interface-coding "Direct link to heading")
* 创建一个类似微软团队的通知界面
* 图像滑块实现。
## 琐事[](#trivia "Direct link to heading")
* 什么是原型?
* [在大前端阅读答案](https://www.greatfrontend.com/questions/quiz/javascript/explain-how-prototypal-inheritance-works)
* 什么是终结?
* [在大前端阅读答案](https://www.greatfrontend.com/questions/quiz/javascript/what-is-a-closure-and-how-why-would-you-use-one)
* `let``const``var`有什么区别?
* [在大前端阅读答案](https://www.greatfrontend.com/questions/quiz/javascript/what-are-the-differences-between-variables-created-using-let-var-or-const)
* 什么是 DOM?
## 系统设计[](#system-design "Direct link to heading")
* 设计一个类似微软 Outlook 的电子邮件客户端。
*来源: [Glassdoor 微软前端开发者面试问题](https://www.glassdoor.sg/Interview/Microsoft-Front-End-Developer-Interview-Questions-EI_IE1651.0,9_KO10,29.htm)*
# 苹果前端面试问题
> 原文:<https://www.frontendinterviewhandbook.com/companies/apple-front-end-interview-questions/>
人们对苹果公司的前端面试流程知之甚少。
## JavaScript[](#javascript "Direct link to heading")
* 使用 JavaScript 自己实现`Array.prototype`方法(`flat``map``reduce``concat`)。
* [大前端练习题](https://www.greatfrontend.com/questions/coding)
* 你如何按顺序执行一系列承诺?
## 用户界面编码[](#user-interface-coding "Direct link to heading")
* 用普通的 JS 实现一个简单的图片订购工具,没有库。
## 琐事[](#trivia "Direct link to heading")
* 如何构建 npm 包?
* CSS 中的复合层是什么?
## 算法[](#algorithm "Direct link to heading")
* 给定一个数组,返回一个数组,其中每个值是下两项的乘积:例如`[3, 4, 5]`->-T1】
*来源: [Glassdoor 苹果前端开发者面试问题](https://www.glassdoor.sg/Interview/Apple-Front-End-Developer-Interview-Questions-EI_IE1138.0,5_KO6,25.htm)*
# Airbnb 前端面试问题
> 原文:<https://www.frontendinterviewhandbook.com/companies/airbnb-front-end-interview-questions/>
## JavaScript[](#javascript "Direct link to heading")
* 写一个简单的承诺。
* 实现一个添加键/值对并监听键的值变化的`StoreData`类。[来源](https://leetcode.com/discuss/interview-question/348436/Airbnb-or-Phone-Screen-or-Implement-StoreData-class)
## 用户界面编码[](#user-interface-coding "Direct link to heading")
* 给定一个输入和一个返回 JSON 列表的端点,结果是,扩展它以在更改时自动完成,处理结果中的键导航。
* 给定一个嵌入在表单中的星星小部件,编写代码来选择星星,并通过正常的表单操作提交正确的值。使多星部件可重复使用。
* [大前端练习题](https://www.greatfrontend.com/questions/user-interface/star-rating)
*来源: [Glassdoor Airbnb 前端工程师面试问题](https://www.glassdoor.sg/Interview/Airbnb-Front-End-Engineer-Interview-Questions-EI_IE391850.0,6_KO7,25.htm)*
## 算法[](#algorithm "Direct link to heading")
Airbnb 确实会通过问 LeetCode 式的问题来评估你的计算机科学基础。一定要做好准备。
# 字节舞/titok 前端面试问题
> 原文:<https://www.frontendinterviewhandbook.com/companies/bytedance-tiktok-front-end-interview-questions/>
字节跳动/抖音的前端采访在采访形式方面相当平衡。
## JavaScript[](#javascript "Direct link to heading")
* 执行`Promise.all`
* [大前端练习题](https://www.greatfrontend.com/questions/javascript/promise-all)
* 实现一个扩展`Array.prototype`的函数。
* [大前端练习题](https://www.greatfrontend.com/questions/coding)
## 用户界面编码[](#user-interface-coding "Direct link to heading")
* 实现一个下拉组件。
## 琐事[](#trivia "Direct link to heading")
* `localStorage`和饼干的区别。
## 算法[](#algorithm "Direct link to heading")
* 合并两个排序的整数数组,删除重复项。
* 你有一个网页上的图像,写 css 和 js,以便当鼠标在图像上时,它旋转 180 度,1 秒钟的动画。
* 给定一列点,找出其中任意四个点是否构成正方形。如果可能,返回“真”,否则返回“假”。
* 例子:`[[0, 0], [2, 0], [1, 1], [0, -1], [-1, -1], [0, 2], [0, 1], [1,0]]`->-T1】
* 检查字符串中的平衡括号。
* 给定两个节点,返回这两个节点之间的树的部分。
* 在陆地和海洋的网格中找到这些岛屿。
*来源: [Glassdoor 字节跳动前端开发者面试问题](https://www.glassdoor.sg/Interview/ByteDance-Front-End-Developer-Interview-Questions-EI_IE1624196.0,9_KO10,29.htm)*
# Dropbox 前端面试问题
> 原文:<https://www.frontendinterviewhandbook.com/companies/dropbox-front-end-interview-questions/>
## JavaScript[](#javascript "Direct link to heading")
* 实现 [`getByClassName()`和`getByClassnameHierarchy()`](https://leetcode.com/discuss/interview-question/427896/Dropbox-or-Phone-Screen-or-Implement-getByClassName-and-getByClassnameHierarchy)
* [大前端练习题](https://www.greatfrontend.com/questions/javascript/get-elements-by-class-name)
* 基于面向对象的班级管理系统。
## 用户界面编码[](#user-interface-coding "Direct link to heading")
* 使用 JavaScript,HTML,CSS 建立一个图库。
* 从手机键盘组词。
* 构建一个 UI,从与设计规范相匹配的天气 API 中获取数据。
* 构建一个与 Dropbox 主页上某个页面的设计规范相匹配的 UI。
## 系统设计[](#system-design "Direct link to heading")
* 设计谷歌日历。
## 算法[](#algorithm "Direct link to heading")
* 你想记录一个网站的点击数。实现两个函数,`log_hit()`在记录点击时被调用,而`get_hits_in_last_five_minutes()`返回最近五分钟内的点击总数。
*来源: [Glassdoor Dropbox 前端开发者面试问题](https://www.glassdoor.sg/Interview/Dropbox-Front-End-Developer-Interview-Questions-EI_IE415350.0,7_KO8,27.htm), [Glassdoor Dropbox Web 开发者面试问题](https://www.glassdoor.sg/Interview/Dropbox-Web-Developer-Interview-Questions-EI_IE415350.0,7_KO8,21.htm?filter.jobTitleFTS=Web+Developer),*
# LinkedIn 前端面试问题
> 原文:<https://www.frontendinterviewhandbook.com/companies/linkedin-front-end-interview-questions/>
## JavaScript[](#javascript "Direct link to heading")
* 写一个`getElementsByClassName`函数。
* [大前端练习题](https://www.greatfrontend.com/questions/javascript/get-elements-by-class-name)
## 用户界面编码[](#user-interface-coding "Direct link to heading")
* 创建工具提示组件。
* 创建跨浏览器 Linkedin 顶部导航栏。
## 琐事[](#trivia "Direct link to heading")
* CSS `padding``margin`的区别。
* [在大前端阅读答案](https://www.greatfrontend.com/questions/quiz/css/explain-your-understanding-of-the-box-model-and-how-you-would-tell-the-browser-in-css-to-render-your-layout-in-different-box-models)
* 承诺和回拨的区别?
* 事件冒泡和捕获的区别?
* JavaScript 中回调和闭包的区别?
* 使用预处理器有什么好处?例如 Sass,Stylus,Less。
* [在大前端阅读答案](https://www.greatfrontend.com/questions/quiz/css/what-are-the-advantages-disadvantages-of-using-css-preprocessors)
* 什么是事件委托?
* [在大前端阅读答案](https://www.greatfrontend.com/questions/quiz/javascript/explain-event-delegation)
## 算法[](#algorithm "Direct link to heading")
* 反转双向链表。
*来源: [Glassdoor 链接前端软件工程师面试问题](https://www.glassdoor.sg/Interview/LinkedIn-Front-End-Software-Engineer-Interview-Questions-EI_IE34865.0,8_KO9,36.htm)*
# Lyft 前端面试问题
> 原文:<https://www.frontendinterviewhandbook.com/companies/lyft-front-end-interview-questions/>
## JavaScript[](#javascript "Direct link to heading")
* 执行`Promise.all`
* [大前端练习题](https://www.greatfrontend.com/questions/javascript/promise-all)
## 用户界面编码[](#user-interface-coding "Direct link to heading")
* 实现自动完成。
*来源: [Glassdoor Lyft 前端工程师面试问题](https://www.glassdoor.sg/Interview/Lyft-Frontend-Engineer-Interview-Questions-EI_IE700614.0,4_KO5,22.htm)*
# Salesforce 前端面试问题
> 原文:<https://www.frontendinterviewhandbook.com/companies/salesforce-front-end-interview-questions/>
对 Salesforce 的前端面试流程了解不多。
## 编码[](#coding "Direct link to heading")
* 展平嵌套数组。
* [大前端练习题](https://www.greatfrontend.com/questions/javascript/flatten)
## 琐事[](#trivia "Direct link to heading")
* 什么是事件循环?
* [在大前端阅读答案](https://www.greatfrontend.com/questions/quiz/javascript/what-is-event-loop-what-is-the-difference-between-call-stack-and-task-queue)
* 什么是终结?
* [在大前端阅读答案](https://www.greatfrontend.com/questions/quiz/javascript/what-is-a-closure-and-how-why-would-you-use-one)
* CSS 中的定位。
* [在大前端阅读答案](https://www.greatfrontend.com/questions/quiz/css/whats-the-difference-between-a-relative-fixed-absolute-and-statically-positioned-element)
*来源: [Glassdoor Salesforce UI 开发者面试问题](https://www.glassdoor.sg/Interview/Salesforce-UI-Developer-Interview-Questions-EI_IE11159.0,10_KO11,23.htm)*
# Twitter 前端面试问题
> 原文:<https://www.frontendinterviewhandbook.com/companies/twitter-front-end-interview-questions/>
## 用户界面编码[](#user-interface-coding "Direct link to heading")
* 实现一个提前类型。[来源](https://leetcode.com/discuss/interview-question/1220887/Twitter-Frontend-Phone-Screen)
* 为井字游戏添加功能。
## 琐事[](#trivia "Direct link to heading")
* `Array.prototype.map``Array.prototype.forEach`有什么区别?
* [在大前端阅读答案](https://www.greatfrontend.com/questions/quiz/javascript/can-you-describe-the-main-difference-between-a-foreach-loop-and-a-map-loop-and-why-you-would-pick-one-versus-the-other)
*来源: [Glassdoor Twitter 前端开发者面试问题](https://www.glassdoor.sg/Interview/Twitter-Front-End-Developer-Interview-Questions-EI_IE100569.0,7_KO8,27.htm)*
# 优步前端面试问题
> 原文:<https://www.frontendinterviewhandbook.com/companies/uber-front-end-interview-questions/>
人们对优步的前端面试过程知之甚少。
## JavaScript[](#javascript "Direct link to heading")
* 在 API 端点之上实现速率限制器属性/修饰/注释。滚动窗口每分钟最多 N 个请求。[源 A](https://leetcode.com/discuss/interview-question/2409192/Uber-or-Phone-Screen-or-Senior-Front-End-Engineer)[源 B](https://leetcode.com/discuss/interview-question/124880/Rate-Limiter)
## 用户界面编码[](#user-interface-coding "Direct link to heading")
* 创建一个按钮,单击该按钮会在页面上添加一个进度条。进度条会在给定的时间内填满(大概 3 到 5 秒)。如果你通过了第一部分,你将被要求调节一次可以运行多少个进度条。例如,如果限制为 3 个进度条,并且用户点击按钮 4 次,则第四个进度条仅在第一个进度条完成后开始。[来源](https://leetcode.com/discuss/interview-question/1064199/uber-front-end-phone-screen-reject)
* 重叠圈 app。[信号源](https://leetcode.com/discuss/interview-question/1784074/Uber-or-Phone-or-Overlapping-circles-app-or-Reject)80/限速器)
# 前端面试手册
> 来源:<https://www.frontendinterviewhandbook.com>
>
> 阶段:机翻(1)
\ No newline at end of file
+ [前端面试手册](README.md)
+ [介绍](01.md)
+ [琐碎问题](02.md)
+ [编码](03.md)
+ [前端面试中的 JavaScript 实用函数编码](04.md)
+ [前端访谈中的用户界面编码](05.md)
+ [前端面试中的编码算法](06.md)
+ [系统设计面试](07.md)
+ [前端系统设计面试概述](08.md)
+ [前端系统设计面试-用户界面组件](09.md)
+ [前端系统设计面试-应用](10.md)
+ [行为面试](11.md)
+ [简历准备](12.md)
+ [公司面试问题](13.md)
+ [谷歌前端面试问题](14.md)
+ [亚马逊前端面试问题](15.md)
+ [Microsoft 前端面试问题](16.md)
+ [苹果前端面试问题](17.md)
+ [Airbnb 前端面试问题](18.md)
+ [字节舞/titok 前端面试问题](19.md)
+ [Dropbox 前端面试问题](20.md)
+ [LinkedIn 前端面试问题](21.md)
+ [Lyft 前端面试问题](22.md)
+ [Salesforce 前端面试问题](23.md)
+ [Twitter 前端面试问题](24.md)
+ [优步前端面试问题](25.md)
# 零、序言
我们很高兴你决定加入我们学习系统设计面试。系统设计面试问题是所有技术面试中最难解决的。这些问题要求受访者为一个软件系统设计一个架构,这个软件系统可以是新闻提要、谷歌搜索、聊天系统等。这些问题令人生畏,没有一定的模式可循。这些问题通常范围很广,也很模糊。这些过程是开放式的,没有标准或正确的答案是不清楚的。
公司广泛采用系统设计面试,因为这些面试中测试的沟通和解决问题的技能与软件工程师日常工作所需的技能相似。受访者的评估基于她如何分析一个模糊的问题,以及她如何一步一步地解决问题。测试的能力还包括她如何解释想法,与他人讨论,以及评估和优化系统。在英语中,使用“她”比使用“他或她”或在两者之间跳跃更流畅。为了便于阅读,我们在整本书中使用了阴性代词。没有不尊重男性工程师的意思。
系统设计问题是开放式的。就像在现实世界中一样,系统中存在许多差异和变化。期望的结果是提出一个架构来实现系统设计目标。根据面试官的不同,讨论可能会以不同的方式进行。有的面试官可能会选择高层架构,涵盖方方面面;而有些人可能会选择一个或多个领域来关注。典型地,系统需求、限制和瓶颈应该被很好地理解以塑造访问者和被访问者的方向。
本书的目的是提供一个解决系统设计问题的可靠策略。正确的策略和知识对面试的成功至关重要。
这本书提供了构建可扩展系统的坚实知识。阅读这本书获得的知识越多,你就越有能力解决系统设计问题。
这本书也提供了一个逐步解决系统设计问题的框架。它提供了许多例子来说明系统化的方法以及您可以遵循的详细步骤。通过不断的练习, 你将有能力应对系统设计面试问题。
\ No newline at end of file
此差异已折叠。
# 二、信封背面估计
在系统设计面试中,有时你会被要求使用粗略估计来估计系统容量或性能需求。根据谷歌高级研究员 Jeff Dean 的说法,“信封背面的计算是你使用思维实验和常见性能数字的组合来创建的估计,以获得满足你要求的设计的良好感觉”[1]。
您需要对可伸缩性基础有一个很好的认识,以便有效地进行预估。应该很好地理解以下概念:2 的幂,每个程序员都应该知道的延迟数字,以及可用性数字。
## 二的幂
虽然在处理分布式系统时,数据量会变得巨大,但计算都归结为基础。为了获得正确的计算结果,使用 2 的幂知道数据量单位是非常重要的。一个字节是 8 位的序列。一个 ASCII 字符使用一个字节的内存(8 位)。下表解释了数据量单位(表 2-1)。
![A screenshot of a cell phone Description automatically generated](img/00027.jpeg)
## 每个程序员都应该知道的延迟数字
来自谷歌的迪恩博士揭示了 2010 年典型计算机操作的长度[1]。随着计算机变得更快更强大,一些数字已经过时了。然而,这些数字应该仍然能够让我们了解不同计算机操作的快慢。
![A screenshot of a cell phone Description automatically generated](img/00028.jpeg)
注释
-
ns =纳秒,s =微秒,ms =毫秒
1 纳秒= 10^-9 秒
1 秒= 10^-6 秒= 1000 纳秒
1 毫秒= 10^-3 秒= 1000 秒= 1000000 纳秒
一名谷歌软件工程师开发了一个工具来可视化迪安博士的数据。该工具还考虑了时间因素。图 2-1 显示了截至 2020 年的可视化延迟数字(图片来源:参考资料[3])。
![A screenshot of a cell phone Description automatically generated](img/00029.jpeg)
通过分析图 2-1 中的数字,我们得到以下结论:
内存快但磁盘慢。
尽可能避免磁盘寻道。
简单压缩算法速度快。
如果可能的话,在通过互联网发送数据之前对其进行压缩。
数据中心通常在不同的区域,它们之间发送数据需要时间。
## 可用性数字
高可用性是指系统在期望的长时间内持续运行的能力。高可用性以百分比来衡量,100%意味着服务没有停机时间。大多数服务介于 99%和 100%之间。
服务水平协议(SLA)是服务提供商常用的术语。这是您(服务提供商)和您的客户之间的协议,该协议正式定义了您的服务将提供的正常运行时间水平。云提供商亚马逊[4]、谷歌[5]和微软[6]将其 SLA 设定为 99.9%或以上。正常运行时间传统上是以 9 来衡量的。九越多越好。如表 2-3 所示,9 的数量与预期的系统停机时间相关。
![A screenshot of a cell phone Description automatically generated](img/00030.jpeg)
## 示例:估计 Twitter QPS 和存储需求
请注意,以下数字仅用于本练习,因为它们不是来自 Twitter 的真实数字。
假设:
3 亿月活跃用户。
50%的用户每天都使用 Twitter。
用户平均每天发布 2 条推文。
10%的推文包含媒体。
数据保存 5 年。
估计:
每秒查询(QPS)估计:
日活跃用户(DAU) = 3 亿* 50% = 1.5 亿
推文 QPS = 1.5 亿* 2 推文/ 24 小时/ 3600 秒= ~3500
峰值 QPS = 2 * QPS = ~7000
我们在这里只估计媒体存储量。
平均推文大小:
推特 _id 64 字节
文本 140 字节
媒体 1 MB
媒体存储:每天 1.5 亿* 2 * 10% * 1mb = 30tb
5 年介质存储:30 TB * 365 * 5 = ~55 PB
## 提示
信封背面的评估是关于整个过程的。解决问题比获得结果更重要。面试官可能会测试你解决问题的能力。以下是一些可以遵循的提示:
舍入和近似。面试时很难进行复杂的数学运算。比如“99987 / 9.1”是什么结果?没必要花宝贵的时间去解复杂的数学题。不期望精度。使用对你有利的整数和近似值。除法问题可以简化为:“10 万/ 10”。
写下你的假设。写下你的假设供以后参考是个好主意。
给你的单位贴上标签。你写下“5”,是指 5 KB 还是 5 MB?你可能会对此感到困惑。写下单位,因为“5 MB”有助于消除歧义。
常见的粗略估计:QPS、峰值 QPS、存储、缓存、服务器数量等。准备面试的时候可以练习一下这些计算。熟能生巧。
祝贺你走到这一步!现在给自己一个鼓励。干得好!
参考资料
【1】j .迪恩。Google Pro 提示:使用信封背面的计算来选择最佳设计:
[http://high scalability . com/blog/2011/1/26/Google-pro-tip-use-back-of-the-envelope-calculations-to-choo . html](http://highscalability.com/blog/2011/1/26/google-pro-tip-use-back-of-the-envelope-calculations-to-choo.html)
【2】系统设计入门:[](https://github.com/donnemartin/system-design-primer)
[3]每个程序员都应该知道的延迟数字:
[https://Colin-Scott . github . io/personal _ website/research/interactive _ latency . htmlT3】](https://colin-scott.github.io/personal_website/research/interactive_latency.html)
【4】亚马逊计算服务水平协议:
[https://aws.amazon.com/compute/sla/](https://aws.amazon.com/compute/sla/)
[5]计算引擎服务级别协议(SLA):
[https://cloud.google.com/compute/sla](https://cloud.google.com/compute/sla)
【6】Azure 服务的 SLA 概要:[https://Azure . Microsoft . com/en-us/support/legal/SLA/summary/](https://azure.microsoft.com/en-us/support/legal/sla/summary/)
\ No newline at end of file
此差异已折叠。
# 三、系统设计面试的框架
你刚刚获得了梦寐以求的理想公司的现场面试机会。招聘协调员会给你发一份当天的日程表。浏览列表,你会感觉很好,直到你的目光落在这个面试环节——系统设计面试。
系统设计面试通常令人生畏。它可以像“设计一个知名产品 X?”。这些问题模棱两可,而且似乎过于宽泛。你的疲倦是可以理解的。毕竟,怎么可能有人在一个小时内设计出一款流行的产品,而这需要数百甚至数千名工程师来完成?
好消息是没人期望你这么做。现实世界的系统设计极其复杂。例如,谷歌搜索看似简单;然而,支撑这种简单性的技术数量确实令人吃惊。如果没有人期望你在一个小时内设计出一个真实世界的系统,那么系统设计面试有什么好处呢?
系统设计面试模拟现实生活中的问题解决,两名员工合作解决一个模糊的问题,并提出一个符合他们目标的解决方案。这个问题是开放式的,没有完美的答案。与你在设计过程中所做的工作相比,最终的设计没有那么重要。这允许你展示你的设计技巧,捍卫你的设计选择,并以建设性的方式回应反馈。
让我们把桌子翻过来,想想面试官走进会议室见你时脑子里在想什么。面试官的首要目标是准确评估你的能力。她最不希望的就是给出一个不确定的评价,因为会议进行得很糟糕,没有足够的信号。在系统设计面试中,面试官想要的是什么?
许多人认为系统设计面试是关于一个人的技术设计技能。远不止如此。一次有效的系统设计面试会给出一个人的合作能力、在压力下工作的能力以及建设性地解决歧义的能力的强烈信号。问出好问题的能力也是一项必备技能,许多面试官专门寻找这项技能。
一个好的面试官也会寻找危险信号。过度工程是许多工程师的真正疾病,因为他们喜欢设计的纯粹性,而忽视权衡。他们常常意识不到过度设计系统的复合成本,许多公司为这种无知付出了高昂的代价。你肯定不希望在系统设计面试中表现出这种倾向。其他危险信号包括心胸狭窄、固执等。
在本章中,我们将复习一些有用的技巧,并介绍一个简单有效的框架来解决系统设计面试问题。
## 有效系统设计面试的 4 步流程
每个系统设计面试都不一样。伟大的系统设计面试是开放式的,没有放之四海而皆准的解决方案。然而,每个系统设计面试都有一些步骤和共同点。
### 第一步——了解问题并确定设计范围
“老虎为什么要吼叫?”
教室后面突然伸出一只手。
“是的,吉米?”,老师回应道。
“因为他饿了”。
“非常好的吉米。”
在童年时代,吉米总是第一个回答班上的问题。每当老师提问时,教室里总有一个孩子爱试着回答这个问题,不管他是否知道答案。那是吉米。
吉米是个优等生。他以很快知道所有答案而自豪。在考试中,他通常是第一个做完题目的人。他是教师参加任何学术竞赛的首选。
不要像吉米一样。
在系统设计面试中,不假思索地快速给出答案不会给你加分。没有完全理解要求的回答是一个巨大的危险信号,因为面试不是一个琐事竞赛。没有正确的答案。
因此,不要马上给出解决方案。慢点。深入思考,提出问题,明确需求和假设。这是极其重要的。
作为工程师,我们喜欢解决难题,一头扎进最终的设计中;然而,这种方法很可能会导致您设计错误的系统。作为一名工程师,最重要的技能之一是提出正确的问题,做出适当的假设,并收集构建系统所需的所有信息。所以,不要害怕提问。
当你提问时,面试官要么直接回答你的问题,要么让你做出假设。如果是后者,在白板或纸上写下你的假设。你以后可能需要它们。
问什么样的问题?提出问题,了解确切的要求。这里有一个帮助你开始的问题列表:
我们要构建什么样的特性?
产品有多少用户?
公司预计扩大规模的速度有多快?3 个月、6 个月和一年后的预期规模是多少?
公司的技术栈是什么?您可以利用哪些现有服务来简化设计?
#### 例子
如果你被要求设计一个新闻订阅系统,你会问一些有助于你阐明需求的问题。你和面试官之间的对话可能是这样的:
考生 :这是手机 app 吗?还是一个 web app?还是两者都有?
面试官 :都有。
候选人 :产品最重要的特点是什么?
面试官 :发帖和查看好友动态的能力。
候选人 : 新闻提要是按时间倒序排序还是按特定顺序排序?这种特殊的顺序意味着每个帖子被赋予不同的权重。例如,来自你亲密朋友的帖子比来自一个团体的帖子更重要。
面试官 : 为了简单起见,我们假设提要是按时间倒序排序的。
候选人 : 一个用户可以有多少好友?
面试官 : 5000
候选人 :车流量是多少?
面试官 :日活跃用户 1000 万(DAU)
候选:feed 可以包含图片、视频,或者只是文字?
面试官 :可以包含媒体文件,包括图片和视频。
以上是你可以问面试官的一些问题。理解需求和澄清歧义很重要
### 第二步——提出高水平的设计并获得认同
在这一步,我们的目标是开发一个高层次的设计,并与面试官就设计达成一致。在面试过程中与面试官合作是个好主意。
拿出最初的设计蓝图。寻求反馈。把你的面试官当成队友,一起努力。许多优秀的面试官喜欢交谈和参与。
在白板或纸上画出关键部件的方框图。这可能包括客户端(移动/web)、API、web 服务器、数据存储、缓存、CDN、消息队列等。
进行粗略计算,评估你的蓝图是否符合规模限制。大声思考。在深入调查之前,如果有必要的话,和面试官交流一下。
如果可能的话,浏览几个具体的用例。这将帮助您构建高层次的设计。用例也有可能帮助您发现您还没有考虑的边缘用例。
我们应该在这里包括 API 端点和数据库模式吗?这个要看问题。对于“设计谷歌搜索引擎”这样的大型设计问题来说,这有点太低级了。对于像为多人扑克游戏设计后端这样的问题,这是一个公平的游戏。与你的面试官交流。
#### 例子
让我们用“设计一个新闻反馈系统”来演示如何进行高级设计。在这里 你不需要了解系统实际上是如何工作的。所有细节将在第 11 章解释。
在高层次上,设计分为两个流程:提要发布和新闻提要构建。
Feed 发布:当用户发布帖子时,相应的数据被写入缓存/数据库,该帖子将被填充到好友的新闻 Feed 中。
新闻提要构建:新闻提要是通过按时间倒序聚合朋友的帖子来构建的。
图 3-1 和图 3-2 分别展示了提要发布和新闻提要构建流程的高级设计。
![A close up of a map Description automatically generated](img/00031.jpeg)
![A close up of a logo Description automatically generated](img/00032.jpeg)
### 第三步——设计深潜
在这一步,你和你的面试官应该已经达到了以下目标:
商定总体目标和功能范围
勾画出总体设计的高层次蓝图
从你的面试官那里获得了关于高层设计的反馈
根据她的反馈,对深度探索中需要关注的领域有了一些初步想法
你应该和面试官一起确定架构中组件的优先级。值得强调的是,每次面试都是不同的。有时候,面试官可能会暗示她喜欢关注高层次的设计。有时,对于高级候选人面试,讨论可能是关于系统性能特征,可能集中在瓶颈和资源估计上。在大多数情况下,面试官可能希望你深入了解一些系统组件的细节。对于 URL shortener,深入研究将长 URL 转换成短 URL 的哈希函数设计是很有趣的。对于一个聊天系统来说,如何减少延迟和如何支持在线/离线状态是两个有趣的话题。
时间管理是必不可少的,因为人们很容易被无法展示你能力的微小细节冲昏头脑。你必须准备好向面试官展示的信号。尽量不要陷入不必要的细节。例如,在系统设计面试中详细讨论脸书 feed 排名的 EdgeRank 算法是不理想的,因为这会花费很多宝贵的时间,并且不能证明你设计可扩展系统的能力。
#### 例子
至此,我们已经讨论了新闻订阅系统的高级设计,面试官对你的提议很满意。接下来,我们将研究两个最重要的用例:
1。订阅源发布
2。新闻提要检索
图 3-3 和图 3-4 显示了两个用例的详细设计,这将在第 11 章中详细解释。
![A close up of a map Description automatically generated](img/00033.jpeg)
![A close up of a map Description automatically generated](img/00034.jpeg)
### 第四步——总结
在这最后一步,面试官可能会问你几个后续问题,或者给你讨论其他要点的自由。这里有几个方向可以遵循:
面试官可能希望你找出系统的瓶颈并讨论潜在的改进。永远不要说你的设计是完美的,没有什么可以改进的。总有需要改进的地方。这是一个展示你批判性思维并留下好的最终印象的好机会。
给面试官回顾一下你的设计可能会有帮助。如果你提出了一些解决方案,这一点尤为重要。在长时间的谈话后,刷新面试官的记忆会很有帮助。
错误案例(服务器故障、网络丢失等。)都是很有意思的话题。
运营问题值得一提。如何监控指标和错误日志?如何铺开系统?
如何处理下一个比例曲线也是一个有趣的话题。例如,如果您当前的设计支持 100 万用户,您需要做哪些更改来支持 1000 万用户?
如果你有更多的时间,提出你需要的其他改进。
作为总结,我们总结了一系列该做和不该做的事情。
Dos
总是要求澄清。不要假设你的假设是正确的。
理解问题的要求。
没有正确的答案,也没有最好的答案。旨在解决年轻初创公司问题的解决方案不同于拥有数百万用户的老牌公司。确保你理解这些要求。
让面试官知道你在想什么。和你的面试沟通。
如有可能,建议多种方法。
一旦你和面试官就蓝图达成一致,就要详细讨论每一部分。首先设计最关键的部件。
向面试官反映想法。一个好的面试官像队友一样和你一起工作。
永不放弃。
不要做
不要对典型的面试问题毫无准备。
在没有明确需求和假设的情况下,不要急于找到解决方案。
不要一开始就对单个组件进行过多的细节描述。首先给出概要设计,然后再向下钻取。
如果你卡住了,不要犹豫,寻求提示。
再次沟通。不要在沉默中思考。
不要以为一旦你给出了设计,你的面试就结束了。直到你的面试官说你结束了,你才算结束。尽早并经常寻求反馈。
### 每一步上的时间分配
系统设计面试问题通常非常宽泛,45 分钟或者一个小时都不足以涵盖整个设计。时间管理至关重要。每一步应该花多少时间?以下是在 45 分钟的面试中分配时间的粗略指南。请记住这是一个粗略的估计,实际的时间分布取决于问题的范围和面试官的要求。
第一步了解问题并确定设计范围:3 - 10 分钟
步骤 2 提出高级设计并获得认同:10 - 15 分钟
第三步设计深潜:10 - 25 分钟
第四步包装:3 - 5 分钟
# 五、设计一致哈希
为了实现水平扩展,在服务器之间高效、均匀地分配请求/数据非常重要。一致哈希是实现这一目标的常用技术。但首先,让我们深入研究一下这个问题。
## 老调重弹问题
如果你有 n 个缓存服务器,平衡负载的一个常用方法是使用下面的哈希方法:
server index = hash(key)% N,其中 N 是服务器池的大小。
让我们用一个例子来说明它是如何工作的。如表 5-1 所示,我们有 4 台服务器和 8 个带哈希的字符串键。
![A screenshot of a cell phone Description automatically generated](img/00052.jpeg)
为了获取存储密钥的服务器,我们执行模块化操作 f(key) % 4 。例如, hash(key0) % 4 = 1 表示客户端必须联系服务器 1 来获取缓存的数据。图 5-1 显示了基于表 5-1 的键的分布。
![A close up of text on a white background Description automatically generated](img/00053.jpeg)
当服务器池的大小固定且数据分布均匀时,这种方法非常有效。然而,当添加新的服务器或者移除现有的服务器时,问题 出现 。例如,如果服务器 1 脱机,服务器池的大小将变为 3。 使用相同的哈希函数,我们得到一个键的相同哈希值。但是应用模运算给了我们不同的服务器索引,因为服务器的数量减少了 1。 我们应用 hash % 3 : 得到如表 5-2 所示的结果
![A screenshot of a cell phone Description automatically generated](img/00054.jpeg)
图 5-2 显示了基于表 5-2 的新的密钥分布。
![A screenshot of a cell phone Description automatically generated](img/00055.jpeg)
如图 5-2 所示,大部分的键都是重新分配的,而不仅仅是原来存储在离线服务器(服务器 1)中的那些。 这意味着当服务器 1 离线时,大多数缓存客户端将连接到错误的服务器来获取数据。这导致了高速缓存未命中的风暴。一致哈希是缓解这一问题的有效技术。
## 一致哈希
引自维基百科:“一致哈希是一种特殊的哈希,当哈希表重新调整大小并使用一致哈希时,平均只有k/n个键需要重新映射,其中 k 是键的数量,n 是槽的数量。相反,在大多数传统哈希表中,数组槽数量的变化会导致几乎所有的键被重新映射[1]”。
### 哈希空间和哈希环
现在我们了解了一致性哈希的定义,让我们看看它是如何工作的。假设 SHA-1 作为哈希函数 f, 哈希函数的输出 范围为 : x0,x1,x2,x3,…,xn 。在密码学中,SHA-1 的哈希空间从 0 到 2^160 - 1。这意味着 x0 对应于 0, xn 对应于 2^160 - 1,中间的所有其他哈希值落在 0 和 2^160-1 之间。图 5-3 显示了哈希空间。
![A close up of a logo Description automatically generated](img/00056.jpeg)
通过连接两端,我们得到一个哈希环如图 图 5-4 :
![A close up of a lamp Description automatically generated](img/00057.jpeg)
### 哈希服务器
使用相同的哈希函数 f ,我们基于服务器 IP 或名称将服务器映射到环上。图 5-5 显示了 4 个服务器被映射到哈希环上。
![A necklace on a table Description automatically generated](img/00058.jpeg)
### 哈希键
值得一提的是,这里使用的 hash 函数与“重哈希问题”中的不同,没有模运算。如图 5-6 所示,4 个缓存键(key0、key1、key2 和 key3)被哈希到哈希环上
![A close up of a necklace Description automatically generated](img/00059.jpeg)
### 服务器查找
为了确定一个密钥存储在哪个服务器上,我们从环上的密钥位置开始顺时针旋转,直到找到一个服务器。 图 5-7 解释了这个过程。顺时针转动 , 键 0 存储在 服务器 0 上; key1 存储在 服务器 1 上; key2 存储在 服务器 2 和 key3 存储在 服务器 3 。
![A necklace hanging on a wall Description automatically generated](img/00060.jpeg)
### 添加服务器
使用上述逻辑,添加新的服务器将只需要重新分发一小部分密钥。
在图 5-8 中,增加了一个新的 服务器 4 后,只有 key0 需要重新分配。 k1、k2、 和 k3 保持在相同的服务器上。让我们仔细看看其中的逻辑。在添加 服务器 4 之前, key0 存储在 服务器 0 上。现在, key0 将被存储在 server 4 上,因为 server 4 是它从 key0 在环上的位置顺时针方向遇到的第一个服务器。其他密钥不会基于一致的哈希算法进行重新分配。
![A picture containing necklace Description automatically generated](img/00061.jpeg)
### 移除一个服务器
当服务器被移除时,只有一小部分密钥需要用一致的哈希法重新分配。在图 5-9 中,当 服务器 1 被移除后,只有 key1 必须重新映射到 服务器 2 。其余的键不受影响。
![A picture containing necklace Description automatically generated](img/00062.jpeg)
### 两个问题的基本处理方法
一致性哈希算法是由 Karger 等人在麻省理工学院提出的[1]。基本步骤是:
使用均匀分布的哈希函数将服务器和密钥映射到环上。
要找出一个密钥映射到哪个服务器,从密钥位置开始顺时针方向走,直到找到环上的第一个服务器。
这种方法发现了两个问题。首先,考虑到可以添加或移除服务器,不可能为环上的所有服务器保持相同大小的分区。分区是相邻服务器之间的哈希空间。分配给每个服务器的环上的分区的大小可能非常小或相当大。在图 5-10 中,如果去掉 s1 , s2 的 分区(用双向箭头突出显示)是 s0 和 s3 的 分区的两倍。
![A close up of a necklace Description automatically generated](img/00063.jpeg)
第二,环上可能有不均匀的密钥分布。例如,如果服务器被映射到图 5-11 中列出的位置,那么大部分密钥都存储在 服务器 2 上。但是 服务器 1服务器 3 没有数据。
![A necklace with a piece of paper Description automatically generated](img/00064.jpeg)
一种叫做虚拟节点或副本的技术被用来解决这些问题。
### 虚拟节点
虚拟节点是指真实节点,每个服务器由环上的多个虚拟节点表示。在图 5-12 中, 服务器 0 和 服务器 1 都有 3 个虚拟节点。3 是任意选择的;而在现实世界的系统中,虚拟节点的数量要大得多。我们没有用 s0 ,而是用 s0_0,s0_1 ,s0_2 来代表环上的 服务器 0 。同样, s1_0,s1_1 ,和 s1_2 代表环上的服务器 1。对于虚拟节点,每台服务器负责多个分区。标签为 s0 的分区(边缘)由服务器 0 管理。另一方面,标签为 s1 的分区由 服务器 1 管理。
![A necklace looking at the camera Description automatically generated](img/00065.jpeg)
为了找到一个密钥存储在哪个服务器上,我们从密钥的位置开始顺时针方向,找到环上遇到的第一个虚拟节点。在图 5-13 中,为了找出 k0 存储在哪个服务器上,我们从 k0 的位置顺时针方向,找到虚拟节点 s1_1 ,它指的是 服务器 1 。
![A picture containing accessory, necklace, table, phone Description automatically generated](img/00066.jpeg)
随着虚拟节点数量的增加,键的分布变得更加均衡。这是因为虚拟节点越多,标准偏差就越小,从而导致平衡的数据分布。标准差衡量数据是如何分布的。online research [2]进行的实验结果显示,对于一个或两百个虚拟节点,标准偏差在平均值的 5% (200 个虚拟节点)和 10% (100 个虚拟节点)之间。当我们增加虚拟节点的数量时,标准偏差会更小。然而,需要更多的空间来存储关于虚拟节点的数据。这是一种权衡,我们可以调整虚拟节点的数量来适应我们的系统需求。
### 找到受影响的按键
当添加或删除服务器时,需要重新分配一小部分数据。如何找到受影响的范围来重新分配密钥?
在图 5-14 中, 服务器 4 被添加到环上。受影响的范围从 s4 (新增节点)开始,绕环逆时针移动,直到找到一个服务器( s3 )。因此,位于 s3 和 s4 之间的键需要重新分配给 s4 。
![A picture containing necklace Description automatically generated](img/00067.jpeg)
当一个服务器( s1 )被移除时,如图 5-15 所示,受影响的范围从 s1 (被移除的节点)开始,绕环逆时针移动,直到找到一个服务器( s0 )。因此,位于 s0 和 s1 之间的键必须重新分配给 s2 。
![A picture containing necklace Description automatically generated](img/00068.jpeg)
## 总结起来
在本章中,我们深入讨论了一致性哈希,包括为什么需要它以及它是如何工作的。一致哈希的好处包括:
添加或删除服务器时,最小化的密钥会重新分配。
因为数据分布更均匀,所以水平缩放更容易。
缓解热点关键问题。对特定碎片的过度访问可能会导致服务器过载。想象一下凯蒂·佩里、贾斯汀比伯和 Lady Gaga 的数据都在同一个碎片上。一致哈希通过更均匀地分布数据来帮助缓解这个问题。
一致性哈希在现实世界的系统中被广泛使用,包括一些著名的:
亚马逊迪纳摩数据库分区组件【3】
Apache Cassandra[4]中跨集群的数据分区
不和谐聊天应用【5】
Akamai 内容交付网络【6】
磁悬浮网络负载均衡器【7】
祝贺你走到这一步!现在给自己一个鼓励。干得好!
参考资料
【1】一致哈希:[](https://en.wikipedia.org/wiki/Consistent_hashing)
[2]一致性哈希:
[https://tom-e-white.com/2007/11/consistent-hashing.html](https://tom-e-white.com/2007/11/consistent-hashing.html)
【3】Dynamo:亚马逊高可用键值存储:[https://www . all things distributed . com/files/Amazon-Dynamo-sosp 2007 . pdf](https://www.allthingsdistributed.com/files/amazon-dynamo-sosp2007.pdf)
【4】Cassandra——一个去中心化的结构化存储系统:
[http://www . cs . Cornell . edu/Projects/ladis 2009/papers/Lakshman-ladis 2009。PDFT3】](http://www.cs.cornell.edu/Projects/ladis2009/papers/Lakshman-ladis2009.PDF)
【5】Discord 如何将仙丹扩展到 500 万并发用户:[【https://blog.discord.com/scaling-elixir-f9b8e1e7c29b】](https://blog.discord.com/scaling-elixir-f9b8e1e7c29b)
【6】cs 168:现代算法工具箱讲座#1:介绍与一致性哈希:[【http://theory.stanford.edu/~tim/s16/l/l1.pdf】](http://theory.stanford.edu/~tim/s16/l/l1.pdf)
【7】Maglev:一款快速可靠的软件网络负载均衡器:[https://static . Google user content . com/media/research . Google . com/en//pubs/archive/44824 . pdf](https://static.googleusercontent.com/media/research.google.com/en//pubs/archive/44824.pdf)
\ No newline at end of file
此差异已折叠。
# 七、设计分布式系统中的唯一 ID 生成器
在这一章中,你被要求在分布式系统中设计一个唯一的 ID 生成器。您首先想到的可能是在传统数据库中使用带有 auto_increment 属性的主键。然而, auto_increment 在分布式环境中不起作用,因为单个数据库服务器不够大,并且在最小延迟的情况下跨多个数据库生成唯一的 id 具有挑战性。
这里有几个唯一 id 的例子:
![A screenshot of a cell phone Description automatically generated](img/00092.jpeg)
## 步骤 1 -了解问题并确定设计范围
提出澄清性问题是解决任何系统设计面试问题的第一步。下面是一个应聘者与面试官互动的例子:
候选人 :唯一 id 有什么特点?
采访者 :身份证必须是唯一的,可排序的。
候选人 :每增加一条新记录,ID 增加 1 吗?
面试官:ID 随时间递增,但不一定只递增 1。同一天晚上创建的 id 比早上创建的 id 大。
候选人:id 只包含数值吗?
面试官 :是的,没错。
考生 :身份证长度有什么要求?
采访者 :身份证应该是 64 位的。
候选人 :系统的规模是多少?
面试官 :系统每秒应该能生成 10000 个 id。
以上是你可以问面试官的一些问题。理解需求和澄清歧义是很重要的。对于这个面试问题,要求如下:
id 必须唯一。
id 仅为数值。
IDs 适合 64 位。
id 按日期排序。
每秒生成超过 10,000 个唯一 id 的能力。
## 第二步——提出高水平的设计并获得认同
在分布式系统中,可以使用多个选项来生成唯一的 id。我们考虑的选项有:
多主复制
【UUID】
票务服务器
推特雪花逼近
让我们来看看每一种方法,它们是如何工作的,以及每种方法的优缺点。
### 多主机复制
如图 7-2 所示,第一种方法是多主机复制。
![A close up of a map Description automatically generated](img/00093.jpeg)
这种方式使用了数据库的auto _ increment特性。我们没有将下一个 ID 增加 1,而是增加了 k, ,其中 k 是正在使用的数据库服务器的数量。如图 7-2 所示,要生成的下一个 ID 等于同一服务器中的前一个 ID 加 2。这解决了一些可伸缩性问题,因为 IDs 可以随着数据库服务器的数量而伸缩。然而,这种策略有一些主要的缺点:
难以扩展多个数据中心
跨多台服务器的 IDs 不随时间上升。
添加或删除服务器时,它无法很好地扩展。
### UUID
UUID 是获得唯一 ID 的另一种简单方法。UUID 是一个 128 位的数字,用于识别计算机系统中的信息。UUID 获得共谋的概率非常低。引用维基百科,“在大约 100 年内每秒生成 10 亿个 UUIDs 后,创建一个单一副本的概率会达到 50%”[1]。
下面举个 UUID 的例子:09 c93e 62-50 B4-468d-bf8a-c 07e 1040 bfb 2。可以独立生成,不需要服务器之间的协调。图 7-3 展示了 UUIDs 的设计。
![A screenshot of a cell phone Description automatically generated](img/00094.jpeg)
在这个设计中,每个 web 服务器都包含一个 ID 生成器,一个 web 服务器独立负责生成 ID。
优点:
生成 UUID 很简单。服务器之间不需要协调,所以不会有任何同步问题。
这个系统很容易扩展,因为每个 web 服务器负责生成它们所使用的 id。ID 生成器可以很容易地与 web 服务器一起伸缩。
缺点:
id 是 128 位长,但我们的要求是 64 位。
id 不随时间而涨。
id 可以是非数字的。
### 票务服务器
票证服务器是另一种生成唯一 id 的有趣方式。Flicker 开发了票证服务器来生成分布式主键[2]。值得一提的是这个系统是如何工作的。
![A close up of a piece of paper Description automatically generated](img/00095.jpeg)
这个想法是在单个数据库服务器(票证服务器)中使用集中式的 自动增量 功能。要了解这方面的更多信息,请参考 flicker 的工程博客文章[2]。
优点:
数字标识。
易于实现,适用于中小型应用。
缺点:
单点故障。单一票证服务器意味着如果票证服务器宕机,所有依赖它的系统都将面临问题。为了避免单点故障,我们可以设置多个票证服务器。然而,这将引入新的挑战,例如数据同步。
### 推特雪花接近
上面提到的方法给了我们一些关于不同 ID 生成系统如何工作的想法。然而,它们都不符合我们的具体要求;因此,我们需要另一种方法。Twitter 独特的 ID 生成系统叫做“雪花”[3]很有启发性,可以满足我们的要求。
分而治之是我们的朋友。我们不是直接生成 ID,而是将 ID 分成不同的部分。图 7-5 显示了一个 64 位 ID 的布局。
![A screenshot of a cell phone Description automatically generated](img/00096.jpeg)
每一部分解释如下。
标志位:1 位。它将永远是 0。这是为将来使用而保留的。它可以潜在地用于区分有符号和无符号数。
时间戳:41 位。自纪元或自定义纪元以来的毫秒数。我们使用 Twitter 雪花默认纪元 1288834974657,相当于 2010 年 11 月 4 日 01:42:54 UTC。
数据中心 ID: 5 位,这给了我们 2 ^ 5 = 32 数据中心。
机器 ID: 5 位,即每个数据中心有 2 台^ 5 = 32 台 机器。
序号:12 位 。对于在该机器/进程上生成的每个 ID,序列号增加 1。该数字每毫秒重置为 0。
## 步骤 3 -设计深度潜水
在概要设计中,我们讨论了在分布式系统中设计唯一 ID 生成器的各种方案。我们决定采用一种基于 Twitter 雪花 ID 生成器的方法。让我们深入研究一下这个设计。为了提醒我们,下面重新列出了设计图。
![A screenshot of a cell phone Description automatically generated](img/00097.jpeg)
数据中心 id 和机器 id 在启动时选择,通常在系统启动运行后固定。数据中心 ID 和机器 ID 的任何更改都需要仔细检查,因为这些值的意外更改会导致 ID 冲突。ID 生成器运行时会生成时间戳和序列号。
时间戳
最重要的 41 位组成时间戳部分。随着时间戳随着时间的增长,id 可以按时间排序。图 7-7 显示了一个二进制表示如何转换成 UTC 的例子。您也可以使用类似的方法将 UTC 转换回二进制表示。
![A screenshot of a cell phone Description automatically generated](img/00098.jpeg)
可以用 41 位表示的最大时间戳是
2 ^ 41 - 1 = 2199023255551 毫秒(ms),由此我们得到:~ 69 年=
2199023255551 毫秒/ 1000 秒/ 365 天/ 24 小时/ 3600 秒 。这意味着 ID 生成器将工作 69 年,拥有一个接近今天日期的自定义纪元时间会延迟溢出时间。69 年后,我们将需要一个新的纪元时间或采用其他技术来迁移 IDs。
序号
序列号是 12 位,这给我们 2 个^ 12 = 4096 个组合。除非在同一台服务器上一毫秒内生成了多个 ID,否则该字段为 0。理论上,一台机器每毫秒最多可以支持 4096 个新 id。
## 步骤 4 -总结
在本章中,我们讨论了设计唯一 ID 生成器的不同方法:多主机复制、UUID、票据服务器和 Twitter 雪花型唯一 ID 生成器。我们选择了雪花,因为它支持我们所有的用例,并且可以在分布式环境中扩展。
如果在采访结束时有额外的时间,这里有一些额外的谈话要点:
时钟同步。在我们的设计中,我们假设 ID 生成服务器具有相同的时钟。当服务器在多个内核上运行时,这种假设可能不成立。在多机场景中也存在同样的挑战。时钟同步的解决方案超出了本书的范围;然而,了解问题的存在是很重要的。网络时间协议是解决这个问题的最流行的方法。感兴趣的读者可以参考参考资料[4]。
分段长度调谐。例如,更少的序列号但更多的时间戳位对于低并发性和长期应用程序是有效的。
高可用性。因为 ID 生成器是一个任务关键型系统,所以它必须高度可用。
祝贺你走到这一步!现在给自己一个鼓励。干得好!
参考资料
【1】通用唯一标识符:[](https://en.wikipedia.org/wiki/Universally_unique_identifier)
【2】票服务器:廉价的分布式唯一主键:
[https://code . Flickr . net/2010/02/08/ticket-servers-distributed-unique-primary-keys-on-the-cheap/T3】](https://code.flickr.net/2010/02/08/ticket-servers-distributed-unique-primary-keys-on-the-cheap/)
【3】宣布雪花:[https://blog . Twitter . com/engineering/en _ us/a/2010/Announcing-snow flake . html](https://blog.twitter.com/engineering/en_us/a/2010/announcing-snowflake.html)
【4】网络时间协议:[](https://en.wikipedia.org/wiki/Network_Time_Protocol)
\ No newline at end of file
# 八、设计 URL 缩短器
在这一章中,我们将解决一个有趣而经典的系统设计面试问题:设计一个像 tinyurl 这样的 URL 缩短服务。
## 第一步——了解问题并确定设计范围
系统设计面试问题有意留有开放性。要设计一个精心制作的系统,提出澄清性问题至关重要。
候选人 :你能举例说明网址缩写是如何工作的吗?
面试官 :假设 URL https://www.systeminterview.com/q=chatsystem&c = logged in&v = v3&l = long 是原 URL。您的服务创建了一个较短的别名:https://tinyurl.com/ y7 keocwj。如果您单击别名,它会将您重定向到原始 URL。
候选人 :车流量是多少?
面试官 :每天产生 1 亿个网址。
候选人 :网址缩短后有多长?
面试官 :尽量简短。
候选人 :网址缩写中允许使用哪些字符?
面试官 :网址缩写可以是数字(0-9)和字符(a-z,A-Z)的组合。
候选人 :可以删除或更新缩短的网址吗?
采访者 :为了简单起见,我们假设被缩短的网址不能被删除或更新。
以下是基本用例:
1。URL 缩短:给定一个长 URL = >返回一个短得多的 URL
2。URL 重定向:给定一个较短的 URL = >重定向到原来的 URL
3。高可用性、可扩展性和容错考虑
### 信封估算的背面
写操作:每天产生 1 亿个 URL。
每秒写操作数:1 亿/ 24 /3600 = 1160
读操作:假设读操作与写操作之比为 10:1,每秒读操作数:1160 * 10 = 11600
假设网址缩写服务将运行 10 年,这意味着我们必须支持 1 亿* 365 = 365 亿条记录。
假设平均 URL 长度为 100。
超过 10 年的存储需求:3650 亿* 100 字节* 10 年= 365 TB
对你来说,和你的面试官一起回顾假设和计算是很重要的,这样你们两个就能达成共识。
## 第二步——提出高层次设计并获得认同
在本节中,我们将讨论 API 端点、URL 重定向和 URL 缩短流程。
### API 终点
API 端点促进了客户端和服务器之间的通信。我们将设计 REST 风格的 API。如果对 restful API 不熟悉,可以参考外部资料,比如参考资料[1]中的那个。一个 URL shortener primary 需要两个 API 端点。
1。URL 缩短。为了创建一个新的短 URL,客户端发送一个 POST 请求,其中包含一个参数:原始的长 URL。API 看起来是这样的:
发布 api/v1/data/shorten
请求参数:{longUrl: longURLString}
返回快捷链接
2。URL 重定向。为了将短 URL 重定向到相应的长 URL,客户端发送 GET 请求。API 看起来是这样的:
获取 api/v1/shortUrl
返回 HTTP 重定向的 longURL】
### 网址重定向
图 8-1 显示了当你在浏览器上输入一个 tinyurl 时会发生什么。一旦服务器接收到 tinyurl 请求,它会使用 301 重定向将短 url 更改为长 URL。
![A screenshot of a social media post Description automatically generated](img/00099.jpeg)
客户端和服务器之间的详细通信如图 8-2 所示。
![A close up of a map Description automatically generated](img/00100.jpeg)
这里值得讨论的一点是 301 重定向 vs 302 重定向。
301 重定向 。301 重定向显示所请求的 URL 被“永久”移动到长 URL。因为它是永久重定向的,所以浏览器缓存响应,并且对同一 URL 的后续请求将不会被发送到 URL 缩短服务。相反,请求被直接重定向到长 URL 服务器。
302 重定向 。302 重定向意味着 URL 被“临时”移动到长 URL,这意味着对同一 URL 的后续请求将首先被发送到 URL 缩短服务。然后,它们被重定向到长 URL 服务器。
每种重定向方法都有其优点和缺点。如果优先考虑的是减少服务器负载,使用 301 重定向是有意义的,因为只有相同 URL 的第一个请求被发送到 URL 缩短服务器。然而,如果分析很重要,302 重定向是一个更好的选择,因为它可以更容易地跟踪点击率和点击来源。
实现 URL 重定向最直观的方法是使用哈希表。假设哈希表存储了 < shortURLlongURL > 对,URL 重定向可以通过以下方式实现:
获取 longURL:longURL = hashtable . Get(short URL)
一旦获得长 URL,就执行 URL 重定向。
### 网址缩短
让我们假设短 URL 是这样的:www.tinyurl.com/{ hash value }。为了支持 URL 缩短用例,我们必须找到一个哈希函数nfx将一个长 URL 映射到 hashValue ,如图 8-3 所示。
![A close up of text on a white background Description automatically generated](img/00101.jpeg)
哈希函数必须满足以下要求:
每个 长 URL 都必须哈希为一个 哈希值 。
每个 的哈希值 都可以映射回 longURL 。
深入讨论哈希函数的详细设计。
## 步骤 3 -设计深度潜水
到目前为止,我们已经讨论了 URL 缩短和 URL 重定向的高级设计 - 。在本节中,我们将深入探讨以下内容:数据模型、哈希函数、URL 缩短和 URL 重定向。
### 数据模型
在高层设计中,一切都存储在哈希表中。这是一个很好的起点;然而,这种方法对于真实世界的系统是不可行的,因为存储器资源是有限的并且昂贵的。更好的选择是在关系数据库中存储 < shortURLlongURL > 映射。图 8-4 显示了一个简单的数据库表设计。表格的简化版包含 3 列: id , shortURL,longURL 。
![A screenshot of a cell phone Description automatically generated](img/00102.jpeg)
### 哈希函数
Hash 函数用于将一个长 URL 哈希成一个短 URL,也称为 hashValue 。
#### 哈希值长度
的哈希值 由[0-9,a-z,A-Z]的字符组成,包含 10 + 26 + 26 = 62 个可能的字符。求 的长度有一个值 ,求最小的 n 使得62^n≥3650 亿 。该系统必须支持高达 3650 亿网址的基础上回来的信封估计。表 8-1 显示了 hashValue 的长度及其对应的可以支持的最大 URL 数。
![A screenshot of a cell phone Description automatically generated](img/00103.jpeg)
当 n = 7,62 ^ n = ~3.5 万亿 时,3.5 万亿容纳 3650 亿个 URL 绰绰有余,所以 的长度 hashValue 为 7。
我们将探讨两种类型的 URL 缩写哈希函数。第一个是“哈希+冲突解决”,第二个是“base 62 转换”。让我们一个一个来看。
#### 哈希+冲突解决
为了缩短一个长 URL,我们应该实现一个哈希函数,将一个长 URL 哈希成一个 7 个字符的字符串。一个简单的解决方案是使用众所周知的哈希函数,如 CRC32、MD5 或 SHA-1。下表比较了对该 URL 应用不同哈希函数后的哈希结果:https://en.wikipedia.org/wiki/Systems_design.
![A screenshot of a cell phone Description automatically generated](img/00104.jpeg)
如表 8-2 所示,即使是最短的哈希值(来自 CRC32)也太长(超过 7 个字符)。怎么才能让它变短?
第一种方法是收集哈希值的前 7 个字符;但是,这种方法会导致哈希冲突。为了解决哈希冲突,我们可以递归地添加一个新的预定义字符串,直到不再发现冲突。这个过程如图 8-5 所示。
![A close up of a map Description automatically generated](img/00105.jpeg)
这种方法可以消除碰撞;然而,查询数据库来检查是否每个请求都有一个 shortURL 是很昂贵的。一种叫做 bloom filters [2]的技术可以提高性能。布隆过滤器是一种节省空间的概率技术,用于测试元素是否是集合的成员。更多详情请参考参考资料[2]。
#### 基数 62 转换
基本转换是 URL 缩写常用的另一种方法。基本转换有助于在不同的数字表示系统之间转换相同的数字。由于 的哈希值 有 62 个可能的字符,所以使用 62 进制转换。让我们用一个例子来说明转换是如何进行的:将 1115710转换为基数为 62 的表示(1115710在基数为 10 的系统中表示 11157)。
顾名思义,base 62 是使用 62 个字符进行编码的一种方式。映射的是: 0-0、...、9-9、10-a、11-b、...,35-z,36-A,...,61-Z,其中‘a’代表 10,‘Z’代表 61,以此类推。
1115710= 2 X 622+55 X 621+59 X 620=【2,55,59】->【2,T,X】以 62 为基数表示。图 8-6 显示了对话过程。
![A close up of text on a white background Description automatically generated](img/00106.jpeg)
这样,短网址就是 https://tinyurl.com/2TX
#### 两种方法的比较
表 8-3 显示了这两种方法的区别。
![A screenshot of a cell phone Description automatically generated](img/00107.jpeg)
### 网址缩短深度剖析
作为系统的核心部分之一,我们希望 URL 缩短流程在逻辑上简单且实用。我们的设计采用 62 进制转换。我们构建了下图(图 8-7)来演示这个流程。
![A close up of a map Description automatically generated](img/00108.jpeg)
1。longURL 是输入。
2。系统检查长 URL 是否在数据库中。
3。如果是,则意味着 longURL 之前被转换为 shortURL。在这种情况下,从数据库获取 shortURL 并将其返回给客户端。
4。如果不是,则 longURL 是新的。唯一 ID 生成器生成新的唯一 ID(主键)。
5。使用 base 62 转换将 ID 转换为 shortURL。
6。用 ID、shortURL 和 longURL 创建新的数据库行。
为了让流程更容易理解,让我们看一个具体的例子。
假设输入的 longURL 是:https://en.wikipedia.org/wiki/Systems_design
唯一 ID 生成器返回 ID: 2009215674938。
使用 62 进制转换将 ID 转换为 shortURL。ID (2009215674938)转换为“zn9edcu”。
将 ID、shortURL 和 longURL 保存到数据库,如表 8-4 所示。
![A screenshot of a cell phone Description automatically generated](img/00109.jpeg)
值得一提的是分布式唯一 ID 生成器。它的主要功能是生成全局唯一的 id,用于创建 shortURLs。在高度分布式的环境中,实现唯一的 ID 生成器是一项挑战。幸运的是,我们已经在“第 7 章:在分布式系统中设计唯一的 ID 生成器”中讨论了一些解决方案。你可以回头参考一下,以唤起你的记忆。
### URL 重定向深潜
图 8-8 显示了 URL 重定向的详细设计。由于读取比写入多, < shortURLlongURL > 映射存储在缓存中以提高性能。
![A screenshot of a cell phone Description automatically generated](img/00110.jpeg)
URL 重定向的流程总结如下:
1。用户点击一个短的网址链接:https://tinyurl.com/zn9edcu
2。负载平衡器将请求转发给 web 服务器。
3。如果 shortURL 已经在缓存中,则直接返回 longURL。
4。如果 shortURL 不在缓存中,则从数据库中获取 longURL。如果它不在数据库中,则可能是用户输入了无效的 shortURL。
5。将 longURL 返回给用户。
## 步骤 4 -总结
在本章中,我们讨论了 API 设计、数据模型、哈希函数、URL 缩短和 URL 重定向。
如果在面试结束时有额外的时间,这里有一些额外的谈话要点。
限速器:我们可能面临的一个潜在安全问题是,恶意用户会发送大量 URL 缩短请求。速率限制器帮助过滤出基于 IP 地址或其他过滤规则的请求。如果你想回忆一下速率限制,请参考“第 4 章:设计一个速率限制器”。
web 服务器扩展:由于 web 层是无状态的,所以通过添加或删除 Web 服务器来扩展 Web 层是很容易的。
数据库伸缩:数据库复制和分片是常见的技术。
分析:数据对商业成功越来越重要。将分析解决方案集成到 URL shortener 中有助于回答一些重要问题,比如有多少人点击了一个链接?他们什么时候点击链接?等等。
可用性、一致性和可靠性。这些概念是任何大型系统成功的核心。我们在第 1 章中详细讨论了它们,请刷新您对这些主题的记忆。
祝贺你走到这一步!现在给自己一个鼓励。干得好!
参考资料
【1】一个宁静的教程:[](https://www.restapitutorial.com/index.html)
【2】布鲁姆滤镜:[](https://en.wikipedia.org/wiki/Bloom_filter)
\ No newline at end of file
此差异已折叠。
# 十、设计通知系统
近年来,通知系统已经成为许多应用程序中非常流行的功能。通知提醒用户重要信息,如突发新闻、产品更新、事件、产品等。它已经成为我们日常生活中不可或缺的一部分。在这一章中,你被要求设计一个通知系统。
通知不仅仅是移动推送通知。三种通知格式是:移动推送通知、SMS 消息和电子邮件。图 10-1 显示了这些通知的一个例子。
![A screenshot of a cell phone Description automatically generated](img/00122.jpeg)
## 第一步——了解问题并确定设计范围
构建一个每天发送数百万条通知的可扩展系统并不是一件容易的事情。它需要对通知生态系统有深刻的理解。面试问题特意设计成开放式的,模棱两可的,你有责任提问明确要求。
候选人 :系统支持什么类型的通知?
面试官 :推送通知、短信、邮件。
候选: 是实时系统吗?
面试官: 姑且说是软实时系统吧。我们希望用户尽快收到通知。但是,如果系统工作负载较高,稍微延迟是可以接受的。
候选: 支持哪些设备?
面试官: iOS 设备,android 设备,以及笔记本电脑/台式机。
候选: 什么触发通知?
面试官: 客户端应用程序可以触发通知。它们也可以在服务器端进行调度。
候选人: 用户可以选择退出吗?
面试官: 是的,选择退出的用户将不再收到通知。
候选人: 每天发出多少通知?
面试官:1000 万条移动推送通知,100 万条短信,500 万封邮件。
## 第二步——提出高水平的设计并获得认同
本节展示了支持各种通知类型的高级设计:iOS 推送通知、Android 推送通知、短信和电子邮件。其结构如下:
不同类型的通知
联系信息采集流程
通知收发流程
### 不同类型的通知
我们先来看看每种通知类型在高层次上是如何工作的。
#### iOS 推送通知
![A picture containing object, mirror Description automatically generated](img/00123.jpeg)
我们主要需要三个组件来发送 iOS 推送通知:
提供者。提供商构建通知请求并将其发送给苹果推送通知服务(APNS)。为了构造推送通知,提供商提供以下数据:
设备令牌:这是用于发送推送通知的唯一标识符。
有效负载:这是一个 JSON 字典,包含通知的有效负载。下面是一个例子:
![A picture containing bird Description automatically generated](img/00124.jpeg)
APNS:这是苹果提供的一项远程服务,用于向 iOS 设备传播推送通知。
iOS 设备:是终端客户端,接收推送通知。
#### 安卓推送通知
Android 采用了类似的通知流程。Firebase Cloud Messaging (FCM)通常用于向 android 设备发送推送通知,而不是使用 APN。
![A picture containing umbrella Description automatically generated](img/00125.jpeg)
#### 短信
对于短信,通常使用 Twilio [1]、Nexmo [2]等第三方短信服务。大部分是商业服务。
![A picture containing clock Description automatically generated](img/00126.jpeg)
#### 电子邮件
虽然公司可以建立自己的电子邮件服务器,但许多公司选择商业电子邮件服务。Sendgrid [3]和 Mailchimp [4]是最受欢迎的电子邮件服务,它们提供更好的投递率和数据分析。
![A picture containing table Description automatically generated](img/00127.jpeg)
图 10-6 显示了包含所有第三方服务后的设计。
![A screenshot of a cell phone Description automatically generated](img/00128.jpeg)
### 联系信息收集流程
为了发送通知,我们需要收集移动设备令牌、电话号码或电子邮件地址。如图 10-7 所示,当用户安装我们的应用程序或者第一次注册时,API 服务器收集用户的联系信息并存储在数据库中。
![A picture containing clock Description automatically generated](img/00129.jpeg)
图 10-8 显示了存储联系信息的简化数据库表。电子邮件地址和电话号码存储在 用户 表中,而设备令牌存储在 设备 表中。一个用户可以有多个设备,这表明推送通知可以被发送到所有的用户设备。
![A screenshot of a cell phone Description automatically generated](img/00130.jpeg)
### 通知发送/接收流程
我们将首先展示最初的设计;然后,提出一些优化。
高--水平设计
图 10-9 显示了设计,每个系统组件解释如下。
![A close up of a map Description automatically generated](img/00131.jpeg)
服务 1 到 N :服务可以是微服务、cron 作业,也可以是触发通知发送事件的分布式系统。例如,一个账单服务发送电子邮件提醒客户他们的到期付款,或者一个购物网站通过短信告诉客户他们的包裹将于明天送达。
通知系统 :通知系统是发送/接收通知的核心。从简单的开始,只使用一个通知服务器。它为服务 1 到 N 提供 API,并为第三方服务构建通知有效负载。
第三方服务: 第三方服务负责向用户发送通知。在与第三方服务集成的同时,我们需要额外关注可扩展性。良好的可扩展性意味着一个灵活的系统,可以很容易地插入或拔出第三方服务。另一个重要的考虑是,第三方服务可能在新的市场或未来不可用。例如,FCM 在中国是不可用的。因此,替代的第三方服务,如 Jpush,PushY 等,在那里使用。
iOS、Android、短信、电子邮件 :用户在其设备上接收通知。
在本设计中发现了三个问题:
单点故障(SPOF):单一通知服务器是指 SPOF。
难以扩展:通知系统在一台服务器上处理与推送通知相关的一切。独立扩展数据库、缓存和不同的通知处理组件是一项挑战。
性能瓶颈:处理和发送通知可能是资源密集型的。例如,构建 HTML 页面和等待第三方服务的响应可能需要时间。在一个系统中处理所有事情会导致系统过载,尤其是在高峰时段。
高级设计(改进)
在列举了初始设计中的挑战后,我们对设计进行了如下改进:
将数据库和缓存移出通知服务器。
添加更多通知服务器并设置自动水平缩放。
引入消息队列来分离系统组件。
图 10-10 显示了改进的高层设计。
![A close up of a map Description automatically generated](img/00132.jpeg)
浏览上图的最佳方式是从左到右:
服务 1 到 N :它们代表通过通知服务器提供的 API 发送通知的不同服务。
通知服务器 :提供以下功能:
为发送通知的服务提供 API。这些 API 只能在内部访问或由经过验证的客户端访问,以防止垃圾邮件。
进行基本验证,以验证电子邮件、电话号码等。
查询数据库或缓存以获取呈现通知所需的数据。
将通知数据放入消息队列进行并行处理。
下面是发送电子邮件的 API 示例:
职务
请求体
![A screenshot of text Description automatically generated](img/00133.jpeg)
缓存 :缓存用户信息、设备信息、通知模板。
DB :存储用户、通知、设置等数据。
消息队列 :它们移除组件之间的依赖关系。当要发送大量通知时,消息队列充当缓冲区。每种通知类型都分配有不同的消息队列,因此一个第三方服务的中断不会影响其他通知类型。
Workers:Workers 是从消息队列中拉出通知事件并发送给相应的第三方服务的服务器列表。
第三方服务 :已在初步设计中说明。
iOS、Android、短信、邮箱 :在初步设计中已经说明。
接下来,让我们看看每个组件如何协同工作来发送通知:
1。服务调用通知服务器提供的 API 来发送通知。
2。通知服务器从缓存或数据库中获取元数据,如用户信息、设备令牌和通知设置。
3。通知事件被发送到相应的队列进行处理。例如,iOS 推送通知事件被发送到 iOS PN 队列。
4。工作人员从消息队列中提取通知事件。
5。工作人员向第三方服务发送通知。
6。第三方服务向用户设备发送通知。
## 步骤 3 -设计深度潜水
在概要设计中,我们讨论了不同类型的通知、联系信息收集流程和通知发送/接收流程。我们将深入探讨以下内容:
可靠性。
附加组件和考虑事项:通知模板、通知设置、速率限制、重试机制、推送通知中的安全性、监控排队通知和事件跟踪。
更新设计。
### 可靠性
在分布式环境中设计通知系统时,我们必须回答几个重要的可靠性问题。
如何防止数据丢失?
通知系统中最重要的要求之一是不能丢失数据。通知通常可以延迟或重新排序,但永远不会丢失。为了满足这一要求,通知系统将通知数据保存在数据库中,并实现重试机制。如图 10-11 所示,包含通知日志数据库是为了数据持久化。
![A screenshot of a cell phone Description automatically generated](img/00134.jpeg)
收件人会收到一次通知吗?
简短的回答是否定的。尽管大多数情况下通知只发送一次,但分布式的本质可能会导致重复的通知。为了减少重复的发生,我们引入了重复数据删除机制,并仔细处理每个故障情况。下面是一个简单的重复数据删除逻辑:
当一个通知事件第一次到达时,我们通过检查事件 ID 来检查它以前是否被看到过。如果是之前看到的,就丢弃。否则,我们将发出通知。感兴趣的读者可以参考参考资料[5],探究为什么我们不能一次交货。
### 附加组件和注意事项
我们已经讨论了如何收集用户联系信息、发送和接收通知。通知系统远不止于此。这里我们讨论其他组件,包括模板重用、通知设置、事件跟踪、系统监控、速率限制等。
#### 通知模板
大型通知系统每天会发出数百万条通知,其中许多通知都遵循相似的格式。引入通知模板是为了避免从头开始构建每个通知。通知模板是一种预先格式化的通知,通过自定义参数、样式、跟踪链接等来创建您的独特通知。下面是推送通知的一个示例模板。
正文:
你梦见了它。我们敢于挑战。[项目名称]已恢复—仅到[日期]为止。
CTA:
现在订购。或者,保存我的【物品名称】
使用通知模板的好处包括保持格式一致、减少误差和节省时间。
#### 通知设置
用户通常每天会收到太多的通知,他们很容易感到不知所措。因此,许多网站和应用程序允许用户对通知设置进行精细控制。该信息存储在通知设置表中,具有以下字段:
用户标识 bigInt
channel varchar #推送通知、电子邮件或短信
opt_in boolean # opt-in 接收通知
在向用户发送任何通知之前,我们首先检查用户是否选择接收此类通知。
#### 速率限制
为了避免过多的通知让用户不知所措,我们可以限制用户可以接收的通知数量。这很重要,因为如果我们发送得太频繁,接收者可能会完全关闭通知。
#### 重试机制
当第三方服务未能发送通知时,该通知将被添加到消息队列中进行重试。如果问题仍然存在,将向开发人员发出警告。
#### 推送通知中的安全性
对于 iOS 或 Android 应用,appKey 和 appSecret 用于保护推送通知 API[6]。只有经过认证或验证的客户端才允许使用我们的 API 发送推送通知。感兴趣的用户可以参考参考资料[6]。
#### 监控排队通知
要监控的一个关键指标是排队通知的总数。如果数量很大,则工作线程处理通知事件的速度不够快。为了避免通知传递的延迟,需要更多的工人。图 10-12 显示了一个待处理的排队消息的例子。
![](img/00135.jpeg)
图 10-12
#### 事件跟踪
打开率、点击率和参与度等通知指标对于了解客户行为非常重要。分析服务实现事件跟踪。通知系统和分析服务之间的集成通常是必需的。图 10-13 显示了出于分析目的可能被跟踪的事件的例子。
![A close up of a necklace Description automatically generated](img/00136.jpeg)
### 更新设计
图 10-14 显示了更新后的通知系统设计。
![A close up of a map Description automatically generated](img/00137.jpeg)
与之前的设计相比,本次设计增加了许多新部件。
通知服务器配备了两个更关键的功能:身份验证和速率限制。
我们还增加了重试机制来处理通知失败。如果系统未能发送通知,它们将被放回消息队列,工作人员将重试预定义的次数。
此外,通知模板提供了一致且高效的通知创建流程。
最后,增加了监控和跟踪系统,用于系统健康检查和未来改进。
## 步骤 4 -总结
通知是必不可少的,因为它们让我们了解重要的信息。它可能是网飞上关于你最喜欢的电影的推送通知,一封关于新产品折扣的电子邮件,或者一条关于你的网上购物支付确认的消息。
在本章中,我们描述了支持多种通知格式的可扩展通知系统的设计:推送通知、SMS 消息和电子邮件。我们采用消息队列来分离系统组件。
除了高级设计,我们还深入研究了更多组件和优化。
可靠性:我们提出了一个健壮的重试机制来最小化故障率。
安全性:AppKey/appSecret 对用于确保只有经过验证的客户端才能发送通知。
跟踪和监控:这些在通知流的任何阶段都可以实现,以捕获重要的统计数据。
尊重用户设置:用户可以选择不接收通知。我们的系统在发送通知前会先检查用户设置。
速率限制:用户会喜欢对他们收到的通知数量设置频率上限。
祝贺你走到这一步!现在给自己一个鼓励。干得好!
参考资料
【1】Twilio 短信:[T3】https://www.twilio.com/smsT5】](https://www.twilio.com/sms)
【2】NEX mo 短信:[T3】https://www.nexmo.com/products/smsT5】](https://www.nexmo.com/products/sms)
【3】send grid:[https://sendgrid.com/](https://sendgrid.com/)
【4】Mailchimp:[T3】https://mailchimp.com/T5】](https://mailchimp.com/)
【5】你不能恰好有一次投递:[https://brave newgeek . com/You-can-Have-exact-Once-Delivery/](https://bravenewgeek.com/you-cannot-have-exactly-once-delivery/)
【6】安全推送通知:【https://cloud.ibm.com/docs/services/mobilepush?】[topic =移动推送通知安全推送通知T5】](https://cloud.ibm.com/docs/services/mobilepush?topic=mobile-pushnotification-security-in-push-notifications)
【7】RadditMQ:[T3】https://bit.ly/2sotIa6T5】](https://bit.ly/2sotIa6)
\ No newline at end of file
# 十一、设计新闻订阅系统
在这一章中,你被要求设计一个新闻订阅系统。什么是新闻订阅源?根据脸书的帮助页面,“新闻提要是在你的主页中间不断更新的故事列表。新闻源包括状态更新、照片、视频、链接、应用活动 、 ,以及你在脸书上关注的人、页面和群组的赞。这是一个常见的面试问题。常见的类似问题有:设计脸书新闻提要、Instagram 提要、Twitter 时间线等。
![A screenshot of a cell phone Description automatically generated](img/00138.jpeg)
## 第一步——了解问题并确定设计范围
第一组澄清性问题是当面试官让你设计一个新闻反馈系统时,你要明白她在想什么。至少,您应该弄清楚要支持哪些特性。下面是一个应聘者与面试官互动的例子:
考生 :这是手机 app 吗?还是一个 web app?还是两者都有?
面试官 :双方
候选人 :有哪些重要特征?
采访: 用户可以发表帖子,并在新闻订阅页面上看到她朋友的帖子。
候选人 : 新闻提要是按时间倒序排序还是按话题分数等任何特定顺序排序?例如,来自你亲密朋友的帖子得分更高。
面试官 : 为了简单起见,我们假设提要是按时间倒序排序的。
候选人 : 一个用户可以有多少好友?
面试官 : 5000
候选人 :车流量是多少?
面试官:1000 万 DAU
候选:feed 可以包含图片、视频,或者只是文字?
面试官 :可以包含媒体文件,包括图片和视频。
现在你已经收集了需求,我们集中精力设计系统。
## 第二步——提出高水平的设计并获得认同
设计分为两个流程:feed 发布和新闻 feed 构建。
Feed 发布:当用户发布帖子时,相应的数据被写入缓存和数据库。她朋友的新闻订阅源上有一个帖子。
新闻提要构建:为了简单起见,我们假设新闻提要是通过按时间倒序聚合朋友的帖子构建的。
### 新闻源 API
新闻提要 API 是客户端与服务器通信的主要方式。这些 API 是基于 HTTP 的,允许客户端执行操作,包括发布状态、检索新闻提要、添加好友等。我们讨论两个最重要的 API:提要发布 API 和新闻提要检索 API。
Feed 发布 API
要发布帖子,将向服务器发送 HTTP POST 请求。API 如下所示:
后/v1/me/进给
参数:
内容:内容是帖子的正文。
auth _ token:用于认证 API 请求。
新闻订阅源检索 API
检索新闻提要的 API 如下所示:
GET /v1/me/feed
参数:
auth _ token:用于认证 API 请求。
### 饲料出版
图 11-2 显示了提要发布流程的高层设计。
![A close up of a map Description automatically generated](img/00139.jpeg)
用户:用户可以在浏览器或移动应用程序上查看新闻源。一个用户通过 API 发布了一个内容为“你好”的帖子:
/v1/me/feed?内容=你好&认证令牌= {认证令牌}
负载均衡器:将流量分配给 web 服务器。
Web 服务器:Web 服务器将流量重定向到不同的内部服务。
Post 服务:在数据库和缓存中持久保存帖子。
Fanout 服务:向好友的新闻推送新内容。新闻订阅源数据存储在缓存中,以便快速检索。
通知服务:通知好友有新内容,发送推送通知。
### 新闻大楼
在本节中,我们将讨论新闻提要是如何在幕后构建的。图 11-3 显示了高层设计:
![A close up of a logo Description automatically generated](img/00140.jpeg)
用户:用户发送请求来检索她的新闻提要。请求看起来是这样的: / v1/me/feed。
负载平衡器:负载平衡器将流量重定向到 web 服务器。
Web 服务器:Web 服务器将请求路由到新闻订阅服务。
新闻订阅服务:新闻订阅服务从缓存中获取新闻订阅。
新闻提要缓存:存储呈现新闻提要所需的新闻提要 id。
## 第三步——设计深潜
概要设计简要地涵盖了两个流程:提要发布和新闻提要构建。在这里,我们更深入地讨论这些话题。
### 供稿出版深潜
图 11-4 概述了 feed 发布的详细设计。我们已经讨论了高层设计中的大部分组件,我们将集中讨论两个组件:web 服务器和扇出服务。
![A close up of a map Description automatically generated](img/00141.jpeg)
#### 网络服务器
除了与客户端通信之外,web 服务器还执行身份验证和速率限制。只有使用有效 auth_token 登录的用户才可以发帖。该系统限制用户在一定时间内可以发布的帖子数量,这对防止垃圾邮件和滥用内容至关重要。
#### 扇出服务
扇出是向所有朋友发送帖子的过程。两种类型的扇出模型是:写时扇出(也称为推模型)和读时扇出(也称为拉模型)。两种模式各有利弊。我们解释他们的工作流程,并探索支持我们系统的最佳方法。
写时扇出。 用这种方法, 新闻提要是在编写时间内预先计算好的。新帖子发布后会立即发送到朋友的缓存中。
优点:
新闻提要实时生成,可以立即推送给朋友。
获取新闻提要的速度很快,因为新闻提要是在编写时预先计算的。
缺点:
如果一个用户有很多朋友,那么获取他们的好友列表并为他们生成新闻提要会非常缓慢和耗时。叫做热键问题。
对于不活跃的用户或者很少登录的用户来说,预先计算的新闻提要浪费了计算资源。
扇出上读 。新闻提要是在读取时生成的。这是一种随需应变的模式。当用户加载她的主页时,最近的帖子被拉出来。
优点:
对于不活跃的用户或者那些很少登录的用户来说,read 上的 fanout 工作得更好,因为它不会在他们身上浪费计算资源。
数据不会推送给朋友,所以不存在热键问题。
缺点:
获取新闻提要很慢,因为新闻提要不是预先计算的。
我们采用了一种混合方法,以获得两种方法的优点并避免其中的缺陷。因为快速获取新闻提要至关重要,所以我们对大多数用户使用推送模型。对于有很多朋友/关注者的名人或用户,我们让关注者按需拉新闻内容,以避免系统过载。一致哈希是一种缓解热键问题的有用技术,因为它有助于更均匀地分布请求/数据。
让我们仔细看看扇出服务,如图 11-5 所示。
![A close up of a map Description automatically generated](img/00142.jpeg)
扇出服务的工作方式如下:
1。从图形数据库中获取朋友 id。图形数据库适合于管理朋友关系和朋友推荐。有兴趣的读者希望了解更多关于这个概念的信息,可以参考参考资料[2]。
2。从用户缓存中获取朋友信息。然后,系统会根据用户设置过滤掉朋友。例如,如果你将某人设为静音,即使你们仍然是朋友,她的帖子也不会显示在你的新闻订阅源上。帖子可能不会显示的另一个原因是,用户可以有选择地与特定的朋友分享信息,或者对其他人隐藏信息。
3。将好友列表和新帖子 ID 发送到消息队列。
4。扇出工作器从消息队列获取数据,并将新闻提要数据存储在新闻提要缓存中。你可以把新闻提要缓存想象成一个 < post_iduser_id > 的映射表。每当一个新的文章发表,它将被附加到新闻提要表中,如图 11-6 所示。如果我们将整个用户和 post 对象存储在缓存中,内存消耗会变得非常大。因此,只存储 id。为了保持较小的内存大小,我们设置了一个可配置的限制。用户在新闻订阅中滚动浏览数千条帖子的可能性很小。大部分用户只对最新的内容感兴趣,所以缓存缺失率很低。
5。在新闻提要缓存中存储 <帖子 id用户 id > 。图 11-6 显示了新闻提要在缓存中的样子。
![A screenshot of a cell phone Description automatically generated](img/00143.jpeg)
### 新闻提要检索深度剖析
图 11-7 展示了新闻提要检索的详细设计。
![A close up of a map Description automatically generated](img/00144.jpeg)
如图 11-7 所示,媒体内容(图片、视频等。)存储在 CDN 中,以便快速检索。让我们看看客户机如何检索新闻提要。
1。用户发送请求来检索她的新闻提要。请求看起来是这样的: /v1/me/feed
2。负载平衡器将请求重新分配给 web 服务器。
3。Web 服务器调用新闻提要服务来获取新闻提要。
4。新闻提要服务从新闻提要缓存中获取一个帖子 id 列表。
5。用户的新闻提要不仅仅是一个提要 id 列表。它包含用户名,个人资料图片,帖子内容,帖子图片等。因此,新闻提要服务从缓存(用户缓存和帖子缓存)中获取完整的用户和帖子对象,以构建完整的新闻提要。
6。完整的新闻提要以 JSON 格式返回给客户端进行呈现。
### 高速缓存架构
对于新闻订阅系统来说,缓存非常重要。我们将缓存层分为 5 层,如图 11-8 所示。
![A picture containing screenshot Description automatically generated](img/00145.jpeg)
新闻提要:存储新闻提要的 id。
内容:存储每条帖子的数据。热门内容存储在热缓存中。
社交图:存储用户关系数据。
动作:它存储了用户是否喜欢某个帖子、回复某个帖子或对某个帖子采取其他动作的信息。
计数器:存储点赞、回复、关注者、关注等计数器。
## 步骤 4 -总结
在这一章中,我们设计了一个新闻订阅系统。我们的设计包含两个流程:提要发布和新闻提要检索。
和任何系统设计面试问题一样,设计一个系统没有完美的方法。每个公司都有其独特的限制,你必须设计一个系统来适应这些限制。理解设计和技术选择的权衡非常重要。如果还有几分钟,可以谈谈可伸缩性问题。为了避免重复讨论,下面只列出了高层次的话题。
缩放数据库:
垂直缩放与水平缩放
T2】SQL vs NoSQL
主从复制
读取副本
一致性模型
T2】数据库分片
其他谈话要点:
保持 web 层无状态
尽可能多地缓存数据
支持多个数据中心
丢失消息队列的几个组件
监控关键指标。例如,用户刷新新闻提要时的高峰时间和延迟时间的 QPS 值得关注。
祝贺你走到这一步!现在给自己一个鼓励。干得好!
参考资料
[1]新闻订阅的工作原理:
[https://www.facebook.com/help/327131014036297/](https://www.facebook.com/help/327131014036297/)
【2】朋友的朋友推荐 Neo4j 和 SQL Sever:
[http://geekswithblogs . net/brendon page/archive/2015/10/26/friend-of-friend-of-friend-recommendations-with-neo4j . aspxT3】](http://geekswithblogs.net/brendonpage/archive/2015/10/26/friend-of-friend-recommendations-with-neo4j.aspx)
\ No newline at end of file
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
# 十七、后记
恭喜你!您已到达本面试指南的末尾。你已经积累了设计系统的技能和知识。不是每个人都有学习你所学的东西的纪律。花点时间拍拍自己的背。你的努力会有回报的。
找到一份理想的工作是一个漫长的旅程,需要大量的时间和努力。熟能生巧。祝你好运!
感谢您购买和阅读这本书。没有你这样的读者,我们的工作就不会存在。我们希望你喜欢这本书!
如果你不介意,请在亚马逊上阅读这本书:[【http://bit.ly/sysreview8】](http://bit.ly/sysreview8%20)它将帮助我吸引更多像你这样的优秀读者。
加入邮件列表
我们即将完成 10 多个真实世界的系统设计面试问题。如果你想在新章节出现时得到通知,请订阅我们的电子邮件列表:[【http://bit.ly/systemmail】](http://bit.ly/systemmail)
加入社区
我创建了一个仅限成员的不和小组。它旨在针对以下主题进行社区讨论:
系统设计基础。
展示设计图并获得反馈。
找模拟面试的哥们。
与社区成员一般聊天。
立即加入我们,点击下面的链接或扫描条形码,向社区介绍自己。
[http://bit.ly/systemdiscord](http://bit.ly/systemdiscord)
![Qr code Description automatically generated](img/00001.jpeg)
如果您对本书有任何意见或疑问,欢迎发送电子邮件至 systemdesigninsider@gmail.com[](mailto:systemdesigninsider@gmail.com)。此外,如果您发现任何错误,请让我们知道,以便我们在下一版中进行更正。谢谢大家!
\ No newline at end of file
# 系统设计面试的行家指南
> 原文:<https://libgen.rs/book/index.php?md5=86983F50E8781CADD98579199BEE2665>
>
> 阶段:机翻(1)
\ No newline at end of file
+ [系统设计面试的行家指南](README.md)
+ [零、序言](00.md)
+ [一、从零扩展到数百万用户](01.md)
+ [二、信封背面估计](02.md)
+ [四、设计速率限制器](03-1.md)
+ [三、系统设计面试的框架](03.md)
+ [五、设计一致哈希](04.md)
+ [六、设计键值存储](05.md)
+ [七、设计分布式系统中的唯一 ID 生成器](06.md)
+ [八、设计 URL 缩短器](07.md)
+ [九、设计网络爬虫](08.md)
+ [十、设计通知系统](09.md)
+ [十一、设计新闻订阅系统](10.md)
+ [十二、设计聊天系统](11.md)
+ [十三、设计搜索自动补全系统](12.md)
+ [十四、设计 YouTube](13.md)
+ [十五、设计谷歌云盘](14.md)
+ [十六、继续学习](15.md)
+ [十七、后记](16.md)
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册