前言: 本文概述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]