跳至正文

Instagram 如何在仅 3 名工程师的情况下扩展到 1400 万用户

Instagram 在 2010 年 10 月至 2011 年 12 月的短短一年多的时间内,用户量从 0 飙升到 1400 万,而这一切的背后只有三名工程师在工作。

这个惊人的数量增长来源于三大基本原则和稳定可靠的技术栈,以下是 Instagram 的指导原则与技术栈构成分析。

Instagram 在技术运作上一直遵循着以下三个指导原则:

  • 简洁为上
  • 避免重复发明轮子
  • 尽可能使用经过验证的、稳固的技术

技术栈简要介绍

Instagram 早期的基础架构运行于 AWS,使用的是配备 Ubuntu Linux 的 EC2。EC2 是 Amazon 提供的服务,允许开发者租用虚拟计算机承载工作负载。

为了更直观地展示,我们从工程师的角度,探讨用户会话的生命周期。(以 “会话” 为标记)

Instagram 的早期基础设施运行在 AWS 之上,使用 EC2 配合 Ubuntu Linux,EC2 是亚马逊提供的服务,允许开发人员租用虚拟计算机承载自家工作负载。

为了保证一切尽可能简单,这里用纯粹的工程师思维展开讨论,延着用户会话的生命周期捋顺整个流程:

前端

会话:用户打开 Instagram 应用。

Instagram 最初于 2010 年发布 iOS 版应用。由于 Swift 语言要到 2014 年才亮相,所以合理的猜测是 Instagram 是使用 Objective-C 和 UIKit 等方案组合编写而成。

负载均衡

会话:在应用开启之后,向后端发送一条获取主提要图像的请求,此请求随后抵达 Instagram 负载均衡器。

Instagram 采用亚马逊的 Elastic Load Balancer 服务。工程师们租用了 3 个 NGINX 实例,并根据其运行情况来决定何时切入和切出。

每条请求会首先抵达负载均衡器,而后再被路由至实际应用服务器。

后端

会话:负载均衡器将请求发送至应用服务器,而应用服务器负责保存正确处理请求所必需的逻辑。

Instagram 的应用服务器使用 Django、由 Python 编写,并选择 Gunicorn 作为其 WSGI 服务器。

这里解释一下,WSGI(Web 服务器网关接口)负责将请求从 Web 服务器转发至 Web 应用程序。

Instagram 使用 Fabric 同时在多个实例上并行运行命令,从而在几秒钟之内完成代码部署。

这一切共同运行在 25 台以上的亚马逊 High-CPU Extra-Large 超大设备之上。由于服务器本身保持无状态,所以在需要处理更多请求时,可以灵活添加更多计算资源。

通用数据存储

会话:应用服务器须识别出请求所需要的主提要数据,这里猜测它需要完成以下流程:

  1. 获取相关图像的最新 ID;
  2. 获取与这些 ID 相匹配的实际图像;
  3. 为这些图像获取用户数据。

数据库:Postgres

会话:应用服务器从 Postgres 处获取相关图像的最新 ID。

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

Postgres 和 Django 之间的连接,由 Pgbouncer 负责汇总成池。

由于收取到的数据量很大(每秒超过 25 张图像和 90 个赞),因此 Instagram 需要对数据进行分片。Instagram 依靠代码将数千个“逻辑”分片映射至数个物理分片。

Instagram 还面临着另一个有趣挑战,即如何生成可以按时间排序的 ID。他们生成的可按时间排序 ID 如下所示:

  • 用 41 位表示时间(以毫秒为单位,可在一条自定义 epoch 中表达 41 年间的所有 ID);
  • 用 13 位表示逻辑分片 ID;
  • 用 10 位表示自动递增序列,模数为 1024。这意味着我们可以每毫秒为每个分片生成 1024 个 ID。

借助 Postgres 中的可按时间排序 ID,应用服务器能够成功接收到相关图像的最新 ID。

图像存储:S3 与 CloudFront

会话:之后,应用服务器会获取与各图像 ID 相匹配的实际图像,并通过快速 CDN 链接为用户提供顺畅的加载体验。

Amazon S3 中存储有数以 TB 的图像。这些图像可通过 Amazon CloudFront 被快速交付给用户。

缓存:Redis 与 Memcached

会话:为了从 Postgres 处获取用户数据,应用服务器(Django)使用 Redis 将图像 ID 与用户 ID 进行匹配。

在 Redis 的支持下,Instagram 能够为约 3 亿张图像存储建立起指向创建者用户 ID 的映射,借此引导在获取主提要、活动提要等图像时具体应查询哪个分片。所有 Redis 都存储在内存内以降低延迟,并将数据分片至多台机器之上。

通过一系列巧妙的哈希处理,Instagram 得以在不到 5 GB 空间内存储这 3 亿个键映射。

由此建立的图像 ID 与用户 ID 的键值映射,用于指示具体应查询哪个 Postgres 分片。

会话:借助 Memcached 的高效缓存(最近响应均被纳入缓存),从 Postgres 处获取用户数据的速度很快。

对于常规缓存,Instagram 使用 Memcached。当时 Instagram 设置了 6 个 Memcached 实例,可以在 Django 上以相对简单的方式进行分层。

有趣的事实:两年之后的 2013 年,Facebook 发布了一篇具有里程碑意义的论文,介绍了他们如何扩展 Memcached 以顺利实现每秒数十亿条请求的处理能力。

会话:用户现在可以看到主页内容,其中展示的就是其所关注用户的最新图像。

主副本设置

Postgres 和 Redis 均在主副本设置中运行,并使用 Amazon EBS(Elastic Block Store)快照对系统进行频繁备份。

推送通知与异步任务

会话:现在,假设用户关闭了 Instagram 应用,但随后收到朋友发布新图像的推送通知。

与 Instagram 的其他推送通知一样,动态推送通知也是由 pyapns 负责发送。Pyapns 是一款开源、通用的苹果推送通知(APNS)提供方案。

会话:用户非常喜欢这张图像,并决定分享到 Twitter 那边。

在后端,这项任务会被推入任务队列 Gearman,它的功能就是把工作移交给更适合的其他设备。Instagram 拥有约 200 个 Python 工作线程,专供 Gearman 任务队列使用。

Gearman 用于执行多项异步任务,例如向所有用户的关注者推送新动态(例如发布的新图像,这项功能被称为 fanout)。

监控

会话:不好!Instagram 应用因为服务器发生故障、发出错误响应而遭遇崩溃。三名 Instagram 工程师立即收到了警报。

Instagram 使用开源 Django 应用 Sentry 来实时监控 Python 错误。

Munin 则用于整理系统范围内的指标并发出异常警报。Instagrm 设置有一大堆自定义 Munin 插件,用以跟踪应用层级的运行指标,例如每秒发布的图像数量。

Pingdom 负责进行外部服务监控,PagerDuty 则用于处理事件和通知。

Facebook 买下 Instagram

到 2012 年 3 月,Instagram 应用的用户群体已增长至约 2700 万。2012 年 4 月,Instagram 推出了 Android 版本,不到一天内下载量即突破 100 万次。当时,该公司还即将进行估值 5 亿美元的新一轮融资。顺带一提,Systrom 与 Facebook 创始人扎克伯格之前在斯坦福大学举办的活动上结识,并在 Instagram 迅速走红后一直保持着联系。

2012 年 4 月,Facebook(现更名为 Meta)提出以 10 亿美元现金加股票的价码收购 Instagram,同时承诺让 Instagram 继续保持独立管理。此后不久,就在 Instagram 即将进行首轮公开募股(IPO)之前,Facebook 成功凭借这一条件将其收入囊中。

Instagram 于 2012 年 11 月发布功能有所精简的网站版本。2014 年 6 月,面向 Amazon Fire 设备的版本正式发布。最后在 2016 年,这款已经在全球掀起热潮的照片分享应用终于出现在微软 Windows 平板电脑和 PC 端之上。

Instagram 为何能一炮而红?

尽管 Instagram 现已拥有大量功能,但其仍然牢牢把握着当初的设计原则:通过应用界面可直接创建免费账户,并轻松上传各种媒体素材(包括图像和视频)。之后,用户可以使用过滤器编辑上传的媒体内容,并配合位置信息和主题标签(即以 #号开头的单词或短语,可供社交媒体平台识别帖子所属的特定主题)进行组织。用户可以将个人资料设为公开或不可见,二者的区别在于:使用公开个人资料时,其他所有 Instagram 用户均可查看该用户的照片/视频;而使用不可见设置时,用户需要申请并获得批准后才能看到帖子内容。

Instagram 用户还可以搜索主题标签和位置来浏览其他用户的照片和视频。此外,用户可以滑动浏览随机热门内容,并通过为帖子“点赞”或添加评论等方式与其他用户的照片和视频进行交互。当有用户“关注”另一用户时,即可将后者的照片和视频转发到自己的动态当中。

Instagram 应用的首个版本仅允许用户以正方形长宽比(即图像宽度与高度间的比例关系)显示媒体,即图像的高度和宽度相同。也就是说,当时 Instagram 用户只能发布 2010 年时 iPhone 4 所支持的 640 像素宽度相匹配的媒体。这一设计直到 2015 年才有所变化,用户终于能够上传尺寸更大的媒体素材(最高 1080 像素)。

自首次推出以来,Instagram 又陆续添加了消息收发功能,并允许用户在同一帖子中展示多个图像或视频。

该应用最受欢迎的功能的之一就是“Instagram Stories”。通过此项功能,用户可以将照片和视频发布到应用内的独立内容源处。这类帖子只在发布后的 24 小时内向其他用户开放。据 Instagram 介绍,截至 2022 年,每天有 5 亿人使用 Instagram Stories 功能。

Instagram 提供的照片分享与评论功能营造出强烈的用户参与度和营销口碑,促使用户自发宣传、吸引好友和家人纷纷加入。其简洁的界面和顺手的功能也在市场上备受青睐。它允许用户通过滑动轻松浏览大量帖子,在一定程度上培养了受众的使用、乃至生活习惯。

尽管自 Meta(前 Facebook)收购以来,Instagram 的用户数量仍在持续增长,但这款应用本身的改进也变得乏善可陈。唯一延续下来的,就是简单直观的用户体验和对照片/视频共享功能的核心关注。尽管收购出价不菲,但对 Meta 来说,这 10 亿美元无疑是笔非常划算的买卖。

2019 年,市场研究公司 eMarketer 预测,到 2021 年 Instagram 用户数量将达到 1.172 亿。2018 年,Instagram 成为苹果应用商店中下载量第二大的免费应用(仅次于 YouTube 的免费移动端应用)。到 2020 年,Instagram 的月活用户规模正式突破 10 亿大关。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注