Instagram 僅 3 名工程師,如何做到 1400 萬用戶?

2023-10-30     51CTO

原標題:Instagram 僅 3 名工程師,如何做到 1400 萬用戶?

2010 年 10 月 6 日,舊金山。當人們還沉浸在擁有更強大攝像頭的 iPhone 4 的激動心情時,一款名為「 Instagram 」 的 iOS 照片分享應用出現在應用商店中。

當天就收穫了 2.5 萬首批用戶,一周之後,下載量攀升到 10 萬,從 2010 年 10 月到 2011 年 12 月,Instagram在短短一年多的時間裡,用戶數量從 0 增長到 1400 萬。

而他的創始人, Kevin Systrom 這期間用了 3 名工程師就做到了這一點。這就讓我們回到那個奇幻的時刻,從工程師的角度思考,一探他們是如何做到的。

簡單來說,他們通過如下遵循 3 個關鍵指導原則並擁有可靠的技術堆棧來做到這一點:讓事情變得非常簡單、不要重新發明輪子、儘可能使用經過驗證的可靠技術。

一、早期基礎配置

早期 Instagram 的基礎設施,是在 AWS 上運行的,使用 EC2 和 Ubuntu Linux。作為參考,EC2 是亞馬遜的服務,允許開發人員租用虛擬計算機。

為了讓事情變得簡單,並且由於我喜歡從工程師的角度思考用戶,所以讓我們回顧一下用戶場景會話的生命周期。

二、前端

場景回顧:用戶打開介面。

Instagram 最初於 2010 年作為 iOS 應用程式推出。由於 Swift 於 2014 年發布,我們可以假設 Instagram 是使用Objective-C 和 UIKit 等其他東西的組合編寫的。

三、負載均衡

場景回顧:打開應用程式後,獲取主訂閱源照片的請求會發送到後端,並在那裡到達Instagram的負載均衡器。

Instagram 使用亞馬遜的彈性負載均衡器。他們有 3 個 NGINX 實例,根據它們是否健康來換入和換出。

每個請求首先到達負載均衡器,然後再路由到實際的應用程式伺服器。

四、後端

場景回顧:負載均衡器將請求發送到應用程式伺服器,應用程式伺服器保存正確處理請求的邏輯。

Instagram 的應用伺服器使用Django ,用 Python 編寫,Gunicorn作為他們的 WSGI 伺服器。

回顧一下,WSGI(Web 伺服器網關接口)將請求從 Web 伺服器轉發到 Web 應用程式。

Instagram 使用Fabric同時在多個實例上並行運行命令。這允許在幾秒鐘內部署代碼。

它們運行在超過 25 台 Amazon High-CPU 超大型機器上。由於伺服器本身是無狀態的,當他們需要處理更多請求時,他們可以添加更多機器。

五、通用數據存儲

場景回顧:應用伺服器發現請求需要主提要的數據。為此,我們假設它需要:

  • 最新的相關照片ID
  • 與這些照片ID匹配的實際照片
  • 這些照片的用戶數據。

1.資料庫:Postgres

場景回顧: 應用伺服器從Postgres獲取最新的相關照片ID。

應用程式伺服器將從PostgreSQL中提取數據,PostgreSQL 存儲了 Instagram 的大部分數據,例如用戶和照片元數據。

Postgres 和 Django 之間的連接使用Pgbouncer進行池化。

Instagram由於收到的數據量很大(每秒超過 25 張照片和 90 個贊)而對他們的數據進行了分片。他們使用代碼將數千個「邏輯」分片映射到幾個物理分片。

Instagram 面臨並解決的一個有趣的挑戰是生成可以按時間排序的 ID。他們生成的可按時間排序的 ID 如下所示:

  • 41 位時間(以毫秒為單位)(提供了 41 年的 ID 和自定義紀元)
  • 13位代表邏輯分片ID
  • 10 位表示自動遞增序列,模數 1024。這意味著我們可以為每個分片、每毫秒生成 1024 個 ID

場景回顧:由於Postgres中的可按時間排序的ID,應用伺服器已成功接收到最新的相關照片ID。

2.照片存儲:S3 和 Cloudfront

場景回顧: 然後,應用伺服器通過快速CDN連結獲取與這些照片ID匹配的實際照片,以便為用戶快速加載。

Amazon S3中存儲了數 TB 的照片。這些照片已使用 Amazon CloudFront快速提供給用戶。

3.緩存: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 以幫助他們每秒處理數十億個請求。

用戶現在可以看到主頁,裡面有他關注的人的最新照片。

4.主副本設置

Postgres 和 Redis 都在主副本設置中運行,並使用 Amazon EBS(彈性塊存儲)快照來頻繁備份系統。

六、推送通知和異步任務

場景回顧:現在,假設用戶關閉了應用程式,但隨後收到朋友發布照片的推送通知。

此推送通知是使用pyapns發送的,與 Instagram 已經發送的其他十億多條推送通知一起。Pyapns 是一個開源、通用的 Apple 推送通知服務 (APNS) 提供商。

場景回顧:用戶非常喜歡這張照片!所以他決定在Twitter上分享。

在後端,任務被推送到Gearman中,這是一個任務隊列,它將工作外包給更適合的機器。Instagram 有大約 200 個 Python 工作線程使用 Gearman 任務隊列。

Gearman 用於執行多個異步任務,例如向所有用戶的關注者推送活動(例如發布的新照片)(這稱為扇出)。

七、監控

場景回顧:Instagram應用程式因伺服器出現錯誤而崩潰,並發送了錯誤響應。Instagram的三名工程師立即得到了提醒。

Instagram 使用Sentry (一款開源 Django 應用程式)來實時監控 Python 錯誤。

Munin用於繪製系統範圍的指標並發出異常警報。Instagram 有一堆自定義 Munin 插件來跟蹤應用程式級別的指標,例如每秒發布的照片。

Pingdom用於外部服務監控,PagerDuty用於處理事件和通知。

八、最終架構一覽

——後記——

Instagram發布的19個月,後活躍用戶數量超過5000萬,活躍用戶數量達到1億,2012年6月份達到1.3億。同年10月25日,當時的Facebook以總值7.15億美元收購Instagram,創始人Kevin從中獲得了4億美元的回報。

值得一提的是,於編程而言,Kevin是自學成才。管理學科出身的他,剛畢業時可謂是一張白紙,在社交旅遊網站Nextstop營銷部門工作時,凱文開始每晚抽時間自學編程。

Instagram 的成功帶來的不僅僅創造了當代矽谷最偉大的成功故事之一,Kevin的自學成才的歷程成為了激烈開發者們對於編程的熱情。

文章來源: https://twgreatdaily.com/zh-mo/c252c5d73d3a07de00407070da28f96e.html