Instagram 如何仅用 3 名工程师就扩展到 1400 万用户

Instagram 如何仅用 3 名工程师就扩展到 1400 万用户

从 2010 年 10 月到 2011 年 12 月,Instagram 在短短一年多的时间里从**0 增加到 1400 万用户。他们只用了 3 名工程师

他们通过遵循 3 个关键原则并拥有可靠的技术堆栈来做到这一点。

Instagram 的指导原则

  • 让事情变得非常简单。
  • 不要重新发明轮子。
  • 尽可能使用经过验证的可靠技术。

堆栈简单解释

早期 Instagram 的基础设施在 AWS 上运行,使用 EC2 和 Ubuntu Linux。 作为参考,EC2 是亚马逊的服务,允许开发人员租用虚拟计算机。

为了让事情变得简单,并且由于我喜欢从工程师的角度思考用户,**让我们回顾一下用户会话的生命周期。 **(标有“会话:”

### 前端

“会话:用户打开 Instagram 应用程序。”

Instagram 最初于 2010 年作为 iOS 应用程序推出。由于 Swift 于 2014 年发布,我们可以假设 Instagram 是使用 Objective-C 和 UIKit 等其他东西的组合编写的。

Instagram 如何仅用 3 名工程师就扩展到 1400 万用户_第1张图片

### 负载均衡

“会话:打开应用程序后,获取主提要照片的请求将发送到后端,并在那里到达 Instagram 的负载平衡器。”

Instagram 使用 Amazon 的弹性负载均衡器。 他们有 3 个 NGINX 实例,根据它们是否健康进行换入和换出。

每个请求首先到达负载均衡器,然后再路由到实际的应用程序服务器。

Instagram 如何仅用 3 名工程师就扩展到 1400 万用户_第2张图片

后端

Session:负载均衡器将请求发送到应用程序服务器,应用程序服务器保存正确处理请求的逻辑。

Instagram 的应用程序服务器使用 Django,它是用 Python 编写的,并使用 Gunicorn 作为其 WSGI 服务器。

回顾一下,WSGI(Web 服务器网关接口)将请求从 Web 服务器转发到 Web 应用程序。

Instagram 使用 Fabric 一次在多个实例上并行运行命令。 这允许在几秒钟内部署代码。

它们运行在超过 25 台 Amazon High-CPU 超大型机器上。 由于服务器本身是无状态的,当他们需要处理更多请求时,他们可以添加更多机器。

Instagram 如何仅用 3 名工程师就扩展到 1400 万用户_第3张图片

一般数据存储

会话:应用程序服务器发现请求需要主提要的数据。 为此,假设它需要:

1.最新的相关带照片身份证件
2. 与这些照片 ID 匹配的实际照片
3.“这些照片的用户数据。”

数据库:Postgres

“会话:应用程序服务器从 Postgres 获取最新的相关照片 ID。”

应用程序服务器将从 PostgreSQL 提取数据,该数据库存储了 Instagram 的大部分数据,例如用户和照片元数据。

Postgres 和 Django 之间的连接使用 Pgbouncer 进行池化。

Instagram 分片了他们的数据,因为他们收到的数据量很大(每秒超过 25 张照片和 90 个赞)。 他们使用代码将数千个“逻辑”分片映射到几个物理分片。

Instagram 面临并解决的一个有趣的挑战是生成可以按时间排序的 ID。 他们生成的可按时间排序的 ID 如下所示:

  • 41 位时间(以毫秒为单位)(为我们提供了 41 年的 ID 和自定义纪元)
  • 13位表示逻辑分片ID
  • 10 位表示自动递增序列,模数 1024。这意味着我们可以为每个分片、每毫秒生成 1024 个 ID
    Engineering.com/sharding-ids-at-instagram-1cf5a71e5a5c)。)

“得益于 Postgres 中可按时间排序的 ID,应用程序服务器已成功收到最新的相关照片 ID。”

照片存储:S3 和 Cloudfront

“会话:然后应用程序服务器获取与这些照片 ID 相匹配的实际照片以及快速 CDN 链接,以便为用户快速加载。”

Amazon S3 中存储了数 TB 的照片。 这些照片使用 Amazon CloudFront 快速提供给用户。

缓存:Redis 和 Memcached

“会话:为了从 Postgres 获取用户数据,应用程序服务器 (Django) 使用 Redis 将照片 ID 与用户 ID 进行匹配。”

Instagram 使用 Redis 来存储大约 将 3 亿张照片发送给创建它们的用户 ID,以便在获取主提要、活动提要等的照片时知道要查询哪个分片。所有 Redis 都存储在内存中以减少延迟,并且在多台机器上进行分片 。

通过一些巧妙的哈希处理,Instagram 能够在不到 5 GB 的空间中存储 3 亿个键映射。

为了知道要查询哪个 Postgres 分片,需要此 photoID 到用户 ID 键值映射。

“会话:由于使用 Memcached 进行高效缓存,从 Postgres 获取用户数据的速度很快,因为响应最近被缓存了。”

对于一般缓存,Instagram 使用 Memcached。 他们当时有 6 个 Memcached 实例。 Memcached 在 Django 上分层相对简单。

有趣的事实:两年后,即 2013 年,Facebook 发布了一篇具有里程碑意义的论文,介绍了他们如何扩展 Memcached 以帮助他们处理*数十亿 [每秒请求数。](https://research.facebook.com/publications/scaling-memcache- 在-facebook/)*

“会话:用户现在可以看到主页,其中填充了他所关注的人的最新照片。”

主副本设置

Postgres 和 Redis 都在主副本设置中运行,并使用 Amazon EBS(弹性块存储)快照来频繁备份系统。

推送通知和异步任务

“会话:现在,假设用户关闭应用程序,但随后收到朋友发布照片的推送通知。”

此推送通知是使用 pyapns 发送的,以及 Instagram 已经发送的超过十亿条其他推送通知。 Pyapns 是一个开源、通用的 Apple 推送通知服务 (APNS) 提供商。

`Session:用户非常喜欢这张照片! 所以他决定在推特上分享。

在后端,任务被推送到 Gearman,这是一个任务队列,它将工作外包给更适合的机器。 Instagram 有大约 200 个 Python 工作线程使用 Gearman 任务队列。

Gearman 用于执行多个异步任务,例如向所有用户的关注者推送活动(例如发布的新照片)(这称为扇出)。

监控

会议:呃哦! Instagram 应用程序崩溃是因为服务器出现错误并发送了错误的响应。 三名 Instagram 工程师立即收到警报。

Instagram 使用 Sentry(一款开源 Django 应用程序)来实时监控 Python 错误。

Munin 用于绘制系统范围的指标并发出异常警报。 Instagram 有一堆自定义 Munin 插件来跟踪应用程序级别的指标,例如每秒发布的照片。

Pingdom 用于外部服务监控,PagerDuty 用于处理事件和通知。

最终架构概述

订阅工程师法典以获取更多视觉架构分解! 就像早期的 Instagram 一样,我让事情变得非常简单。

资料来源:

  • Instagram 的动力:数百个实例,数十种技术
  • 在Redis中存储数亿个简单键值对
  • Instagram 上的分片 ID

你可能感兴趣的:(其他)