當前位置: 妍妍網 > 碼農

Instagram如何擴充套件支撐25億使用者的基礎架構?

2024-07-08碼農

前言: 本文概述Instagram如何擴充套件其基礎設施,主要基於筆者研究,可能與實際實踐情況有所差異。

從前,兩位史丹佛大學畢業生決客製作一款實作位置簽到功能的應用程式。然而,他們註意到,該套用中使用最頻繁的功能是「照片共享」,所以他們轉而建立了一款照片分享套用,並將其命名為Instagram。

隨著更多早期使用者加入,他們購買硬體來擴大規模,但擴充套件到一定程度後,垂直擴充套件的成本就會急劇增加,變得十分昂貴。

垂直擴充套件

然而,使用者增長飛速,在不到兩年時間內,該款套用已具備3000萬使用者,因此他們透過添加新伺服器來擴大規模。

水平擴充套件

雖然這種方式暫時解決了可延伸性問題,但超速增長又帶來了新的問題。

問題包括但不限於:

1.資源使用情況

配備更多硬體以便規模擴充套件,但是每台伺服器的最大容量並未被充分使用。

簡而言之,由於伺服器吞吐量不高,資源被浪費了。

2.數據一致性

為了處理大量流量,Instagram在世界各地建立了數據中心。

而數據一致性影響著使用者體驗良好與否,隨著數據中心數量增加,確保數據一致性變得越來越困難。

3.效能

Instagram的套用伺服器上執行Python,這意味著由於全域直譯器鎖(GIL),它們擁有行程而非執行緒,因而存在一些效能限制。

Instagram基礎設施

機智的Instagram工程師們用簡單的方式解決了這些難題,它們提供的極端可延伸性方式如下:

1.資源使用情況

Python很優雅,但C語言更快,因此它們用Cython和C/C++廣泛使用的穩定函式替換了它們,以此減少了CPU的使用率。

即使沒有購買昂貴的硬體來擴大規模,也減少了完成任務所需的CPU指令。

這意味著程式碼執行良好,從而增加了每台伺服器能夠處理的使用者數量。

共享記憶體 VS 私有記憶體

此外,伺服器上的Python行程數量受到可用系統記憶體的限制。同時,每個行程都有一段私有記憶體和一段可以存取共享記憶體的許可權。

這意味著,如果公共數據物件被移動到共享記憶體,則可以執行更多行程。

因此,如果單個副本足夠的話,它們就會將數據物件從私有記憶體移動到共享記憶體。

同時刪除未使用的程式碼,以減少記憶體中的程式碼量。

2.數據一致性

使用Cassandra支持Instagram使用者反饋。

每個Cassandra節點可以部署在不同的數據中心,並透過最終一致性實作同步。

然而,在不同大洲執行Cassandra節點會導致延遲更加嚴重,實作數據一致性更加困難。

使用獨立Cassandra集群實作最佳數據放置

因此,他們沒有為全世界執行一個Cassandra集群,而是為各大洲分別設定不同的集群。

這意味著歐洲的Cassandra集群將儲存歐洲使用者的數據。而美國的Cassandra集群將儲存美國使用者的數據。

換句話說,副本的數量並不等同於數據中心的數量。

然而,如果每個地區都有獨立的Cassandra集群,就存在宕機的風險。

將單個副本保存在另一個區域以備災

因此,他們在另一個區域保留了單個副本,並使用法定人數來路由請求,減少額外的延遲。

此外,他們還使用Akkio(譯者註:由Facebook開發的數據布局服務,即data placement service)來最佳化數據放置,Akkio將數據分割成具有強定位性的邏輯單元。

將Akkio想象成一種服務,它知道何時以及如何行動資料以降低延遲。

他們透過全域負載平衡器路由每個使用者請求。以下是他們為請求找到合適Cassandra集群的方法:

根據使用者請求尋找正確的Cassandra集群

  • 使用者向應用程式發送請求,但應用程式不知道使用者的Cassandra集群

  • 應用程式將請求轉發給Akkio代理

  • Akkio代理詢問緩存層

  • Akkio代理會在緩存未命中時與位置資料庫通訊。由於數據集較小,因此會在每個區域進行復制

  • Akkio代理將使用者的Cassandra集群資訊返回給應用程式

  • 應用程式根據響應直接存取正確的Cassandra集群

  • 應用程式緩存資訊以供後續請求

  • Akkio請求大約需要10毫秒,因此額外的延遲是可以忍受的。

    此外,如果使用者搬到另一大洲定居,他們還會遷移使用者數據。

    當使用者跨大洲移動時,數據遷移方式如下:

    當使用者遷移到另一大洲時的數據遷移

  • Akkio代理從生成的響應中知道使用者的Cassandra集群位置。

  • 他們會在存取資料庫中維護一個計數器,以此記錄了每個使用者從特定地區存取的次數。

  • 每次請求時,Akkio代理都會遞增存取資料庫計數器,可以根據IP地址找到使用者的確切位置。

  • 如果計數器超過限制,Akkio會將使用者數據遷移到另一個Cassandra集群。

  • 此外,他們還在PostgreSQL中儲存使用者資訊、好友關系和圖片後設資料。

    然而,他們收到的讀取請求卻多於寫入請求。

    擴充套件PostgreSQL

    因此,他們在領導者-追隨者復制拓撲中執行PostgreSQL,並將寫入請求路由到領導者,讀取請求則被路由到同一數據中心的跟隨者。

    3.效能

    套用層是同步的,必須等待外部服務做出響應。

    這意味著執行的CPU指令會減少,並且伺服器資源匱乏。

    同步執行與異步執行

    因此,他們使用Python異步IO與外部服務進行異步對話,並且,他們使用Python行程而不是執行緒。

    換句話說,如果一個請求需要更長時間才能完成,伺服器的容量就會被浪費。

    因此,如果一個請求的完成時間超過12秒,他們就會終止該請求。

    此外,他們還使用Memcache來保護PostgreSQL免受大量流量的影響,並將讀取請求路由到Memcache。

    Memcache用作鍵值儲存,每秒可處理數百萬個請求。

    然而為了降低延遲,他們不會跨數據中心復制Memcache。

    由另一個數據中心的緩存提供的陳舊數據

    因此存在數據過期的風險。

    例如,在一個數據中心收到對某張圖片的評論,對於另一個數據中心檢視同一圖片的人來說是看不見的。

    在更新PostgreSQL時使緩存失效

    因此,他們不會直接將數據插入Memcache。取而代之的是由一個單獨的服務來監視PostgreSQL更新,然後使Memcache失效。

    這意味著緩存失效後的第一個請求會被路由到PostgreSQL。

    然而,PostgreSQL存在超載的風險。

    例如,尋找熱門圖片獲得的點贊數可能會變得很昂貴:

    取而代之的是一個單獨的服務,它負責監視PostgreSQL的更新,然後使Memcache失效。

    這意味著緩存失效後的第一個請求會被路由到PostgreSQL。

    然而,PostgreSQL有超載的風險。

    例如,尋找熱門圖片獲得的點贊數可能會變得很昂貴:

    selectcount(*)fromuser_likes_mediawheremedia_id=42;

    因此,他們建立了非規範化表來處理昂貴的查詢:

    selectcountfrommedia_likeswheremedia_id=42

    這樣就能以更少的資源消耗提供更快的響應。

    但是,一次性失效所有緩存可能會給PostgreSQL帶來驚群問題(譯者註:Thundering herd problem,當事件發生時,大量等待該事件的行程或執行緒被喚醒,但只有一個行程能夠處理該事件,就會發生驚群問題。當行程被喚醒時,他們將各自嘗試處理該事件,但只有一個行程會獲勝。所有行程都會爭奪資源,可能會導致電腦當機,直到群體再次平靜下來)。

    因此,他們使用了Memcache租賃。

    Memcache租賃工作流程

    工作原理如下:

  • 第一個請求被路由到Memcache。但這不是普通的GET操作,而是租用GET操作。

  • Memcache將請求轉發給PostgreSQL,並要求客戶端等待。

  • 如果第一個請求尚未完成,Memcache會要求第二個請求等待。

  • Memcache提供過期數據作為第二個請求的替代選項。在大多數情況下,例如尋找圖片的點贊數,這就足夠了。

  • 對第一個請求的響應會更新Memcache。

  • 待處理的和較新的請求從Memcache獲取新數據。

  • 結語

  • 擴充套件應用程式需要持續努力。

  • 每一種架構決策都是一種權衡。

  • 而Instagram能夠憑借這些技術為25億使用者提供服務,這個例子說明Python和其他成熟的技術足以處理互聯網規模的流量。

    > > > >

    參考資料




  • Scaling Instagram Infrastructure

    https://www.youtube.com/watch?v=hnpzNAPiC0E

  • SREcon19 Asia/Pacific - Cross Continent Infrastructure Scaling at Instagram

    https://www.youtube.com/watch?v=IFPHQo-o6Vo

  • Open-sourcing a 10x reduction in Apache Cassandra tail latency

    https://instagram-engineering.com/open-sourcing-a-10x-reduction-in-apache-cassandra-tail-latency-d64f86b43589

  • What Powers Instagram: Hundreds of Instances, Dozens of Technologies

    https://instagram-engineering.com/what-powers-instagram-hundreds-of-instances-dozens-of-technologies-adf2e22da2ad

  • Managing data store locality at scale with Akkio

    https://engineering.fb.com/2018/10/08/core-infra/akkio/

  • Location-Aware Distribution: Configuring servers at scale

    https://engineering.fb.com/2018/07/19/data-infrastructure/location-aware-distribution-configuring-servers-at-scale/

  • Burbn - the early Instagram

    https://pg-designs.ca/burbn-the-early-instagram2/

  • How Instagram is scaling its infrastructure across the ocean

    https://opensource.com/article/18/10/instagram-scaled-infrastructure

  • How do threads work in Python, and what are common Python-threading-specific pitfalls?

    https://stackoverflow.com/questions/31340/how-do-threads-work-in-python-and-what-are-common-python-threading-specific-pit

  • Why should I use a thread vs. using a process?

    https://stackoverflow.com/questions/617787/why-should-i-use-a-thread-vs-using-a-process

  • What makes C faster than Python?

    https://stackoverflow.com/questions/13853053/what-makes-c-faster-than-python

  • 作者丨Neo Kim 編譯丨onehunnit

    來源丨newsletter.systemdesign.one/p/instagram-infrastructure?utm_source=profile&utm_medium=reader2

    *本文為dbaplus社群編譯整理,如需轉載請取得授權並標明出處! 歡迎廣大技術人員投稿,投稿信箱:[email protected]