查看原文
其他

从 0 到 1400 万用户,3 名工程师如何撑起 Instagram?

CSDN 2023-12-12

Instagram,是 Meta 于 2010 年出的一款免费提供在线图片及视频分享的社群应用软件。在推出短短一年的时间里,Instagram 迅速“蹿红”,它的用户数量从 0 增长到了 1400 万。而在这背后,只有三名工程师在支撑。

Instagram 的成功,成为很多软件学习的楷模,那么它究竟是怎么做到的?背后运用了哪些技术栈?近日,一篇文章初探了其中的秘密。

来源:https://engineercodex.substack.com/p/how-instagram-scaled-to-14-million


翻译工具 | ChatGPT   责编 | 苏宓
出品 | CSDN(ID:CSDNnews)

以下为译文:

从 2010 年 10 月到 2011 年 12 月,Instagram 在短短一年多的时间里,用户数量从 0 增长到了 1400 万。他们仅仅依靠 3 名工程师实现了这一壮举。

他们之所以能够做到这一点,是因为遵循了 3 个关键原则并采用了可靠的技术堆栈。

Instagram 的指导原则:

1. 保持极度简单。

2. 不要重新发明轮子。

3. 在可能的情况下使用经过验证的、稳定的技术。

Instagram 背后的技术堆栈

早期的 Instagram 基础设施在 AWS 上运行,使用了带有 Ubuntu Linux 的 EC2。EC2 是亚马逊的一项服务,允许开发人员租用虚拟计算机。

为了简化说明,这里从工程师的角度来看用户会话的生命周期(下文标注为“Session:”),从而捋清楚 Instagram 所用到的一些技术。

前端

Session:用户打开 Instagram 应用。

Instagram 最初于 2010 年作为 iOS 应用推出。由于 Swift 于 2014 年发布,我们可以猜测 Instagram 是使用 Objective-C 以及其他如 UIKit 的组合技术来编写的。

负载均衡

Session:打开应用后,向后端发送请求以获取主要的动态照片,该请求将被发送到 Instagram 的负载均衡器。

Instagram 使用了亚马逊的弹性负载均衡器。工程师租用了 3 个 NGINX 实例,并根据它们的健康状态进行交替切换。

每个请求首先会被发送到负载均衡器,然后再路由到实际的应用服务器。

后端

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

Instagram 的应用服务器使用 Django 框架以及它是用 Python 编程语言编写的,并选择 Gunicorn 作为他们的 WSGI 服务器。

值得一提的是,WSGI(Web 服务器网关接口)将请求从 Web 服务器转发到 Web 应用程序。

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

这些应用服务器运行在超过 25 台亚马逊高性能 CPU 大型服务器上。由于服务器本身是无状态的,当需要处理更多请求时,他们可以添加更多服务器。

通用数据存储

Session:应用服务器意识到请求需要主要动态数据。为此,让我们假设它需要:

  • 最新相关的照片 ID

  • 与这些照片 ID 匹配的实际照片

  • 这些照片的用户数据。

数据库:Postgres

Session:应用服务器从 Postgres 中获取最新相关的照片 ID。

应用服务器会从存储了大部分 Instagram 数据的 PostgreSQL 中提取数据,包括用户和照片元数据。

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

由于 Instagram 收到的数据量很大(每秒超过 25 张照片和 90 个点赞),工程师对数据进行了分片。他们使用代码将数千个“逻辑”分片映射到少数物理分片上。

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

  • 用 41 位表示毫秒级时间(使用自定义时期,可提供 41 年的 ID)

  • 用 13 位表示逻辑分片 ID

  • 用 10 位表示自动递增序列,模数为 1024。这意味着我们可以在每个分片中每毫秒生成 1024 个 ID

由于在 Postgres 中使用可按时间排序的 ID,应用服务器已成功接收到最新相关的照片 ID。

照片存储:S3 和 Cloudfront

Session:应用服务器获取与这些照片 ID 匹配的实际照片,并使用快速 CDN 链接,以便为用户快速加载这些照片。

数千字节的照片存储在 Amazon S3 中。这些照片通过 Amazon CloudFront 迅速提供给用户。

缓存:Redis 和 Memcached

Session:为了从 Postgres 中获取用户数据,应用服务器(Django)使用 Redis 将照片 ID 与用户 ID 匹配。

Instagram 使用 Redis 存储了大约 3 亿张照片与创建它们的用户 ID 的映射,以便在获取主要动态数据、活动动态数据等时知道要查询哪个分片。所有的 Redis 都存储在内存中,以降低延迟,并分布在多台机器上。

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

为了知道要查询哪个 Postgres 分片,需要这种 photoID 到 user ID 的键-值映射。

Session:由于最近已经缓存响应,通过高效的 Memcached 缓存获取用户数据,从 Postgres 获取数据的速度很快。

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

有趣的事实:2 年后,即在 2013 年,Facebook 发布了一篇关于如何扩展 Memcached 以帮助他们处理每秒数十亿请求的重要论文。

Session:用户现在可以看到主页动态,其中包含他正在关注的人的最新照片。

主从设置

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

推送通知和异步任务

Session:现在,假设用户关闭了应用,但后来收到了一个朋友发布了一张照片的推送通知。

这个推送通知是使用 pyapns 发送的,以及 Instagram 发送出的十亿多条其他推送通知。Pyapns 是一个开源的通用苹果推送通知服务(APNS)提供商。

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

在后端,这个任务被推送到 Gearman,这是一个任务队列,用于分配适合的机器来处理工作。Instagram 拥有大约 200 个 Python 工作程序来消耗 Gearman 任务队列。

Gearman 被用于多个异步任务,比如向所有用户的粉丝(称为粉丝传播)推送活动信息(比如发布新照片)。

监控

Session:糟糕!Instagram 应用程序崩溃了,因为服务器上出现了错误,并发送了错误的响应。三名 Instagram 工程师立即收到警报。

Instagram 使用 Sentry,一个开源的 Django 应用程序,实时监控 Python 错误。

Munin 用于绘制系统范围的指标和警告异常。Instagram 有很多自定义的 Munin 插件来跟踪应用级别的指标,比如每秒发布的照片数量。

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

最终架构概述

推荐阅读:

▶ 余承东何小鹏隔空「互怼」,车圈大佬热议 AEB;马斯克的 AI 大模型来了;OpenAI 首届开发者大会被“剧透”|极客头条

李开复领队开源大模型 Yi,40万字上下文窗口破纪录

Gartner 2024 年十大战略技术趋势,半数与 AI 相关

继续滑动看下一个

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存