• Instagram为什么靠3个程序员就能撑起1400万的用户?
  • 发布于 2个月前
  • 257 热度
    0 评论
  • 望北海
  • 0 粉丝 24 篇博客
  •   
Instagram 在 2010 年 10 月至 2011 年 12 月的短短一年多的时间内,用户量从 0 飙升到 1400 万。而这一切的背后只有三名工程师在工作。他们的成功归功于遵循三大核心原则以及他们的稳固技术栈。

Instagram 的三大核心原则:
1.简洁为上。
2.避免重复发明轮子。
3.尽可能使用经过验证的、稳固的技术。

一.简易解释技术栈
Instagram 早期的基础架构运行在 AWS 上,使用的是配备 Ubuntu Linux 的 EC2。EC2 是 Amazon 的服务,允许开发者租用虚拟计算机。为了更直观地展示,让我们从工程师的角度来探讨一个用户会话的生命周期。(以 “会话” 为标记)

前端
会话:用户启动 Instagram 应用程序。
2010 年,Instagram 首次作为 iOS 应用推出。考虑到 Swift 是在 2014 年发布的,我们可以认为 Instagram 最初是使用 Objective-C 配合 UIKit 等技术编写的。

负载均衡
会话:在打开应用之后,为获取首页的图片流,一个请求被发送至后端,并首先接触到 Instagram 的负载均衡器。
Instagram 采用了 Amazon 的 Elastic Load Balancer,配置了三个 NGINX 实例,这些实例会根据其运行状况进行切换。
每一个发向后端的请求都会首先到达负载均衡器,然后被定向至真正的应用服务器。

后端

会话:经过负载均衡器处理后,请求被传送至应用服务器,该服务器包含了处理请求的核心逻辑。
Instagram 的应用服务器是基于 Django 并使用 Python 语言编写,而 Gunicorn 则作为其 WSGI 服务器。
再简说下,WSGI(Web Server Gateway Interface)是一个协议,负责将请求从 Web 服务器转发到 Web 应用程序。
Instagram 采用 Fabric 工具,在多个实例上并行地执行命令,这使得他们能够在几秒内迅速部署代码。

这些服务器都运行在 25 台以上的 Amazon High-CPU Extra-Large 机型上。因为这些服务器是无状态的,当面对更多请求时,他们可以简单地增加更多机器来扩展处理能力。

常规数据存储
会话:应用服务器发现请求需要主要的动态数据。它可能需要以下信息:
.最近相关的照片 ID
.对应这些照片 ID 的实际照片
.这些照片的用户数据

数据库:Postgres
会话:应用服务器从 Postgres 中提取最新相关的照片 ID。
应用服务器从 PostgreSQL 数据库中提取数据,其中包括大部分 Instagram 的数据,例如用户和照片的元数据。
Instagram 使用 Pgbouncer 对 Postgres 和 Django 之间的连接进行池化。
鉴于他们每秒收到超过 25 张照片和 90 个赞,Instagram 采用了数据分片技术。他们利用代码将数千个 “逻辑” 分片映射到少数物理分片。

Instagram 成功解决了一个有趣的挑战:如何生成可以按时间排序的 ID。最终的 ID 格式如下:
. 41 位用于毫秒级时间(这为我们提供了 41 年的 ID 空间)
. 13 位代表逻辑分片 ID
. 10 位代表自增序列,模为 1024,意味着我们每毫秒可以为每个分片生成 1024 个 ID

感谢 Postgres 中可按时间排序的 ID,应用服务器成功获取了最新相关的照片 ID。

照片存储:S3 和 Cloudfront
会话:随后,应用服务器使用快速的 CDN 链接获取与那些照片 ID 匹配的实际照片,确保用户快速加载。

数以 TB 计的照片被存储在 Amazon S3 中,并通过 Amazon CloudFront 快速地提供给用户。


缓存:Redis 和 Memcached
会话:为了从 Postgres 中获取用户数据,应用服务器(Django)使用 Redis 将照片 ID 与用户 ID 相匹配。
Instagram 用 Redis 存储了大约 3 亿张照片到用户 ID 的映射,以确定在获取主要动态或其他动态时应查询哪个数据分片。为减少延迟,整个 Redis 都存储在内存中,并在多个机器上进行了分片。

利用精妙的哈希技术,Instagram 只需不到 5GB 的空间就可以存储 3 亿个键映射。
这个照片 ID 到用户 ID 的键值映射是为了确定应该查询哪个 Postgres 分片。
会话:得益于 Memcached 的高效缓存,从 Postgres 获取的用户数据非常迅速,因为这个响应最近已被缓存。
对于普通的缓存需求,Instagram 使用了 Memcached,并拥有 6 个 Memcached 实例。在 Django 上加入 Memcached 是相对简单的。
有趣的是,两年后,即 2013 年,Facebook 发布了一篇论文,描述了他们如何扩展 Memcached 以应对每秒数十亿的请求。
会话:现在,用户可以看到其首页动态,其中填充了他关注的人的最新图片。

主 - 从架构

Postgres 和 Redis 都采用了主 - 从架构,并使用 Amazon EBS(弹性块存储)进行频繁的系统备份。

二.推送通知与异步任务
会话:现在,假设用户关闭了应用,但随后收到了一个推送通知,告知他的朋友上传了一张新照片。

这个推送通知是通过 Pyapns 发送的。至今,Instagram 已经通过它发送了超过十亿的推送通知。Pyapns 是一个开源的,用于 Apple Push Notification Service(APNS)的通用提供器。

会话:用户非常喜欢这张照片!因此,他决定将其分享至 Twitter。
在后端,这项任务被推送至 Gearman,这是一个任务队列系统,可以将任务分派给更加合适的机器来处理。Instagram 拥有约 200 个 Python 工作进程来处理 Gearman 的任务队列。

Gearman 被用于处理多种异步任务,例如将活动(如新的照片发布)推送给用户的所有粉丝(这个过程叫做 “扇出”)。

三.监控

情境:糟糕!Instagram 应用程序因服务器出错而崩溃,这导致了一个错误的响应被发送出去。三位 Instagram 的工程师立刻收到了报警。
Instagram 采用了 Sentry,这是一个开源的 Django 应用,用于实时追踪 Python 的错误。
他们使用 Munin 来对整个系统的指标进行绘图并对异常进行警告。Instagram 还定制了许多 Munin 的插件,以便追踪应用级的指标,如每秒上传的照片数。
为了对外部服务进行监控,他们选择了 Pingdom。而当发生意外情况和需要发送通知时,他们会使用 PagerDuty。

四.架构总览

用户评论