- 原文地址:github.com/donnemartin…
- 译文出自:掘金翻译计划
- 译者:XatMassacrE、L9m、Airmacho、xiaoyusilen、jifaxu
- 请持续关注 中文维护连接 获取最新内容。
有兴趣参与翻译? 如下是正在进行中的翻译:javascript
学习如何设计大型系统。php
为系统设计的面试作准备。html
学习如何设计可扩展的系统将会有助于你成为一个更好的工程师。前端
系统设计是一个很宽泛的话题。在互联网上,关于系统设计原则的资源也是多如牛毛。java
这个仓库就是这些资源的组织收集,它能够帮助你学习如何构建可扩展的系统。python
这是一个不断更新的开源项目的初期的版本。mysql
欢迎贡献!react
在不少科技公司中,除了代码面试,系统设计也是技术面试过程中的一个必要环节。android
实践常见的系统设计面试题而且把你的答案和例子的解答进行对照:讨论,代码和图表。ios
面试准备的其余主题:
这里提供的抽认卡堆使用间隔重复的方法,帮助你记忆关键的系统设计概念。
随时随地均可使用。
你正在寻找资源以准备编程面试吗?
请查看咱们的姐妹仓库互动式编程挑战,其中包含了一个额外的抽认卡堆:
从社区中学习。
欢迎提交 PR 提供帮助:
一些还须要完善的内容放在了正在完善中。
请查看贡献指南。
各类系统设计主题的摘要,包括优势和缺点。每个主题都面临着取舍和权衡。
每一个章节都包含着更的资源的连接。
基于你面试的时间线(短、中、长)去复习那些推荐的主题。
问:对于面试来讲,我须要知道这里的全部知识点吗?
答:不,若是只是为了准备面试的话,你并不须要知道全部的知识点。
在一场面试中你会被问到什么取决于下面这些因素:
那些有经验的候选人一般会被指望了解更多的系统设计的知识。架构师或者团队负责人则会被指望了解更多除了我的贡献以外的知识。顶级的科技公司一般也会有一次或者更多的系统设计面试。
面试会很宽泛的展开并在几个领域深刻。这回帮助你了解一些关于系统设计的不一样的主题。基于你的时间线,经验,面试的职位和面试的公司对下面的指导作出适当的调整。
短时间 | 中期 | 长期 | |
---|---|---|---|
阅读 系统设计主题 以得到一个关于系统如何工做的宽泛的认识 | :+1: | :+1: | :+1: |
阅读一些你要面试的公司工程博客的文章 | :+1: | :+1: | :+1: |
阅读 真实架构 | :+1: | :+1: | :+1: |
复习 如何处理一个系统设计面试题 | :+1: | :+1: | :+1: |
完成 系统设计的面试题和解答 | 一些 | 不少 | 大部分 |
完成 面向对象设计的面试题和解答 | 一些 | 不少 | 大部分 |
复习 其它的系统设计面试题 | 一些 | 不少 | 大部分 |
系统设计面试是一个开放式的对话。他们指望你去主导这个对话。
你能够使用下面的步骤来指引讨论。为了巩固这个过程,请使用下面的步骤完成系统设计的面试题和解答这个章节。
把全部须要的东西汇集在一块儿,审视问题。不停的提问,以致于咱们能够明确使用场景和约束。讨论假设。
使用全部重要的组件来描绘出一个高级的设计。
对每个核心组件进行详细深刻的分析。举例来讲,若是你被问到设计一个 url 缩写服务,开始讨论:
确认和处理瓶颈以及一些限制。举例来讲就是你须要下面的这些来完成拓展性的议题吗?
论述可能的解决办法和代价。每件事情须要取舍。能够使用可拓展系统的设计原则来处理瓶颈。
你或许会被要求经过手算进行一些估算。涉及到的附录涉及到的是下面的这些资源:
查看下面的连接以得到咱们指望的更好的想法:
普通的系统设计面试题和相关事例的论述,代码和图表。
与内容有关的解答在
solutions/
文件夹中。
问题 | |
---|---|
设计 Pastebin.com (或者 Bit.ly) | 解答 |
设计 Twitter 时间线和搜索 (或者 Facebook feed 和搜索) | 解答 |
设计一个网页爬虫 | 解答 |
设计 Mint.com | 解答 |
为一个社交网络设计数据结构 | 解答 |
为搜索引擎设计一个 key-value 储存 | 解答 |
经过分类特性设计 Amazon 的销售排名 | 解答 |
在 AWS 上设计一个百万用户级别的系统 | 解答 |
添加一个系统设计问题 | 贡献 |
常见面向对象设计面试问题及实例讨论,代码和图表演示。
与内容相关的解决方案在
solutions/
文件夹中。注:此节还在完善中
问题 | |
---|---|
设计 hash map | 解决方案 |
设计 LRU 缓存 | 解决方案 |
设计一个呼叫中心 | 解决方案 |
设计一副牌 | 解决方案 |
设计一个停车场 | 解决方案 |
设计一个聊天服务 | 解决方案 |
设计一个环形数组 | 待解决 |
添加一个面向对象设计问题 | 待解决 |
不熟悉系统设计?
首先,你须要对通常性原则有一个基本的认识,知道它们是什么,怎样使用以及利弊。
接下来,咱们将看看高阶的权衡和取舍:
记住每一个方面都面临取舍和权衡。
而后,咱们将深刻更具体的主题,如 DNS、CDN 和负载均衡器。
若是服务性能的增加与资源的增长是成比例的,服务就是可扩展的。一般,提升性能意味着服务于更多的工做单元,另外一方面,当数据集增加时,一样也能够处理更大的工做单位。1
另外一个角度来看待性能与可扩展性:
延迟是执行操做或运算结果所花费的时间。
吞吐量是单位时间内(执行)此类操做或运算的数量。
一般,你应该以可接受级延迟下最大化吞吐量为目标。
在一个分布式计算系统中,只能同时知足下列的两点:
网络并不可靠,因此你应要支持分区容错性,并须要在软件可用性和一致性间作出取舍。
等待分区节点的响应可能会致使延时错误。若是你的业务需求须要原子读写,CP 是一个不错的选择。
响应节点上可用数据的最近版本可能并非最新的。当分区解析完后,写入(操做)可能须要一些时间来传播。
若是业务需求容许最终一致性,或当有外部故障时要求系统继续运行,AP 是一个不错的选择。
有同一份数据的多份副本,咱们面临着怎样同步它们的选择,以便让客户端有一致的显示数据。回想 CAP 理论中的一致性定义 ─ 每次访问都能得到最新数据但可能会收到错误响应
在写入以后,访问可能看到,也可能看不到(写入数据)。尽力优化之让其能访问最新数据。
这种方式能够 memcached 等系统中看到。弱一致性在 VoIP,视频聊天和实时多人游戏等真实用例中表现不错。打个比方,若是你在通话中丢失信号几秒钟时间,当从新链接时你是听不到这几秒钟所说的话的。
在写入后,访问最终能看到写入数据(一般在数毫秒内)。数据被异步复制。
DNS 和 email 等系统使用的是此种方式。最终一致性在高可用性系统中效果不错。
在写入后,访问当即可见。数据被同步复制。
文件系统和关系型数据库(RDBMS)中使用的是此种方式。强一致性在须要记录的系统中运做良好。
有两种支持高可用性的模式: 故障切换(fail-over)和复制(replication)。
关于工做到备用的故障切换流程是,工做服务器发送周期信号给待机中的备用服务器。若是周期信号中断,备用服务器切换成工做服务器的 IP 地址并恢复服务。
宕机时间取决于备用服务器处于“热”待机状态仍是须要从“冷”待机状态进行启动。只有工做服务器处理流量。
工做到备用的故障切换也被称为主从切换。
在双工做切换中,双方都在管控流量,在它们之间分散负载。
若是是外网服务器,DNS 将须要对两方都了解。若是是内网服务器,应用程序逻辑将须要对两方都了解。
双工做切换也能够称为主主切换。
这个主题进一步探讨了数据库部分:
域名系统是把 www.example.com 等域名转换成 IP 地址。
域名系统是分层次的,一些 DNS 服务器位于顶层。当查询(域名) IP 时,路由或 ISP 提供链接 DNS 服务器的信息。较底层的 DNS 服务器缓存映射,它可能会由于 DNS 传播延时而失效。DNS 结果能够缓存在浏览器或操做系统中一段时间,时间长短取决于存活时间 TTL。
CNAME
记录( example.com 指向 www.example.com )或映射到一个 A
记录。CloudFlare 和 Route 53 等平台提供管理 DNS 的功能。某些 DNS 服务经过集中方式来路由流量:
内容分发网络(CDN)是一个全球性的代理服务器分布式网络,它从靠近用户的位置提供内容。一般,HTML/CSS/JS,图片和视频等静态内容由 CDN 提供,虽然亚马逊 CloudFront 等也支持动态内容。CDN 的 DNS 解析会告知客户端链接哪台服务器。
将内容存储在 CDN 上能够从两个方面来提供性能:
当你服务器上内容发生变更时,推送 CDN 接受新内容。直接推送给 CDN 并重写 URL 地址以指向你的内容的 CDN 地址。你能够配置内容到期时间及什么时候更新。内容只有在更改或新增是才推送,流量最小化,但储存最大化。
CDN 拉取是当第一个用户请求该资源时,从服务器上拉取资源。你将内容留在本身的服务器上并重写 URL 指向 CDN 地址。直到内容被缓存在 CDN 上为止,这样请求只会更慢,
存活时间(TTL)决定缓存多久时间。CDN 拉取方式最小化 CDN 上的储存空间,但若是过时文件并在实际更改以前被拉取,则会致使冗余的流量。
高流量站点使用 CDN 拉取效果不错,由于只有最近请求的内容保存在 CDN 中,流量才能更平衡地分散。
负载均衡器将传入的请求分发到应用服务器和数据库等计算资源。不管哪一种状况,负载均衡器将从计算资源来的响应返回给恰当的客户端。负载均衡器的效用在于:
负载均衡器能够经过硬件(昂贵)或 HAProxy 等软件来实现。
增长的好处包括:
一般会设置采用工做─备用 或 双工做 模式的多个负载均衡器,以避免发生故障。
负载均衡器能基于多种方式来路由流量:
四层负载均衡根据监看传输层的信息来决定如何分发请求。一般,这会涉及来源,目标 IP 地址和请求头中的端口,但不包括数据包(报文)内容。四层负载均衡执行网络地址转换(NAT)来向上游服务器转发网络数据包。
七层负载均衡器根据监控应用层来决定怎样分发请求。这会涉及请求头的内容,消息和 cookie。七层负载均衡器终结网络流量,读取消息,作出负载均衡断定,而后传送给特定服务器。好比,一个七层负载均衡器能直接将视频流量链接到托管视频的服务器,同时将更敏感的用户帐单流量引导到安全性更强的服务器。
以损失灵活性为代价,四层负载均衡比七层负载均衡花费更少时间和计算资源,虽然这对现代商用硬件的性能影响甚微。
负载均衡器还能帮助水平扩展,提升性能和可用性。使用商业硬件的性价比更高,而且比在单台硬件上垂直扩展更贵的硬件具备更高的可用性。相比招聘特定企业系统人才,招聘商业硬件方面的人才更加容易。
反向代理是一种能够集中地调用内部服务,并提供统一接口给公共客户的 web 服务器。来自客户端的请求先被反向代理服务器转发到可响应请求的服务器,而后代理再把服务器的响应结果返回给客户端。
带来的好处包括:
将 Web 服务层与应用层(也被称做平台层)分离,能够独立缩放和配置这两层。添加新的 API 只须要添加应用服务器,而没必要添加额外的 web 服务器。
单一职责原则提倡小型的,自治的服务共同合做。小团队经过提供小型的服务,能够更激进地计划增加。
应用层中的工做进程也有能够实现异步化。
与此讨论相关的话题是 微服务,能够被描述为一系列能够独立部署的小型的,模块化服务。每一个服务运行在一个独立的线程中,经过明肯定义的轻量级机制通信,共同实现业务目标。1
例如,Pinterest 可能有这些微服务: 用户资料、关注者、Feed 流、搜索、照片上传等。
像 Consul,Etcd 和 Zookeeper 这样的系统能够经过追踪注册名、地址、端口等信息来帮助服务互相发现对方。Health checks 能够帮助确认服务的完整性和是否常用一个 HTTP 路径。Consul 和 Etcd 都有一个内建的 key-value 存储 用来存储配置信息和其余的共享信息。
像 SQL 这样的关系型数据库是一系列以表的形式组织的数据项集合。
校对注:这里做者 SQL 可能指的是 MySQL
ACID 用来描述关系型数据库事务的特性。
关系型数据库扩展包括许多技术:主从复制、主主复制、联合、分片、非规范化和 SQL调优。
主库同时负责读取和写入操做,并复制写入到一个或多个从库中,从库只负责读操做。树状形式的从库再将写入复制到更多的从库中去。若是主库离线,系统能够以只读模式运行,直到某个从库被提高为主库或有新的主库出现。
两个主库都负责读操做和写操做,写入操做时互相协调。若是其中一个主库挂机,系统能够继续读取和写入。
联合(或按功能划分)将数据库按对应功能分割。例如,你能够有三个数据库:论坛、用户和产品,而不只是一个单体数据库,从而减小每一个数据库的读取和写入流量,减小复制延迟。较小的数据库意味着更多适合放入内存的数据,进而意味着更高的缓存命中概率。没有只能串行写入的中心化主库,你能够并行写入,提升负载能力。
分片将数据分配在不一样的数据库上,使得每一个数据库仅管理整个数据集的一个子集。以用户数据库为例,随着用户数量的增长,愈来愈多的分片会被添加到集群中。
相似联合的优势,分片能够减小读取和写入流量,减小复制并提升缓存命中率。也减小了索引,一般意味着查询更快,性能更好。若是一个分片出问题,其余的仍能运行,你能够使用某种形式的冗余来防止数据丢失。相似联合,没有只能串行写入的中心化主库,你能够并行写入,提升负载能力。
常见的作法是用户姓氏的首字母或者用户的地理位置来分隔用户表。
非规范化试图以写入性能为代价来换取读取性能。在多个表中冗余数据副本,以免高成本的联结操做。一些关系型数据库,好比 PostgreSQl 和 Oracle 支持物化视图,能够处理冗余信息存储和保证冗余副本一致。
当数据使用诸如联合和分片等技术被分割,进一步提升了处理跨数据中心的联结操做复杂度。非规范化能够规避这种复杂的联结操做。
在多数系统中,读取操做的频率远高于写入操做,比例可达到 100:1,甚至 1000:1。须要复杂的数据库联结的读取操做成本很是高,在磁盘操做上消耗了大量时间。
SQL 调优是一个范围很广的话题,有不少相关的书能够做为参考。
利用基准测试和性能分析来模拟和发现系统瓶颈很重要。
基准测试和性能分析可能会指引你到如下优化方案。
CHAR
类型存储固定长度的字段,不要用 VARCHAR
。
CHAR
在快速、随机访问时效率很高。若是使用 VARCHAR
,若是你想读取下一个字符串,不得不先读取到当前字符串的末尾。TEXT
类型存储大块的文本,例如博客正文。TEXT
还容许布尔搜索。使用 TEXT
字段须要在磁盘上存储一个用于定位文本块的指针。INT
类型存储高达 2^32 或 40 亿的较大数字。DECIMAL
类型存储货币能够避免浮点数表示错误。BLOBS
存储对象,存储存放对象的位置。VARCHAR(255)
是以 8 位数字存储的最大字符数,在某些关系型数据库中,最大限度地利用字节。NOT NULL
约束来提升搜索性能。SELECT
、GROUP BY
、ORDER BY
、JOIN
)的列若是用了索引会更快。NoSQL 是键-值数据库、文档型数据库、列型数据库或图数据库的统称。数据库是非规范化的,表联结大多在应用程序代码中完成。大多数 NoSQL 没法实现真正符合 ACID 的事务,支持最终一致。
BASE 一般被用于描述 NoSQL 数据库的特性。相比 CAP 理论,BASE 强调可用性超过一致性。
除了在 SQL 仍是 NoSQL 之间作选择,了解哪一种类型的 NoSQL 数据库最适合你的用例也是很是有帮助的。咱们将在下一节中快速了解下 键-值存储、文档型存储、列型存储和图存储数据库。
抽象模型:哈希表
键-值存储一般能够实现 O(1) 时间读写,用内存或 SSD 存储数据。数据存储能够按字典顺序维护键,从而实现键的高效检索。键-值存储能够用于存储元数据。
键-值存储性能很高,一般用于存储简单数据模型或频繁修改的数据,如存放在内存中的缓存。键-值存储提供的操做有限,若是须要更多操做,复杂度将转嫁到应用程序层面。
键-值存储是如文档存储,在某些状况下,甚至是图存储等更复杂的存储系统的基础。
抽象模型:将文档做为值的键-值存储
文档类型存储以文档(XML、JSON、二进制文件等)为中心,文档存储了指定对象的所有信息。文档存储根据文档自身的内部结构提供 API 或查询语句来实现查询。请注意,许多键-值存储数据库有用值存储元数据的特性,这也模糊了这两种存储类型的界限。
基于底层实现,文档能够根据集合、标签、元数据或者文件夹组织。尽管不一样文档能够被组织在一块儿或者分红一组,但相互之间可能具备彻底不一样的字段。
MongoDB 和 CouchDB 等一些文档类型存储还提供了相似 SQL 语言的查询语句来实现复杂查询。DynamoDB 同时支持键-值存储和文档类型存储。
文档类型存储具有高度的灵活性,经常使用于处理偶尔变化的数据。
抽象模型:嵌套的
ColumnFamily<RowKey, Columns<ColKey, Value, Timestamp>>
映射
类型存储的基本数据单元是列(名/值对)。列能够在列族(相似于 SQL 的数据表)中被分组。超级列族再分组普通列族。你能够使用行键独立访问每一列,具备相同行键值的列组成一行。每一个值都包含版本的时间戳用于解决版本冲突。
Google 发布了第一个列型存储数据库 Bigtable,它影响了 Hadoop 生态系统中活跃的开源数据库 HBase 和 Facebook 的 Cassandra。像 BigTable,HBase 和 Cassandra 这样的存储系统将键以字母顺序存储,能够高效地读取键列。
列型存储具有高可用性和高可扩展性。一般被用于大数据相关存储。
抽象模型: 图
在图数据库中,一个节点对应一条记录,一个弧对应两个节点之间的关系。图数据库被优化用于表示外键繁多的复杂关系或多对多关系。
图数据库为存储复杂关系的数据模型,如社交网络,提供了很高的性能。它们相对较新,还没有普遍应用,查找开发工具或者资源相对较难。许多图只能经过 REST API 访问。
选取 SQL 的缘由:
选取 NoSQL 的缘由:
适合 NoSQL 的示例数据:
缓存能够提升页面加载速度,并能够减小服务器和数据库的负载。在这个模型中,分发器先查看请求以前是否被响应过,若是有则将以前的结果直接返回,来省掉真正的处理。
数据库分片均匀分布的读取是最好的。可是热门数据会让读取分布不均匀,这样就会形成瓶颈,若是在数据库前加个缓存,就会抹平不均匀的负载和突发流量对数据库的影响。
缓存能够位于客户端(操做系统或者浏览器),服务端或者不一样的缓存层。
CDN 也被视为一种缓存。
反向代理和缓存(好比 Varnish)能够直接提供静态和动态内容。Web 服务器一样也能够缓存请求,返回相应结果而没必要链接应用服务器。
数据库的默认配置中一般包含缓存级别,针对通常用例进行了优化。调整配置,在不一样状况下使用不一样的模式能够进一步提升性能。
基于内存的缓存好比 Memcached 和 Redis 是应用程序和数据存储之间的一种键值存储。因为数据保存在 RAM 中,它比存储在磁盘上的典型数据库要快多了。RAM 比磁盘限制更多,因此例如 least recently used (LRU) 的缓存无效算法能够将「热门数据」放在 RAM 中,而对一些比较「冷门」的数据不作处理。
Redis 有下列附加功能:
有多个缓存级别,分为两大类:数据库查询和对象:
通常来讲,你应该尽可能避免基于文件的缓存,由于这使得复制和自动缩放很困难。
当你查询数据库的时候,将查询语句的哈希值与查询结果存储到缓存中。这种方法会遇到如下问题:
将您的数据视为对象,就像对待你的应用代码同样。让应用程序将数据从数据库中组合到类实例或数据结构中:
建议缓存的内容:
因为你只能在缓存中存储有限的数据,因此你须要选择一个适用于你用例的缓存更新策略。
应用从存储器读写。缓存不和存储器直接交互,应用执行如下操做:
def get_user(self, user_id):
user = cache.get("user.{0}", user_id)
if user is None:
user = db.query("SELECT * FROM users WHERE user_id = {0}", user_id)
if user is not None:
key = "user.{0}".format(user_id)
cache.set(key, json.dumps(user))
return user复制代码
Memcached 一般用这种方式使用。
添加到缓存中的数据读取速度很快。缓存模式也称为延迟加载。只缓存所请求的数据,这避免了没有被请求的数据占满了缓存空间。
应用使用缓存做为主要的数据存储,将数据读写到缓存中,而缓存负责从数据库中读写数据。
应用代码:
set_user(12345, {"foo":"bar"})复制代码
缓存代码:
def set_user(user_id, values):
user = db.query("UPDATE Users WHERE id = {0}", user_id, values)
cache.set(user_id, user)复制代码
因为存写操做因此直写模式总体是一种很慢的操做,可是读取刚写入的数据很快。相比读取数据,用户一般比较能接受更新数据时速度较慢。缓存中的数据不会过期。
在回写模式中,应用执行如下操做:
你能够将缓存配置成在到期以前自动刷新最近访问过的内容。
若是缓存能够准确预测未来可能请求哪些数据,那么刷新可能会致使延迟与读取时间的下降。
异步工做流有助于减小那些本来顺序执行的请求时间。它们能够经过提早进行一些耗时的工做来帮助减小请求时间,好比按期汇总数据。
消息队列接收,保留和传递消息。若是按顺序执行操做太慢的话,你能够使用有如下工做流的消息队列:
不去阻塞用户操做,做业在后台处理。在此期间,客户端可能会进行一些处理使得看上去像是任务已经完成了。例如,若是要发送一条推文,推文可能会立刻出如今你的时间线上,可是可能须要一些时间才能将你的推文推送到你的全部关注者那里去。
Redis 是一个使人满意的简单的消息代理,可是消息有可能会丢失。
RabbitMQ 很受欢迎可是要求你适应「AMQP」协议而且管理你本身的节点。
Amazon SQS 是被托管的,但可能具备高延迟,而且消息可能会被传送两次。
任务队列接收任务及其相关数据,运行它们,而后传递其结果。 它们能够支持调度,并可用于在后台运行计算密集型做业。
Celery 支持调度,主要是用 Python 开发的。
若是队列开始明显增加,那么队列大小可能会超过内存大小,致使高速缓存未命中,磁盘读取,甚至性能更慢。背压能够经过限制队列大小来帮助咱们,从而为队列中的做业保持高吞吐率和良好的响应时间。一旦队列填满,客户端将获得服务器忙活着 HTTP 503 状态码,以便稍后重试。客户端能够在稍后时间重试该请求,也许是指数退避。
HTTP 是一种在客户端和服务器之间编码和传输数据的方法。它是一个请求/响应协议:客户端和服务端针对相关内容和完成状态信息的请求和响应。HTTP 是独立的,容许请求和响应流经许多执行负载均衡,缓存,加密和压缩的中间路由器和服务器。
一个基本的 HTTP 请求由一个动词(方法)和一个资源(端点)组成。 如下是常见的 HTTP 动词:
动词 | 描述 | *幂等 | 安全性 | 可缓存 |
---|---|---|---|---|
GET | 读取资源 | Yes | Yes | Yes |
POST | 建立资源或触发处理数据的进程 | No | No | Yes,若是回应包含刷新信息 |
PUT | 建立或替换资源 | Yes | No | No |
PATCH | 部分更新资源 | No | No | Yes,若是回应包含刷新信息 |
DELETE | 删除资源 | Yes | No | No |
屡次执行不会产生不一样的结果。
HTTP 是依赖于较低级协议(如 TCP 和 UDP)的应用层协议。
TCP 是经过 IP 网络的面向链接的协议。 使用握手创建和断开链接。 发送的全部数据包保证以原始顺序到达目的地,用如下措施保证数据包不被损坏:
若是发送者没有收到正确的响应,它将从新发送数据包。若是屡次超时,链接就会断开。TCP 实行流量控制)和拥塞控制。这些确保措施会致使延迟,并且一般致使传输效率比 UDP 低。
为了确保高吞吐量,Web 服务器能够保持大量的 TCP 链接,从而致使高内存使用。在 Web 服务器线程间拥有大量开放链接可能开销巨大,消耗资源过多,也就是说,一个 memcached 服务器。链接池 能够帮助除了在适用的状况下切换到 UDP。
TCP 对于须要高可靠性但时间紧迫的应用程序颇有用。好比包括 Web 服务器,数据库信息,SMTP,FTP 和 SSH。
如下状况使用 TCP 代替 UDP:
UDP 是无链接的。数据报(相似于数据包)只在数据报级别有保证。数据报可能会无序的到达目的地,也有可能会遗失。UDP 不支持拥塞控制。虽然不如 TCP 那样有保证,但 UDP 一般效率更高。
UDP 能够经过广播将数据报发送至子网内的全部设备。这对 DHCP 颇有用,由于子网内的设备尚未分配 IP 地址,而 IP 对于 TCP 是必须的。
UDP 可靠性更低但适合用在网络电话、视频聊天,流媒体和实时多人游戏上。
如下状况使用 UDP 代替 TCP:
Source: Crack the system design interview
在 RPC 中,客户端会去调用另外一个地址空间(一般是一个远程服务器)里的方法。调用代码看起来就像是调用的是一个本地方法,客户端和服务器交互的具体过程被抽象。远程调用相对于本地调用通常较慢并且可靠性更差,所以区分二者是有帮助的。热门的 RPC 框架包括 Protobuf、Thrift 和 Avro。
RPC 是一个“请求-响应”协议:
RPC 调用示例:
GET /someoperation?data=anId
POST /anotheroperation
{
"data":"anId";
"anotherdata": "another value"
}复制代码
RPC 专一于暴露方法。RPC 一般用于处理内部通信的性能问题,这样你能够手动处理本地调用以更好的适应你的状况。
当如下状况时选择本地库(也就是 SDK):
遵循 REST 的 HTTP API 每每更适用于公共 API。
REST 是一种强制的客户端/服务端架构设计模型,客户端基于服务端管理的一系列资源操做。服务端提供修改或获取资源的接口。全部的通讯必须是无状态和可缓存的。
RESTful 接口有四条规则:
REST 请求的例子:
GET /someresources/anId
PUT /someresources/anId
{"anotherdata": "another value"}复制代码
REST 关注于暴露数据。它减小了客户端/服务端的耦合程度,常常用于公共 HTTP API 接口设计。REST 使用更一般与规范化的方法来经过 URI 暴露资源,经过 header 来表述并经过 GET、POST、PUT、DELETE 和 PATCH 这些动做来进行操做。由于无状态的特性,REST 易于横向扩展和隔离。
操做 | RPC | REST |
---|---|---|
注册 | POST /signup | POST /persons |
注销 | POST /resign { "personid": "1234" } |
DELETE /persons/1234 |
读取用户信息 | GET /readPerson?personid=1234 | GET /persons/1234 |
读取用户物品列表 | GET /readUsersItemsList?personid=1234 | GET /persons/1234/items |
向用户物品列表添加一项 | POST /addItemToUsersItemsList { "personid": "1234"; "itemid": "456" } |
POST /persons/1234/items { "itemid": "456" } |
更新一个物品 | POST /modifyItem { "itemid": "456"; "key": "value" } |
PUT /items/456 { "key": "value" } |
删除一个物品 | POST /removeItem { "itemid": "456" } |
DELETE /items/456 |
资料来源:你真的知道你为何更喜欢 REST 而不是 RPC 吗
这一部分须要更多内容。一块儿来吧!
安全是一个宽泛的话题。除非你有至关的经验、安全方面背景或者正在申请的职位要求安全知识,你不须要了解安全基础知识之外的内容:
一些时候你会被要求作出保守估计。好比,你可能须要估计从磁盘中生成 100 张图片的缩略图须要的时间或者一个数据结构须要多少的内存。2 的次方表和每一个开发者都须要知道的一些时间数据(译注:OSChina 上有这篇文章的译文)都是一些很方便的参考资料。
Power Exact Value Approx Value Bytes
---------------------------------------------------------------
7 128
8 256
10 1024 1 thousand 1 KB
16 65,536 64 KB
20 1,048,576 1 million 1 MB
30 1,073,741,824 1 billion 1 GB
32 4,294,967,296 4 GB
40 1,099,511,627,776 1 trillion 1 TB复制代码
Latency Comparison Numbers
--------------------------
L1 cache reference 0.5 ns
Branch mispredict 5 ns
L2 cache reference 7 ns 14x L1 cache
Mutex lock/unlock 100 ns
Main memory reference 100 ns 20x L2 cache, 200x L1 cache
Compress 1K bytes with Zippy 10,000 ns 10 us
Send 1 KB bytes over 1 Gbps network 10,000 ns 10 us
Read 4 KB randomly from SSD* 150,000 ns 150 us ~1GB/sec SSD
Read 1 MB sequentially from memory 250,000 ns 250 us
Round trip within same datacenter 500,000 ns 500 us
Read 1 MB sequentially from SSD* 1,000,000 ns 1,000 us 1 ms ~1GB/sec SSD, 4X memory
Disk seek 10,000,000 ns 10,000 us 10 ms 20x datacenter roundtrip
Read 1 MB sequentially from 1 Gbps 10,000,000 ns 10,000 us 10 ms 40x memory, 10X SSD
Read 1 MB sequentially from disk 30,000,000 ns 30,000 us 30 ms 120x memory, 30X SSD
Send packet CA->Netherlands->CA 150,000,000 ns 150,000 us 150 ms
Notes
-----
1 ns = 10^-9 seconds
1 us = 10^-6 seconds = 1,000 ns
1 ms = 10^-3 seconds = 1,000 us = 1,000,000 ns复制代码
基于上述数字的指标:
常见的系统设计面试问题,给出了如何解决的方案连接
问题 | 引用 |
---|---|
设计相似于 Dropbox 的文件同步服务 | youtube.com |
设计相似于 Google 的搜索引擎 | queue.acm.org stackexchange.com ardendertat.com stanford.edu |
设计相似于 Google 的可扩展网络爬虫 | quora.com |
设计 Google 文档 | code.google.com neil.fraser.name |
设计相似 Redis 的建值存储 | slideshare.net |
设计相似 Memcached 的缓存系统 | slideshare.net |
设计相似亚马逊的推荐系统 | hulu.com ijcai13.org |
设计相似 Bitly 的短连接系统 | n00tc0d3r.blogspot.com |
设计相似 WhatsApp 的聊天应用 | highscalability.com |
设计相似 Instagram 的图片分享系统 | highscalability.com highscalability.com |
设计 Facebook 的新闻推荐方法 | quora.com quora.com slideshare.net |
设计 Facebook 的时间线系统 | facebook.com highscalability.com |
设计 Facebook 的聊天系统 | erlang-factory.com facebook.com |
设计相似 Facebook 的图表搜索系统 | facebook.com facebook.com facebook.com |
设计相似 CloudFlare 的内容传递网络 | cmu.edu |
设计相似 Twitter 的热门话题系统 | michael-noll.com snikolov .wordpress.com |
设计一个随机 ID 生成系统 | blog.twitter.com github.com |
返回必定时间段内次数前 k 高的请求 | ucsb.edu wpi.edu |
设计一个数据源于多个数据中心的服务系统 | highscalability.com |
设计一个多人网络卡牌游戏 | indieflashblog.com buildnewgames.com |
设计一个垃圾回收系统 | stuffwithstuff.com washington.edu |
添加更多的系统设计问题 | 贡献 |
关于现实中真实的系统是怎么设计的文章。
Source: Twitter timelines at scale
不要专一于如下文章的细节,专一于如下方面:
类型 | 系统 | 引用 |
---|---|---|
Data processing | MapReduce - Google的分布式数据处理 | research.google.com |
Data processing | Spark - Databricks 的分布式数据处理 | slideshare.net |
Data processing | Storm - Twitter 的分布式数据处理 | slideshare.net |
Data store | Bigtable - Google 的列式数据库 | harvard.edu |
Data store | HBase - Bigtable 的开源实现 | slideshare.net |
Data store | Cassandra - Facebook 的列式数据库 | slideshare.net |
Data store | DynamoDB - Amazon 的文档数据库 | harvard.edu |
Data store | MongoDB - 文档数据库 | slideshare.net |
Data store | Spanner - Google 的全球分布数据库 | research.google.com |
Data store | Memcached - 分布式内存缓存系统 | slideshare.net |
Data store | Redis - 可以持久化及具备值类型的分布式内存缓存系统 | slideshare.net |
File system | Google File System (GFS) - 分布式文件系统 | research.google.com |
File system | Hadoop File System (HDFS) - GFS 的开源实现 | apache.org |
Misc | Chubby - Google 的分布式系统的低耦合锁服务 | research.google.com |
Misc | Dapper - 分布式系统跟踪基础设施 | research.google.com |
Misc | Kafka - LinkedIn 的发布订阅消息系统 | slideshare.net |
Misc | Zookeeper - 集中的基础架构和协调服务 | slideshare.net |
添加更多 | 贡献 |
Company | Reference(s) |
---|---|
Amazon | Amazon 的架构 |
Cinchcast | 天天产生 1500 小时的音频 |
DataSift | 每秒实时挖掘 120000 条 tweet |
DropBox | 咱们如何缩放 Dropbox |
ESPN | 每秒操做 100000 次 |
Google 的架构 | |
1400 万用户,达到兆级别的照片存储 是什么在驱动 Instagram |
|
Justin.tv | Justin.Tv 的直播广播架构 |
Facebook 的可扩展 memcached TAO: Facebook 社交图的分布式数据存储 Facebook 的图片存储 |
|
Flickr | Flickr 的架构 |
Mailbox | 在 6 周内从 0 到 100 万用户 |
从零到每个月数十亿的浏览量 1800 万访问用户,10 倍增加,12 名员工 |
|
Playfish | 月用户量 5000 万并在不断增加 |
PlentyOfFish | PlentyOfFish 的架构 |
Salesforce | 他们天天如何处理 13 亿笔交易 |
Stack Overflow | Stack Overflow 的架构 |
TripAdvisor | 40M 访问者,200M 页面浏览量,30TB 数据 |
Tumblr | 每个月 150 亿的浏览量 |
Making Twitter 10000 percent faster 天天使用 MySQL 存储2.5亿条 tweet 150M 活跃用户,300K QPS,22 MB/S 的防火墙 可扩展时间表 Twitter 的大小数据 Twitter 的行为:规模超过 1 亿用户 |
|
Uber | Uber 如何扩展本身的实时化市场 |
Facebook 用 190 亿美圆购买 WhatsApp 的架构 | |
YouTube | YouTube 的可扩展性 YouTube 的架构 |
你即将面试的公司的架构
你面对的问题可能就来自于一样领域
有兴趣加入添加一些部分或者帮助完善某些部分吗?加入进来吧!
整个仓库都提供了证书和源
特别鸣谢:
欢迎联系我讨论本文的不足、问题或者意见。
能够在个人 GitHub 主页上找到个人联系方式
Creative Commons Attribution 4.0 International License (CC BY 4.0)
http://creativecommons.org/licenses/by/4.0/复制代码
掘金翻译计划 是一个翻译优质互联网技术文章的社区,文章来源为 掘金 上的英文分享文章。内容覆盖 Android、iOS、React、前端、后端、产品、设计 等领域,想要查看更多优质译文请持续关注 掘金翻译计划。