想必大家都聽說過 Instagram ,它是全球最受歡迎的社交媒體平臺之一,擁有數(shù)十億的活躍用戶
Instagram 誕生于 2010 年,上線一周就坐擁 10 萬注冊用戶,一年之內(nèi)就擁有了 1400 萬用戶,可見擴張趨勢突飛猛進。
Instagram 誕生的時候只有 3 個工程師,想必大家對【他們怎么設計后端架構(gòu),使用了什么技術(shù)來支持這么多用戶】很感興趣吧
那么今天我們就來了解一下 Instagram 是如何在只有 3 名工程師的情況下擴展到 1400 萬用戶
原文:https://engineercodex.substack.com/p/how-instagram-scaled-to-14-million
圖片
從 2010 年 10 月到 2011 年 12 月,Instagram 的用戶在一年多的時間里從 0 增加到1400萬,關(guān)鍵是他們只有 3 個工程師
這聽起來是不是很不可思議。據(jù) Instagram 工程師透露,他們通過遵循下面 3 個關(guān)鍵原則并擁有可靠的技術(shù)棧來做到這一點:
- 讓事情變得非常簡單
- 不要重復造輪子
- 盡可能使用經(jīng)過驗證的可靠技術(shù)
技術(shù)棧
Instagram 早期的基礎設施運行在 AWS 上,使用 EC2 和 Ubuntu linux
EC2 是 Amazon 的云服務,它允許開發(fā)人員租用虛擬機
- 前端 App
Instagram 最初在 2010 年作為 IOS 應用程序推出。由于 Swift 在 2014 年才發(fā)布,那 Instagram 應該是使用 Objective-C 和 UIKit 等其他語言的組合來編寫的
- 負載均衡
Instagram 使用了 Amazon 的 Elastic 負載均衡器(Load Balancer)。他們有 3 個 Nginx 實例,Nginx 之間會進行健康檢查以此保證服務高可用
當用戶請求到來時,每個請求會先經(jīng)過負載均衡器,然后才被轉(zhuǎn)發(fā)到后端實際服務器
圖片
- 后端服務
圖片
Instagram 的應用程序服務器使用了 Django 框架,它是由 Python/ target=_blank class=infotextkey>Python 編寫的,而 Gunicorn 是它們的 WSGI 服務器
WSGI (Web Server Gateway Interface)全稱 web 服務器網(wǎng)關(guān)接口,它會將請求從 web 服務器轉(zhuǎn)發(fā)到 web 應用程序
在批量管理和自動運維方面,Instagram 通過 Fabric 同時在多個實例上面并行運行命令,做到幾秒鐘內(nèi)部署代碼
Fabric 是 Python 的一個模塊,基于 SSH 提供了豐富的交互接口,可以用來在本地或遠程機器上自動化的執(zhí)行 Shel l命令,非常適合用來做應用的遠程部署及系統(tǒng)維護
這些實例在超過25臺 Amazon High-CPU Extra-Large 機器上運行。由于服務器本身是無狀態(tài)的,如果需要處理更多請求時,便可以添加更多的機器
- 一般數(shù)據(jù)存儲
Instagram 使用了 PostgreSQL 來存儲數(shù)據(jù),應用程序服務器將從 PostgreSQL 中提取數(shù)據(jù),PostgreSQL 存儲了 Instagram 的大部分數(shù)據(jù),例如用戶和照片元數(shù)據(jù)
PostgreSQL 和 Django 之間的連接通過 pgbouncer
pgbouncer 是一個 PostgreSQL 連接池
任何目標應用程序都可以像連接 PostgreSQL 服務器一樣連接到 pgbouncer,并且 pgbouncer 將創(chuàng)建到實際服務器的連接,或者重用其現(xiàn)有的連接
Instagram 對用戶的數(shù)據(jù)進行了分片,即使用代碼將幾千個“邏輯”碎片映射到幾個物理碎片,因為收到的數(shù)據(jù)量很大(每秒超過 25 張照片和 90 個贊)
但是在將數(shù)據(jù)寫入這組服務器之前,Instagram 必須解決如何為數(shù)據(jù)庫中的每條數(shù)據(jù)分配ID(唯一標識符)的問題
下面則是 Instagram 中每條數(shù)據(jù) ID 包含的內(nèi)容:
- 41 位表示時間(以毫秒為單位)
- 13 位表示邏輯分片 ID
- 10 位表示自動遞增序列,模數(shù) 1024。這意味著我們可以在每毫秒內(nèi)為每個分片生成 1024 個id
Instagram 的數(shù)據(jù)分片和 ID 具體是怎么解決的小伙伴們可以看這篇文章:
https://instagram-engineering.com/sharding-ids-at-instagram-1cf5a71e5a5c
- 照片數(shù)據(jù)存儲
對于用戶的照片,Instagram 使用 Amazon S3 來存儲,并且使用 Amazon CloudFront 把照片快速提供給用戶
- 緩存
Instagram 使用 redis 將大約 3 億張照片映射到創(chuàng)建它們的用戶 ID 進行存儲,所有 Redis 都存儲在內(nèi)存中以減少延遲,并在多臺機器上進行分片。
通過一些巧妙的散列,Instagram 能夠在不到 5 GB 的內(nèi)存中存儲 3 億個鍵映射
對于常規(guī)緩存,Instagram 使用了 Memcached。他們當時有 6 個 Memcached 實例。Memcached 相對容易疊加在 Django 上
圖片
PostgreSQL 和 Redis 都使用了主從架構(gòu),并使用 Amazon EBS(彈性塊存儲)快照對系統(tǒng)進行頻繁備份
- 推送通知和異步任務
Instagram 使用 pyapns 來實現(xiàn),Pyapns 是一個開源的、通用的蘋果推送通知服務(APNS)提供商
在后端,任務被推送到 Gearman,這是一個任務隊列,將工作分配給更適合的機器。Instagram 有 大約 200 名 Python 工作者使用 Gearman 任務隊列
Gearman 常用于多個異步任務,例如向用戶的所有關(guān)注者推送活動(發(fā)布的新照片)
- 監(jiān)控
Instagram 使用開源 Django 應用程序 Sentry 來實時監(jiān)控 Python 錯誤
Munin 用于繪制系統(tǒng)范圍的指標并發(fā)出異常警報。Instagram 有一堆自定義的 Munin 插件來跟蹤應用程序級別的指標,例如每秒發(fā)布的照片
Pingdom 用于外部服務監(jiān)控,PagerDuty 用于處理事件和通知