system-design-primer - 学习如何设计大型系统

Created at: 2017-02-27 00:15:28
Language: Python
License: NOASSERTION

English日本語简体中文 ∙ 繁體中文 |العَرَبِيَّةবাংলাPortuguês do BrasilDeutschελληνικάעבריתItaliano한국어فارسیPolskiрусский языкEspañolภาษาไทยTürkçetiếng ViệtFrançais |添加翻译

帮助翻译本指南!

系统设计入门


赋予动机

了解如何设计大型系统。

准备系统设计面试。

了解如何设计大型系统

学习如何设计可扩展的系统将帮助你成为一名更好的工程师。

系统设计是一个广泛的话题。关于系统设计原则的大量资源散布在整个网络上

此存储库是有组织的资源集合,可帮助你了解如何大规模构建系统。

向开源社区学习

这是一个不断更新的开源项目。

欢迎投稿

系统设计面试准备

除了编码面试外,系统设计是许多科技公司技术面试过程必要组成部分

练习常见的系统设计面试问题,并将结果与示例解决方案(讨论、代码和图表)进行比较

面试准备的其他主题:

Anki 抽认卡


提供的 Anki 抽认卡组使用间隔重复来帮助你保留关键的系统设计概念。

非常适合在旅途中使用。

编码资源:交互式编码挑战

正在寻找资源来帮助你准备编码面试


查看姊妹存储库 Interactive Coding Challenges,其中包含一个额外的 Anki 套牌:

贡献

向社区学习。

请随时提交拉取请求以帮助:

  • 修正错误
  • 改进部分
  • 添加新部分
  • 翻译

需要打磨的内容正在开发中

查看贡献指南

系统设计主题索引

各种系统设计主题的摘要,包括优点和缺点。 一切都是权衡取舍

每个部分都包含指向更深入资源的链接。


学习指南

根据你的面试时间表(短、中、长)建议要审查的主题。

伊姆古尔

问:对于面试,我需要知道这里的一切吗?

答:不,你不需要知道这里的一切来准备面试

面试中会问到什么取决于以下变量:

  • 你有多少经验
  • 你的技术背景是什么
  • 你正在面试什么职位
  • 你正在面试哪些公司
  • 运气

更有经验的考生通常应该更多地了解系统设计。架构师或团队领导可能比个人贡献者知道的更多。顶级科技公司可能会进行一轮或多轮设计面试。

从广义开始,在几个领域深入。它有助于了解一些关键系统设计主题。根据你的时间表、经验、你正在面试的职位以及你正在面试的公司调整以下指南。

  • 较短的时间线 - 以系统设计主题的广度为目标。通过解决一些面试问题进行练习。
  • 中等时间线 - 以系统设计主题的广度深度为目标。通过解决许多面试问题进行练习。
  • 长时间线 - 以系统设计主题的广度深度为目标。通过解决大多数面试问题进行练习。
中等
通读系统设计主题,全面了解系统的工作原理 👍 👍 👍
通读公司工程博客中的几篇文章,了解你正在面试的公司 👍 👍 👍
通读一些真实世界的架构 👍 👍 👍
复习如何处理系统设计面试问题 👍 👍 👍
通过系统设计面试问题和解决方案进行工作 一些
通过面向对象的设计面试问题和解决方案进行工作 一些
查看其他系统设计面试问题 一些

如何处理系统设计面试问题

如何解决系统设计面试问题。

系统设计面试是一个开放式的对话。你应该领导它。

你可以使用以下步骤来指导讨论。为了帮助巩固此过程,请使用以下步骤完成系统设计面试问题和解决方案部分。

第 1 步:概述用例、约束和假设

收集需求并确定问题范围。提出问题以阐明用例和约束。讨论假设。

  • 谁将使用它?
  • 他们将如何使用它?
  • 有多少用户?
  • 系统有什么作用?
  • 系统的输入和输出是什么?
  • 我们期望处理多少数据?
  • 我们预计每秒有多少个请求?
  • 预期的读写比率是多少?

第 2 步:创建高级设计

概述包含所有重要组件的高级设计。

  • 绘制主要组件和连接的草图
  • 证明你的想法是合理的

第 3 步:设计核心组件

深入了解每个核心组件的详细信息。例如,如果你被要求设计一个网址缩短服务,请讨论:

  • 生成和存储完整 url 的哈希值
    • MD5Base62
    • 哈希冲突
    • SQL 或 NoSQL
    • 数据库架构
  • 将经过哈希处理的 URL 转换为完整 URL
    • 数据库查找
  • API 和面向对象设计

第 4 步:缩放设计

在给定约束的情况下,识别并解决瓶颈。例如,是否需要以下内容来解决可伸缩性问题?

  • 负载均衡器
  • 水平缩放
  • 缓存
  • 数据库分片

讨论潜在的解决方案和权衡。一切都是权衡取舍。使用可扩展系统设计原则解决瓶颈问题。

粗略的计算

你可能会被要求手动进行一些估算。有关以下资源,请参阅附录

来源和延伸阅读

请查看以下链接,以更好地了解预期内容:

系统设计面试问题及解决方案

常见的系统设计面试问题,包括示例讨论、代码和图表。

链接到文件夹中内容的解决方案。

solutions/

问题
设计 Pastebin.com(或 Bit.ly) 溶液
设计 Twitter 时间线和搜索(或 Facebook 提要和搜索) 溶液
设计网络爬虫 溶液
设计 Mint.com 溶液
设计社交网络的数据结构 溶液
为搜索引擎设计键值存储 溶液
按类别功能设计亚马逊的销售排名 溶液
在 AWS 上设计可扩展到数百万用户的系统 溶液
添加系统设计问题 贡献

设计 Pastebin.com(或 Bit.ly)

查看练习和解决方案

伊姆古尔

设计 Twitter 时间线和搜索(或 Facebook 提要和搜索)

查看练习和解决方案

伊姆古尔

设计网络爬虫

查看练习和解决方案

伊姆古尔

设计 Mint.com

查看练习和解决方案

伊姆古尔

设计社交网络的数据结构

查看练习和解决方案

伊姆古尔

为搜索引擎设计键值存储

查看练习和解决方案

伊姆古尔

按类别功能设计亚马逊的销售排名

查看练习和解决方案

伊姆古尔

在 AWS 上设计可扩展到数百万用户的系统

查看练习和解决方案

伊姆古尔

面向对象的设计面试问题及解决方案

常见的面向对象设计面试问题,包括示例讨论、代码和图表。

链接到文件夹中内容的解决方案。

solutions/

注意:此部分正在开发中

问题
设计哈希映射 溶液
设计最近最少使用的缓存 溶液
设计呼叫中心 溶液
设计一副纸牌 溶液
设计停车场 溶液
设计聊天服务器 溶液
设计圆形阵列 贡献
添加面向对象的设计问题 贡献

系统设计主题:从这里开始

刚接触系统设计?

首先,你需要对常见原则有一个基本的了解,了解它们是什么、如何使用它们以及它们的优缺点。

第 1 步:查看可伸缩性视频讲座

哈佛大学可扩展性讲座

  • 主题:
    • 垂直缩放
    • 水平缩放
    • 缓存
    • 负载均衡
    • 数据库复制
    • 数据库分区

步骤 2:查看可伸缩性一文

可扩展性

后续步骤

接下来,我们将了解高级权衡:

  • 性能可伸缩性
  • 延迟吞吐量
  • 可用性一致性

请记住,一切都是权衡取舍

然后,我们将深入探讨更具体的主题,例如 DNS、CDN 和负载均衡器。

性能与可伸缩性

如果服务以与添加的资源成正比的方式提高性能,则该服务是可伸缩的。通常,提高性能意味着为更多的工作单元提供服务,但也可能是处理更大的工作单元,例如当数据集增长时。1

查看性能与可伸缩性的另一种方式:

  • 如果遇到性能问题,则单个用户的系统速度较慢。
  • 如果存在可伸缩性问题,则系统对于单个用户来说速度很快,但在高负载下速度较慢。

来源和延伸阅读

延迟与吞吐量

延迟是执行某些操作或产生某些结果的时间。

吞吐量是每单位时间内此类操作或结果的数量。

通常,应以可接受的延迟实现最大吞吐量为目标。

来源和延伸阅读

可用性与一致性

CAP定理


资料来源:重新审视 CAP 定理

在分布式计算机系统中,只能支持以下两项保证:

  • 一致性 - 每次读取都会收到最新的写入或错误
  • 可用性 - 每个请求都会收到响应,但不能保证它包含最新版本的信息
  • 分区容错 - 尽管由于网络故障导致任意分区,系统仍继续运行

网络不可靠,因此需要支持分区容错。你需要在一致性和可用性之间进行软件权衡。

CP - 一致性和分区容错性

等待分区节点的响应可能会导致超时错误。如果你的业务需求需要原子读取和写入,CP 是一个不错的选择。

AP - 可用性和分区容错性

响应返回任何节点上可用数据的最容易获得的版本,这可能不是最新的。解析分区时,写入可能需要一些时间才能传播。

如果业务需要允许最终一致性,或者当系统需要在外部错误的情况下继续工作时,AP 是一个不错的选择。

来源和延伸阅读

一致性模式

对于同一数据的多个副本,我们面临着如何同步它们的选项,以便客户对数据有一个一致的视图。回想一下 CAP 定理中一致性的定义 - 每次读取都会收到最近的写入或错误。

一致性弱

写入后,读取者可能会或可能不会看到它。采取尽力而为的方法。

这种方法在 memcached 等系统中可见。弱一致性在实时用例(如 VoIP、视频聊天和实时多人游戏)中效果很好。例如,如果你在通话中失去接收几秒钟,当你重新获得连接时,你不会听到连接丢失期间所说的内容。

最终一致性

写入后,读取者最终会看到它(通常在几毫秒内)。数据是异步复制的。

这种方法在 DNS 和电子邮件等系统中可见。最终一致性在高可用性系统中效果很好。

一致性强

写入后,读取者将看到它。数据是同步复制的。

这种方法在文件系统和 RDBMS 中可见。强一致性在需要事务的系统中效果很好。

来源和延伸阅读

可用性模式

有两种互补模式可以支持高可用性:故障转移复制

故障转移

主动-被动

通过主动-被动故障转移,检测信号在备用服务器和无源服务器之间发送。如果检测信号中断,无源服务器将接管主用服务器的 IP 地址并恢复服务。

停机时间的长短取决于无源服务器是否已经在“热”备用状态下运行,或者是否需要从“冷”备用状态启动。只有活动服务器处理流量。

主动-被动故障切换也称为主-从故障切换。

主动-主动

在主动-主动模式下,两台服务器都在管理流量,在它们之间分散负载。

如果服务器是面向公众的,则 DNS 需要了解两台服务器的公共 IP。如果服务器面向内部,则应用程序逻辑需要了解这两个服务器。

主动-主动故障切换也称为主-主故障切换。

缺点:故障转移

  • 故障转移会增加更多的硬件和额外的复杂性。
  • 如果主动系统在将任何新写入的数据复制到被动系统之前发生故障,则可能会丢失数据。

复制

主-从和主-主

本主题将在“数据库”部分中进一步讨论:

可用性数量

可用性通常通过正常运行时间(或停机时间)来量化,作为服务可用时间的百分比。可用性通常以 9 的数量来衡量,可用性为 99.99% 的服务被描述为具有四个 9。

99.9% 的可用性 - 三个 9

期间 可接受的停机时间
每年停机时间 8小时 45分 57秒
每月停机时间 43 分 49.7 秒
每周停机时间 10 分 4.8 秒
每天停机时间 1 分 26.4 秒

99.99% 可用性 - 四个 9

期间 可接受的停机时间
每年停机时间 52分 35.7秒
每月停机时间 4 分 23 秒
每周停机时间 1 分 5 秒
每天停机时间 8.6秒

并行可用性与顺序可用性

如果服务由多个容易发生故障的组件组成,则服务的整体可用性取决于这些组件是按顺序还是并行。

当两个可用性< 100% 的组件依次排列时,总体可用性会降低:

Availability (Total) = Availability (Foo) * Availability (Bar)

如果两者和每个都有 99.9% 的可用性,则它们的总可用性依次为 99.8%。

Foo
Bar

并行

当两个可用性< 100% 的组件并行时,总体可用性会提高:

Availability (Total) = 1 - (1 - Availability (Foo)) * (1 - Availability (Bar))

如果两者和每个都有 99.9% 的可用性,则它们的并行总可用性将为 99.9999%。

Foo
Bar

域名系统


来源:DNS 安全演示文稿

域名系统 (DNS) 将域名(如 www.example.com)转换为 IP 地址。

DNS 是分层的,在顶层有一些权威服务器。你的路由器或 ISP 提供有关在执行查找时要联系的 DNS 服务器的信息。较低级别的 DNS 服务器缓存映射,由于 DNS 传播延迟,这些映射可能会过时。你的浏览器或操作系统也可以将 DNS 结果缓存一段时间,由生存时间 (TTL) 决定。

  • NS 记录(名称服务器) - 指定域/子域的 DNS 服务器。
  • MX 记录(邮件交换) - 指定用于接受邮件的邮件服务器。
  • 记录(地址) - 将名称指向 IP 地址。
  • CNAME (canonical) - 将一个名称指向另一个名称或(example.com 指向 www.example.com)或记录。
    CNAME
    A

CloudFlareRoute 53 等服务提供托管 DNS 服务。某些 DNS 服务可以通过各种方法路由流量:

缺点:DNS

  • 访问 DNS 服务器会引入轻微的延迟,但可以通过上述缓存来缓解。
  • DNS 服务器管理可能很复杂,通常由政府、ISP 和大公司管理。
  • DNS 服务最近受到 DDoS 攻击,阻止用户在不知道 Twitter 的 IP 地址的情况下访问 Twitter 等网站。

来源和延伸阅读

内容分发网络


来源:为什么要使用 CDN

内容分发网络 (CDN) 是一个全球分布的代理服务器网络,从离用户更近的位置提供内容。通常,HTML/CSS/JS、照片和视频等静态文件由 CDN 提供,尽管某些 CDN(如 Amazon 的 CloudFront)支持动态内容。站点的 DNS 解析将告诉客户端要联系哪个服务器。

从 CDN 提供内容可以通过两种方式显著提高性能:

  • 用户从附近的数据中心接收内容
  • 你的服务器不必为 CDN 满足的请求提供服务

推送 CDN

每当服务器上发生更改时,推送 CDN 都会接收新内容。你全权负责提供内容、直接上传到 CDN 以及重写 URL 以指向 CDN。你可以配置内容何时过期以及何时更新内容。仅当内容是新的或更改的内容时才上传,从而最大限度地减少流量,但最大化存储空间。

流量较小的网站或内容不经常更新的网站可以很好地与推送 CDN 配合使用。 内容在 CDN 上放置一次,而不是定期重新拉取。

拉取 CDN

拉取 CDN 在第一个用户请求内容时从你的服务器获取新内容。将内容保留在服务器上,并重写 URL 以指向 CDN。这会导致请求速度变慢,直到内容缓存到 CDN 上。

生存时间 (TTL) 决定了缓存内容的时间。拉取 CDN 可最大程度地减少 CDN 上的存储空间,但如果文件过期并在实际更改之前拉取,则可能会产生冗余流量。

流量大的网站与拉式 CDN 配合得很好,因为流量分布得更均匀,CDN 上只保留最近请求的内容。

缺点:CDN

  • CDN 成本可能很高,具体取决于流量,尽管这应该与不使用 CDN 会产生的额外成本相权衡。
  • 如果内容在 TTL 过期之前更新,则内容可能已过时。
  • CDN 需要更改静态内容的 URL 以指向 CDN。

来源和延伸阅读

负载均衡器


来源:可扩展的系统设计模式

负载均衡器将传入的客户端请求分发到计算资源,例如应用程序服务器和数据库。在每种情况下,负载均衡器都会将响应从计算资源返回到相应的客户端。负载均衡器在以下方面有效:

  • 防止请求进入运行状况不佳的服务器
  • 防止资源过载
  • 帮助消除单点故障

负载均衡器可以使用硬件(昂贵)或软件(如 HAProxy)来实现。

其他好处包括:

  • SSL 终止 - 解密传入请求并加密服务器响应,以便后端服务器不必执行这些可能代价高昂的操作
  • 会话持久性 - 如果 Web 应用不跟踪会话,则发出 Cookie 并将特定客户端的请求路由到同一实例

为了防止故障,通常在主动-被动或主动-主动模式下设置多个负载均衡器。

负载均衡器可以根据各种指标路由流量,包括:

第 4 层负载均衡

第 4 层负载均衡器查看传输层的信息,以决定如何分发请求。通常,这涉及标头中的源、目标 IP 地址和端口,但不涉及数据包的内容。第 4 层负载均衡器将网络数据包转发到上游服务器或从上游服务器转发网络数据包,执行网络地址转换 (NAT)。

第 7 层负载均衡

第 7 层负载均衡器查看应用程序层以决定如何分发请求。这可能涉及标头、消息和 Cookie 的内容。第 7 层负载平衡器终止网络流量,读取消息,做出负载平衡决策,然后打开与所选服务器的连接。例如,第 7 层负载均衡器可以将视频流量定向到托管视频的服务器,同时将更敏感的用户计费流量定向到安全强化的服务器。

以灵活性为代价,第 4 层负载均衡比第 7 层需要更少的时间和计算资源,尽管对现代商用硬件的性能影响可能很小。

水平缩放

负载均衡器还可以帮助进行水平扩展,从而提高性能和可用性。与在更昂贵的硬件上纵向扩展单个服务器(称为垂直缩放)相比,使用商用计算机进行横向扩展更具成本效益,并且可以提高可用性。与专业企业系统相比,雇用从事商用硬件工作的人才也更容易。

缺点:水平缩放

  • 水平扩展会带来复杂性,并涉及克隆服务器
    • 服务器应该是无状态的:它们不应包含任何与用户相关的数据,如会话或个人资料图片
    • 会话可以存储在集中式数据存储中,例如数据库(SQL、NoSQL)或持久性缓存(Redis、Memcached)
  • 随着上游服务器的横向扩展,下游服务器(如缓存和数据库)需要处理更多的并发连接

缺点:负载均衡器

  • 如果负载均衡器没有足够的资源或配置不正确,它可能会成为性能瓶颈。
  • 引入负载均衡器以帮助消除单点故障会导致复杂性增加。
  • 单个负载均衡器是单点故障,配置多个负载均衡器会进一步增加复杂性。

来源和延伸阅读

反向代理(Web 服务器)


资料来源:维基百科

反向代理是一种 Web 服务器,它集中了内部服务并向公众提供统一的接口。在反向代理将服务器的响应返回给客户端之前,来自客户端的请求将转发到可以完成该请求的服务器。

其他好处包括:

  • 提高安全性 - 隐藏有关后端服务器的信息,将 IP 列入黑名单,限制每个客户端的连接数
  • 提高可扩展性和灵活性 - 客户端只能看到反向代理的 IP,从而允许你扩展服务器或更改其配置
  • SSL 终止 - 解密传入请求并加密服务器响应,以便后端服务器不必执行这些可能代价高昂的操作
  • Compression - 压缩服务器响应
  • 缓存 - 返回缓存请求的响应
  • 静态内容 - 直接提供静态内容
    • HTML/CSS/JS格式
    • 照片
    • 视频

负载均衡器与反向代理

  • 当你有多个服务器时,部署负载平衡器非常有用。通常,负载均衡器将流量路由到一组提供相同功能的服务器。
  • 即使只有一个 Web 服务器或应用程序服务器,反向代理也很有用,这开启了上一节中描述的好处。
  • NGINX 和 HAProxy 等解决方案可以同时支持第 7 层反向代理和负载均衡。

缺点:反向代理

  • 引入反向代理会导致复杂性增加。
  • 单个反向代理是单点故障,配置多个反向代理(即故障转移)会进一步增加复杂性。

来源和延伸阅读

应用层


来源:Intro to Architecting Systems for Scale

通过将 Web 层与应用层(也称为平台层)分离出来,你可以独立扩展和配置这两个层。添加新的 API 会导致添加应用程序服务器,而不必添加其他 Web 服务器。单一责任原则提倡协同工作的小型和自主服务。拥有小型服务的小型团队可以更积极地规划快速增长。

应用层的工作线程还有助于实现异步。

微服务

与此讨论相关的是服务,它可以被描述为一套可独立部署的小型模块化服务。每个服务都运行一个独特的流程,并通过定义明确的轻量级机制进行通信,以实现业务目标。1

例如,Pinterest 可以有以下微服务:用户个人资料、关注者、提要、搜索、照片上传等。

服务发现

ConsulEtcdZookeeper 等系统可以通过跟踪注册的名称、地址和端口来帮助服务找到彼此。运行状况检查有助于验证服务完整性,通常使用 HTTP 终结点完成。Consul 和 Etcd 都有一个内置的键值存储,可用于存储配置值和其他共享数据。

缺点:应用层

  • 添加具有松散耦合服务的应用程序层需要从架构、操作和流程的角度(与整体系统)不同的方法。
  • 微服务可能会增加部署和操作的复杂性。

来源和延伸阅读

数据库


来源:扩展到前 1000 万用户

关系数据库管理系统 (RDBMS)

像 SQL 这样的关系数据库是以表形式组织的数据项的集合。

ACID 是关系数据库事务的一组属性。

  • 原子性 - 每笔交易都是全有或全无
  • 一致性 - 任何事务都会将数据库从一个有效状态带到另一个有效状态
  • 隔离 - 并发执行事务的结果与串行执行事务的结果相同
  • 持久性 - 一旦交易被提交,它将保持这种状态

有许多技术可以扩展关系数据库:主复制、主-主复制联合分片非规范化SQL 优化

主从复制

主服务器提供读取和写入服务,将写入复制到一个或多个仅提供读取服务的从服务器。从属服务器还可以以树状的方式复制到其他从属服务器。如果主设备脱机,系统可以继续以只读模式运行,直到从设备升级为主设备或配置新的主设备。


来源:可伸缩性、可用性、稳定性、模式

缺点:主从复制
  • 需要额外的逻辑才能将从属设备提升为主设备。
  • 请参阅缺点:复制,了解与主从和主主相关的点。

主-主复制

两个主服务器都提供读取和写入,并在写入时相互协调。如果任一主设备出现故障,系统可以继续进行读取和写入操作。


来源:可伸缩性、可用性、稳定性、模式

缺点:主-主复制
  • 需要负载均衡器,或者需要对应用程序逻辑进行更改以确定写入位置。
  • 大多数主-主系统要么松散一致(违反 ACID),要么由于同步而增加了写入延迟。
  • 随着添加更多写入节点和延迟增加,冲突解决发挥了更大的作用。
  • 请参阅缺点:复制,了解与主从和主主相关的点。
缺点:复制
  • 如果主节点在将任何新写入的数据复制到其他节点之前发生故障,则可能会丢失数据。
  • 写入将重放到只读副本。如果写入次数很多,则只读副本可能会因重放写入而陷入困境,并且无法执行尽可能多的读取操作。
  • 读取从属设备越多,需要复制的次数就越多,这会导致更大的复制延迟。
  • 在某些系统上,写入主服务器可能会生成多个线程以并行写入,而只读副本仅支持使用单个线程按顺序写入。
  • 复制增加了更多的硬件和额外的复杂性。
来源和延伸阅读:复制

联邦


来源:扩展到前 10 万用户

联合(或功能分区)按功能拆分数据库。例如,你可以拥有三个数据库:论坛用户产品,而不是单个整体式数据库,从而减少每个数据库的读取和写入流量,从而减少复制滞后。数据库越小,内存中可以容纳的数据就越多,这反过来又会由于缓存局部性的改进而导致更多的缓存命中。由于没有单个中央主序列化写入,因此你可以并行写入,从而提高吞吐量。

缺点:联合
  • 如果架构需要大型函数或表,则联合无效。
  • 需要更新应用程序逻辑,以确定要读取和写入的数据库。
  • 使用服务器链接联接来自两个数据库的数据更为复杂。
  • 联合增加了更多的硬件和额外的复杂性。
来源和延伸阅读:联邦

分片


来源:可伸缩性、可用性、稳定性、模式

分片将数据分布在不同的数据库之间,因此每个数据库只能管理数据的子集。以用户数据库为例,随着用户数量的增加,集群中加入的分片也越来越多。

联合的优点类似,分片可以减少读取和写入流量、减少复制和增加缓存命中。索引大小也会减小,这通常会通过更快的查询来提高性能。如果一个分片出现故障,其他分片仍可运行,但你需要添加某种形式的复制以避免数据丢失。与联合一样,没有单个中央主序列化写入,允许你在增加吞吐量的同时并行写入。

对用户表进行分片的常见方法是通过用户的姓氏首字母或用户的地理位置。

缺点:分片
  • 你需要更新应用程序逻辑以使用分片,这可能会导致复杂的 SQL 查询。
  • 数据分布在分片中可能会变得不平衡。例如,与其他分片相比,分片上的一组高级用户可能会导致该分片的负载增加。
    • 再平衡增加了额外的复杂性。基于一致哈希的分片函数可以减少传输的数据量。
  • 联接来自多个分片的数据更为复杂。
  • 分片增加了更多的硬件和额外的复杂性。
来源和延伸阅读:分片

非规范化

非规范化想以牺牲某些写入性能为代价来提高读取性能。数据的冗余副本写入多个表中,以避免成本高昂的联接。一些 RDBMS(如 PostgreSQL 和 Oracle)支持物化视图,这些视图处理存储冗余信息和保持冗余副本一致性的工作。

一旦数据通过联合分片等技术进行分布式处理,跨数据中心管理联接将进一步增加复杂性。非规范化可能会规避对这种复杂连接的需求。

在大多数系统中,读取次数可能远远超过写入次数 100:1 甚至 1000:1。导致复杂数据库联接的读取可能非常昂贵,在磁盘操作上花费大量时间。

缺点:非规范化
  • 数据重复。
  • 约束可以帮助冗余的信息副本保持同步,这增加了数据库设计的复杂性。
  • 在繁重的写入负载下,非规范化数据库的性能可能比规范化的对应数据库差。
来源和延伸阅读:非规范化

SQL 调优

SQL调优是一个广泛的话题,已经写了许多书籍作为参考。

基准测试和分析进行建模以模拟和发现瓶颈非常重要。

  • 基准测试 - 使用 ab.
  • 配置文件 - 启用慢速查询日志等工具,以帮助跟踪性能问题。

基准测试和分析可能会指向以下优化。

收紧架构
  • MySQL以连续块的形式转储到磁盘,以便快速访问。
  • 代替固定长度字段使用。
    CHAR
    VARCHAR
    • CHAR
      有效地允许快速、随机的访问,而使用 ,你必须先找到一个字符串的末尾,然后才能进入下一个字符串。
      VARCHAR
  • 用于大块文本,例如博客文章。 还允许布尔搜索。使用字段会导致在磁盘上存储一个指针,该指针用于查找文本块。
    TEXT
    TEXT
    TEXT
  • 用于高达 2^32 或 40 亿的较大数字。
    INT
  • 用于货币以避免浮点表示错误。
    DECIMAL
  • 避免存储大,而是存储获取对象的位置。
    BLOBS
  • VARCHAR(255)
    是可以用 8 位数字计数的最大字符数,通常在某些 RDBMS 中最大化使用一个字节。
  • 在适用的情况下设置约束以提高搜索性能
    NOT NULL
使用好的索引
  • 使用索引,你查询的列 (, , , ) 可能会更快。
    SELECT
    GROUP BY
    ORDER BY
    JOIN
  • 索引通常表示为自平衡 B 树,它保持数据排序,并允许在对数时间内进行搜索、顺序访问、插入和删除。
  • 放置索引可以将数据保留在内存中,从而需要更多空间。
  • 写入速度也可能较慢,因为索引也需要更新。
  • 加载大量数据时,禁用索引、加载数据,然后重新生成索引可能会更快。
避免成本高昂的联接
分区表
  • 通过将热点放在单独的表中来分解表,以帮助将其保留在内存中。
优化查询缓存
来源和延伸阅读:SQL 调优

NoSQL的

NoSQL 是以键值存储、文档存储、宽列存储图形数据库表示的数据项的集合。数据是非规范化的,联接通常在应用程序代码中完成。大多数 NoSQL 存储缺乏真正的 ACID 事务,并且有利于最终一致性

BASE 通常用于描述 NoSQL 数据库的属性。与 CAP 定理相比,BASE 选择可用性而不是一致性。

  • 基本可用 - 系统保证可用性。
  • 软状态 - 即使没有输入,系统的状态也可能随时间而变化。
  • 最终一致性 - 系统将在一段时间内保持一致,前提是系统在该时间段内未收到输入。

除了在 SQL 或 NoSQL 之间进行选择之外,了解哪种类型的 NoSQL 数据库最适合你的用例也很有帮助。我们将在下一节中介绍键值存储、文档存储、宽列存储图形数据库

键值存储

抽象:哈希表

键值存储通常允许 O(1) 读取和写入,并且通常由内存或 SSD 提供支持。数据存储可以按字典顺序维护密钥,从而可以有效地检索密钥范围。键值存储可以允许存储具有值的元数据。

键值存储提供高性能,通常用于简单的数据模型或快速变化的数据,例如内存中缓存层。由于它们仅提供一组有限的操作,因此如果需要其他操作,复杂性会转移到应用层。

键值存储是更复杂系统(如文档存储)的基础,在某些情况下,还有图形数据库。

来源和延伸阅读:键值存储

文档存储

抽象:键值存储,文档存储为值

文档存储以文档(XML、JSON、二进制等)为中心,其中文档存储给定对象的所有信息。文档存储提供 API 或查询语言,用于根据文档本身的内部结构进行查询。请注意,许多键值存储都包含用于处理值元数据的功能,从而模糊了这两种存储类型之间的界限。

根据基础实现,文档按集合、标记、元数据或目录进行组织。尽管文档可以组织或组合在一起,但文档可能具有彼此完全不同的字段。

一些文档存储(如 MongoDBCouchDB)也提供类似 SQL 的语言来执行复杂的查询。DynamoDB 支持键值对和文档。

文档存储提供了高度的灵活性,通常用于处理偶尔更改的数据。

来源及延伸阅读:文件存储

宽列存储


资料来源:SQL 和 NoSQL,简史

抽象:嵌套映射

ColumnFamily<RowKey, Columns<ColKey, Value, Timestamp>>

宽列存储的基本数据单位是列(名称/值对)。列可以按列系列进行分组(类似于 SQL 表)。超级色谱柱族进一步对色谱柱族进行分组。你可以使用行键独立访问每一列,具有相同行键的列构成一行。每个值都包含用于版本控制和冲突解决的时间戳。

Google 引入了 Bigtable 作为第一个宽列存储,这影响了 Hadoop 生态系统中经常使用的开源 HBase,以及 Facebook 的 Cassandra。BigTable、HBase 和 Cassandra 等存储按字典顺序维护密钥,从而可以高效检索选择性密钥范围。

宽列存储提供高可用性和高可伸缩性。它们通常用于非常大的数据集。

来源和延伸阅读:宽列存储

图形数据库


来源:图库

抽象:图形

在图形数据库中,每个节点都是一条记录,每个弧是两个节点之间的关系。图形数据库经过优化,可以表示具有许多外键或多对多关系的复杂关系。

图形数据库为具有复杂关系的数据模型(例如社交网络)提供高性能。它们相对较新,尚未广泛使用;查找开发工具和资源可能更加困难。许多图形只能使用 REST API 访问。

来源和延伸阅读:图表

来源和延伸阅读:NoSQL

SQL 或 NoSQL


来源:从 RDBMS 过渡到 NoSQL

使用 SQL 的原因:

  • 结构化数据
  • 严格架构
  • 关系数据
  • 需要复杂的联接
  • 交易
  • 清晰的缩放模式
  • 更成熟:开发人员、社区、代码、工具等
  • 按索引查找非常快

使用 NoSQL 的原因:

  • 半结构化数据
  • 动态或灵活的架构
  • 非关系型数据
  • 无需复杂的连接
  • 存储数 TB(或 PB)的数据
  • 数据密集型工作负载
  • IOPS 的超高吞吐量

非常适合 NoSQL 的示例数据:

  • 快速摄取点击流和日志数据
  • 排行榜或得分数据
  • 临时数据,例如购物车
  • 经常访问的(“热”)表
  • 元数据/查找表
来源和延伸阅读:SQL 或 NoSQL

缓存


来源:可扩展的系统设计模式

缓存可缩短页面加载时间,并可减少服务器和数据库的负载。在此模型中,调度程序将首先查找之前是否发出过请求,并尝试查找要返回的先前结果,以保存实际执行。

数据库通常受益于跨分区的读取和写入的均匀分布。热门项目可能会扭曲分布,从而导致瓶颈。将缓存放在数据库的前面有助于吸收不均匀的负载和流量峰值。

客户端缓存

缓存可以位于客户端(操作系统或浏览器)、服务器端或不同的缓存层中。

CDN 缓存

CDN 被视为一种缓存。

Web 服务器缓存

反向代理和缓存(如 Varnish)可以直接提供静态和动态内容。Web 服务器还可以缓存请求,返回响应,而无需联系应用程序服务器。

数据库缓存

你的数据库通常在默认配置中包含某种级别的缓存,并针对通用用例进行了优化。针对特定使用模式调整这些设置可以进一步提高性能。

应用程序缓存

Memcached 和 Redis 等内存缓存是应用程序和数据存储之间的键值存储。由于数据保存在 RAM 中,因此它比数据存储在磁盘上的典型数据库快得多。RAM 比磁盘更受限制,因此缓存失效算法(如最近最少使用过 (LRU))可以帮助使“冷”条目失效,并将“热”数据保留在 RAM 中。

Redis 具有以下附加功能:

  • 持久性选项
  • 内置数据结构,例如排序集和列表

可以缓存多个级别,这些级别分为两个常规类别:数据库查询对象

  • 行级别
  • 查询级别
  • 完全格式化的可序列化对象
  • 完全呈现的 HTML

通常,应尽量避免基于文件的缓存,因为它会使克隆和自动缩放更加困难。

数据库查询级别的缓存

每当查询数据库时,请将查询作为键进行哈希处理,并将结果存储到缓存中。此方法存在过期问题:

  • 难以删除具有复杂查询的缓存结果
  • 如果一条数据发生更改(例如表单元格),则需要删除可能包含已更改单元格的所有缓存查询

对象级别的缓存

将数据视为对象,类似于对应用程序代码执行的操作。让应用程序将数据库中的数据集组合到类实例或数据结构中:

  • 如果对象的基础数据已更改,则从缓存中删除该对象
  • 允许异步处理:工作线程通过使用最新的缓存对象来组装对象

缓存内容的建议:

  • 用户会话
  • 完全呈现的网页
  • 活动流
  • 用户图数据

何时更新缓存

由于你只能在缓存中存储有限数量的数据,因此你需要确定哪种缓存更新策略最适合你的用例。

缓存端


源:从缓存到内存中数据网格

该应用程序负责从存储中读取和写入。缓存不直接与存储交互。该应用程序执行以下操作:

  • 在缓存中查找条目,导致缓存未命中
  • 从数据库加载条目
  • 将条目添加到缓存
  • 回程入场
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 通常以这种方式使用。

对添加到缓存中的数据的后续读取速度很快。缓存端也称为延迟加载。仅缓存请求的数据,从而避免使用未请求的数据填满缓存。

缺点:缓存端
  • 每次缓存未命中都会导致三次行程,这可能会导致明显的延迟。
  • 如果在数据库中更新数据,数据可能会过时。通过设置强制更新缓存条目的生存时间 (TTL) 或使用直写功能,可以缓解此问题。
  • 当节点发生故障时,它将被一个新的空节点替换,从而增加延迟。

直写


来源:可伸缩性、可用性、稳定性、模式

The application uses the cache as the main data store, reading and writing data to it, while the cache is responsible for reading and writing to the database:

  • Application adds/updates entry in cache
  • Cache synchronously writes entry to data store
  • Return

Application code:

set_user(12345, {"foo":"bar"})

Cache code:

def set_user(user_id, values):
    user = db.query("UPDATE Users WHERE id = {0}", user_id, values)
    cache.set(user_id, user)

Write-through is a slow overall operation due to the write operation, but subsequent reads of just written data are fast. Users are generally more tolerant of latency when updating data than reading data. Data in the cache is not stale.

Disadvantage(s): write through
  • When a new node is created due to failure or scaling, the new node will not cache entries until the entry is updated in the database. Cache-aside in conjunction with write through can mitigate this issue.
  • Most data written might never be read, which can be minimized with a TTL.

后写(write-back)


来源:可伸缩性、可用性、稳定性、模式

In write-behind, the application does the following:

  • Add/update entry in cache
  • Asynchronously write entry to the data store, improving write performance
Disadvantage(s): write-behind
  • There could be data loss if the cache goes down prior to its contents hitting the data store.
  • It is more complex to implement write-behind than it is to implement cache-aside or write-through.

提前刷新


源:从缓存到内存中数据网格

You can configure the cache to automatically refresh any recently accessed cache entry prior to its expiration.

Refresh-ahead can result in reduced latency vs read-through if the cache can accurately predict which items are likely to be needed in the future.

Disadvantage(s): refresh-ahead
  • Not accurately predicting which items are likely to be needed in the future can result in reduced performance than without refresh-ahead.

Disadvantage(s): cache

  • Need to maintain consistency between caches and the source of truth such as the database through cache invalidation.
  • Cache invalidation is a difficult problem, there is additional complexity associated with when to update the cache.
  • Need to make application changes such as adding Redis or memcached.

来源和延伸阅读

Asynchronism


Source: Intro to architecting systems for scale

Asynchronous workflows help reduce request times for expensive operations that would otherwise be performed in-line. They can also help by doing time-consuming work in advance, such as periodic aggregation of data.

Message queues

Message queues receive, hold, and deliver messages. If an operation is too slow to perform inline, you can use a message queue with the following workflow:

  • An application publishes a job to the queue, then notifies the user of job status
  • A worker picks up the job from the queue, processes it, then signals the job is complete

The user is not blocked and the job is processed in the background. During this time, the client might optionally do a small amount of processing to make it seem like the task has completed. For example, if posting a tweet, the tweet could be instantly posted to your timeline, but it could take some time before your tweet is actually delivered to all of your followers.

Redis is useful as a simple message broker but messages can be lost.

RabbitMQ is popular but requires you to adapt to the 'AMQP' protocol and manage your own nodes.

Amazon SQS is hosted but can have high latency and has the possibility of messages being delivered twice.

Task queues

Tasks queues receive tasks and their related data, runs them, then delivers their results. They can support scheduling and can be used to run computationally-intensive jobs in the background.

Celery has support for scheduling and primarily has python support.

Back pressure

If queues start to grow significantly, the queue size can become larger than memory, resulting in cache misses, disk reads, and even slower performance. Back pressure can help by limiting the queue size, thereby maintaining a high throughput rate and good response times for jobs already in the queue. Once the queue fills up, clients get a server busy or HTTP 503 status code to try again later. Clients can retry the request at a later time, perhaps with exponential backoff.

Disadvantage(s): asynchronism

  • Use cases such as inexpensive calculations and realtime workflows might be better suited for synchronous operations, as introducing queues can add delays and complexity.

Source(s) and further reading

Communication


Source: OSI 7 layer model

Hypertext transfer protocol (HTTP)

HTTP is a method for encoding and transporting data between a client and a server. It is a request/response protocol: clients issue requests and servers issue responses with relevant content and completion status info about the request. HTTP is self-contained, allowing requests and responses to flow through many intermediate routers and servers that perform load balancing, caching, encryption, and compression.

A basic HTTP request consists of a verb (method) and a resource (endpoint). Below are common HTTP verbs:

Verb Description Idempotent* Safe Cacheable
GET Reads a resource Yes Yes Yes
POST Creates a resource or trigger a process that handles data No No Yes if response contains freshness info
PUT Creates or replace a resource Yes No No
PATCH Partially updates a resource No No Yes if response contains freshness info
DELETE Deletes a resource Yes No No

*Can be called many times without different outcomes.

HTTP is an application layer protocol relying on lower-level protocols such as TCP and UDP.

Source(s) and further reading: HTTP

Transmission control protocol (TCP)


Source: How to make a multiplayer game

TCP is a connection-oriented protocol over an IP network. Connection is established and terminated using a handshake. All packets sent are guaranteed to reach the destination in the original order and without corruption through:

If the sender does not receive a correct response, it will resend the packets. If there are multiple timeouts, the connection is dropped. TCP also implements flow control and congestion control. These guarantees cause delays and generally result in less efficient transmission than UDP.

To ensure high throughput, web servers can keep a large number of TCP connections open, resulting in high memory usage. It can be expensive to have a large number of open connections between web server threads and say, a memcached server. Connection pooling can help in addition to switching to UDP where applicable.

TCP is useful for applications that require high reliability but are less time critical. Some examples include web servers, database info, SMTP, FTP, and SSH.

Use TCP over UDP when:

  • You need all of the data to arrive intact
  • You want to automatically make a best estimate use of the network throughput

User datagram protocol (UDP)


Source: How to make a multiplayer game

UDP is connectionless. Datagrams (analogous to packets) are guaranteed only at the datagram level. Datagrams might reach their destination out of order or not at all. UDP does not support congestion control. Without the guarantees that TCP support, UDP is generally more efficient.

UDP can broadcast, sending datagrams to all devices on the subnet. This is useful with DHCP because the client has not yet received an IP address, thus preventing a way for TCP to stream without the IP address.

UDP is less reliable but works well in real time use cases such as VoIP, video chat, streaming, and realtime multiplayer games.

Use UDP over TCP when:

  • You need the lowest latency
  • Late data is worse than loss of data
  • You want to implement your own error correction

Source(s) and further reading: TCP and UDP

Remote procedure call (RPC)


Source: Crack the system design interview

In an RPC, a client causes a procedure to execute on a different address space, usually a remote server. The procedure is coded as if it were a local procedure call, abstracting away the details of how to communicate with the server from the client program. Remote calls are usually slower and less reliable than local calls so it is helpful to distinguish RPC calls from local calls. Popular RPC frameworks include Protobuf, Thrift, and Avro.

RPC is a request-response protocol:

  • Client program - Calls the client stub procedure. The parameters are pushed onto the stack like a local procedure call.
  • Client stub procedure - Marshals (packs) procedure id and arguments into a request message.
  • Client communication module - OS sends the message from the client to the server.
  • Server communication module - OS passes the incoming packets to the server stub procedure.
  • Server stub procedure - Unmarshalls the results, calls the server procedure matching the procedure id and passes the given arguments.
  • The server response repeats the steps above in reverse order.

Sample RPC calls:

GET /someoperation?data=anId

POST /anotheroperation
{
  "data":"anId";
  "anotherdata": "another value"
}

RPC is focused on exposing behaviors. RPCs are often used for performance reasons with internal communications, as you can hand-craft native calls to better fit your use cases.

Choose a native library (aka SDK) when:

  • You know your target platform.
  • You want to control how your "logic" is accessed.
  • You want to control how error control happens off your library.
  • Performance and end user experience is your primary concern.

HTTP APIs following REST tend to be used more often for public APIs.

Disadvantage(s): RPC

  • RPC clients become tightly coupled to the service implementation.
  • A new API must be defined for every new operation or use case.
  • It can be difficult to debug RPC.
  • You might not be able to leverage existing technologies out of the box. For example, it might require additional effort to ensure RPC calls are properly cached on caching servers such as Squid.

Representational state transfer (REST)

REST is an architectural style enforcing a client/server model where the client acts on a set of resources managed by the server. The server provides a representation of resources and actions that can either manipulate or get a new representation of resources. All communication must be stateless and cacheable.

There are four qualities of a RESTful interface:

  • Identify resources (URI in HTTP) - use the same URI regardless of any operation.
  • Change with representations (Verbs in HTTP) - use verbs, headers, and body.
  • Self-descriptive error message (status response in HTTP) - Use status codes, don't reinvent the wheel.
  • HATEOAS (HTML interface for HTTP) - your web service should be fully accessible in a browser.

Sample REST calls:

GET /someresources/anId

PUT /someresources/anId
{"anotherdata": "another value"}

REST is focused on exposing data. It minimizes the coupling between client/server and is often used for public HTTP APIs. REST uses a more generic and uniform method of exposing resources through URIs, representation through headers, and actions through verbs such as GET, POST, PUT, DELETE, and PATCH. Being stateless, REST is great for horizontal scaling and partitioning.

Disadvantage(s): REST

  • With REST being focused on exposing data, it might not be a good fit if resources are not naturally organized or accessed in a simple hierarchy. For example, returning all updated records from the past hour matching a particular set of events is not easily expressed as a path. With REST, it is likely to be implemented with a combination of URI path, query parameters, and possibly the request body.
  • REST typically relies on a few verbs (GET, POST, PUT, DELETE, and PATCH) which sometimes doesn't fit your use case. For example, moving expired documents to the archive folder might not cleanly fit within these verbs.
  • Fetching complicated resources with nested hierarchies requires multiple round trips between the client and server to render single views, e.g. fetching content of a blog entry and the comments on that entry. For mobile applications operating in variable network conditions, these multiple roundtrips are highly undesirable.
  • Over time, more fields might be added to an API response and older clients will receive all new data fields, even those that they do not need, as a result, it bloats the payload size and leads to larger latencies.

RPC and REST calls comparison

Operation RPC REST
Signup POST /signup POST /persons
Resign POST /resign
{
"personid": "1234"
}
DELETE /persons/1234
Read a person GET /readPerson?personid=1234 GET /persons/1234
Read a person’s items list GET /readUsersItemsList?personid=1234 GET /persons/1234/items
Add an item to a person’s items POST /addItemToUsersItemsList
{
"personid": "1234";
"itemid": "456"
}
POST /persons/1234/items
{
"itemid": "456"
}
Update an item POST /modifyItem
{
"itemid": "456";
"key": "value"
}
PUT /items/456
{
"key": "value"
}
Delete an item POST /removeItem
{
"itemid": "456"
}
DELETE /items/456

Source: Do you really know why you prefer REST over RPC

Source(s) and further reading: REST and RPC

Security

This section could use some updates. Consider contributing!

Security is a broad topic. Unless you have considerable experience, a security background, or are applying for a position that requires knowledge of security, you probably won't need to know more than the basics:

  • Encrypt in transit and at rest.
  • Sanitize all user inputs or any input parameters exposed to user to prevent XSS and SQL injection.
  • Use parameterized queries to prevent SQL injection.
  • Use the principle of least privilege.

Source(s) and further reading

Appendix

You'll sometimes be asked to do 'back-of-the-envelope' estimates. For example, you might need to determine how long it will take to generate 100 image thumbnails from disk or how much memory a data structure will take. The Powers of two table and Latency numbers every programmer should know are handy references.

Powers of two table

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

Source(s) and further reading

Latency numbers every programmer should know

Latency Comparison Numbers
--------------------------
L1 cache reference                           0.5 ns
Branch mispredict                            5   ns
L2 cache reference                           7   ns                      14x L1 cache
Mutex lock/unlock                           25   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
HDD 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 HDD     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

Handy metrics based on numbers above:

  • Read sequentially from HDD at 30 MB/s
  • Read sequentially from 1 Gbps Ethernet at 100 MB/s
  • Read sequentially from SSD at 1 GB/s
  • Read sequentially from main memory at 4 GB/s
  • 6-7 world-wide round trips per second
  • 2,000 round trips per second within a data center

Latency numbers visualized

Source(s) and further reading

Additional system design interview questions

Common system design interview questions, with links to resources on how to solve each.

Question Reference(s)
Design a file sync service like Dropbox youtube.com
Design a search engine like Google queue.acm.org
stackexchange.com
ardendertat.com
stanford.edu
Design a scalable web crawler like Google quora.com
Design Google docs code.google.com
neil.fraser.name
Design a key-value store like Redis slideshare.net
Design a cache system like Memcached slideshare.net
Design a recommendation system like Amazon's hulu.com
ijcai13.org
Design a tinyurl system like Bitly n00tc0d3r.blogspot.com
Design a chat app like WhatsApp highscalability.com
Design a picture sharing system like Instagram highscalability.com
highscalability.com
Design the Facebook news feed function quora.com
quora.com
slideshare.net
Design the Facebook timeline function facebook.com
highscalability.com
Design the Facebook chat function erlang-factory.com
facebook.com
Design a graph search function like Facebook's facebook.com
facebook.com
facebook.com
Design a content delivery network like CloudFlare figshare.com
Design a trending topic system like Twitter's michael-noll.com
snikolov .wordpress.com
Design a random ID generation system blog.twitter.com
github.com
Return the top k requests during a time interval cs.ucsb.edu
wpi.edu
Design a system that serves data from multiple data centers highscalability.com
Design an online multiplayer card game indieflashblog.com
buildnewgames.com
Design a garbage collection system stuffwithstuff.com
washington.edu
Design an API rate limiter https://stripe.com/blog/
Design a Stock Exchange (like NASDAQ or Binance) Jane Street
Golang Implementation
Go Implementation
Add a system design question Contribute

Real world architectures

Articles on how real world systems are designed.


Source: Twitter timelines at scale

Don't focus on nitty gritty details for the following articles, instead:

  • Identify shared principles, common technologies, and patterns within these articles
  • Study what problems are solved by each component, where it works, where it doesn't
  • Review the lessons learned
Type System Reference(s)
Data processing MapReduce - Distributed data processing from Google research.google.com
Data processing Spark - Distributed data processing from Databricks slideshare.net
Data processing Storm - Distributed data processing from Twitter slideshare.net
Data store Bigtable - Distributed column-oriented database from Google harvard.edu
Data store HBase - Open source implementation of Bigtable slideshare.net
Data store Cassandra - Distributed column-oriented database from Facebook slideshare.net
Data store DynamoDB - Document-oriented database from Amazon harvard.edu
Data store MongoDB - Document-oriented database slideshare.net
Data store Spanner - Globally-distributed database from Google research.google.com
Data store Memcached - Distributed memory caching system slideshare.net
Data store Redis - Distributed memory caching system with persistence and value types slideshare.net
File system Google File System (GFS) - Distributed file system research.google.com
File system Hadoop File System (HDFS) - Open source implementation of GFS apache.org
Misc Chubby - Lock service for loosely-coupled distributed systems from Google research.google.com
Misc Dapper - Distributed systems tracing infrastructure research.google.com
Misc Kafka - Pub/sub message queue from LinkedIn slideshare.net
Misc Zookeeper - Centralized infrastructure and services enabling synchronization slideshare.net
Add an architecture Contribute

Company architectures

Company Reference(s)
Amazon Amazon architecture
Cinchcast Producing 1,500 hours of audio every day
DataSift Realtime datamining At 120,000 tweets per second
Dropbox How we've scaled Dropbox
ESPN Operating At 100,000 duh nuh nuhs per second
Google Google architecture
Instagram 14 million users, terabytes of photos
What powers Instagram
Justin.tv Justin.Tv's live video broadcasting architecture
Facebook Scaling memcached at Facebook
TAO: Facebook’s distributed data store for the social graph
Facebook’s photo storage
How Facebook Live Streams To 800,000 Simultaneous Viewers
Flickr Flickr architecture
Mailbox From 0 to one million users in 6 weeks
Netflix A 360 Degree View Of The Entire Netflix Stack
Netflix: What Happens When You Press Play?
Pinterest From 0 To 10s of billions of page views a month
18 million visitors, 10x growth, 12 employees
Playfish 50 million monthly users and growing
PlentyOfFish PlentyOfFish architecture
Salesforce How they handle 1.3 billion transactions a day
Stack Overflow Stack Overflow architecture
TripAdvisor 40M visitors, 200M dynamic page views, 30TB data
Tumblr 15 billion page views a month
Twitter Making Twitter 10000 percent faster
Storing 250 million tweets a day using MySQL
150M active users, 300K QPS, a 22 MB/S firehose
Timelines at scale
Big and small data at Twitter
Operations at Twitter: scaling beyond 100 million users
How Twitter Handles 3,000 Images Per Second
Uber How Uber scales their real-time market platform
Lessons Learned From Scaling Uber To 2000 Engineers, 1000 Services, And 8000 Git Repositories
WhatsApp The WhatsApp architecture Facebook bought for $19 billion
YouTube YouTube scalability
YouTube architecture

Company engineering blogs

Architectures for companies you are interviewing with.

Questions you encounter might be from the same domain.

Source(s) and further reading

Looking to add a blog? To avoid duplicating work, consider adding your company blog to the following repo:

Under development

Interested in adding a section or helping complete one in-progress? Contribute!

  • Distributed computing with MapReduce
  • Consistent hashing
  • Scatter gather
  • Contribute

捐赠

捐赠 and sources are provided throughout this repo.

Special thanks to:

Contact info

Feel free to contact me to discuss any issues, questions, or comments.

My contact info can be found on my GitHub page.

License

I am providing code and resources in this repository to you under an open source license. Because this is my personal repository, the license you receive to my code and resources is from me and not my employer (Facebook).

Copyright 2017 Donne Martin

Creative Commons Attribution 4.0 International License (CC BY 4.0)

http://creativecommons.org/licenses/by/4.0/