Instagram遷移第二部分:擴展基礎架構到多數據中心

jopen 9年前發布 | 12K 次閱讀 數據中心
 

【編者的話】本文介紹了Instagram從AWS遷移到非死book基礎架構的過程中面臨的由多數據中心帶來的挑戰和解決方法。

在2013年,大約是我們加入非死book一周年后,每個月有2億人使用Instagram而且我們存儲了200億照片。

毫不猶豫的,我們開始了“Instagration”——從AWS服務器移動到非死book的基礎架構。

兩年后,Instagram已經成長為月活4億有400億照片和視頻的社區,每秒服務超過100萬請求。

為了保持對這種增長的支持和確保社區在Instagram上有一個可靠的體驗,我們決定在地理上擴展我們的基礎架構。

本文將討論為什么我們要將基礎架構從一個數據中心擴展到三個,和在擴展中遇到的一些技術挑戰。

動機

Mike Krieger, Instagram的聯合創始人和CTO,近期寫了一篇 文章

,文章中提到了一個故事,大約在2012年的時候,弗吉尼亞州的一場颶風癱瘓了將近一半的(服務器)實例。

在接下來的36小時里,這個小團隊重建了幾乎我們全部的基礎架構,這種體驗是他們永遠不想重復的。

像這樣的自然災害有可能對數據中心造成臨時的和永久的傷害——我們需要保證在用戶體驗上有最小的損失。

其他的在地理上擴容的動機包括:

  • ** 區域故障的恢復: ** 比自然災害更加常見的是網絡短線、電力問題,等等。例如在我們擴展我們的服務到俄勒岡州不久,
    我們的一個基礎構件,包括memecache和異步層服務器,被關機了,導致了用戶請求的大規模一場。
    在我們的新架構下,我們能夠將流量從該區域轉移走,以減輕我們在從電力故障中恢復時的問題。
  • ** 彈性容量擴展: ** 非死book有不少數據中心。當我們的基礎架構準備好擴展到一個區域甚至當網絡上有不小的延遲時,
    可以非常容易的將Instagram的容量擴展到所有可用的容量中。這幫助我們快速決定為用戶準備好新的功能而不用Scramble for基礎架構資源來支持他們。

從一到二

所以我們怎么開始這件事情的? 首先讓我們來看一下Instagram的整體基礎架構棧。

擴展到多數據中心的關鍵是區分全局數據和局部數據。全局數據需要在不同的數據中心間復制,而局部數據在每個區域可能不同(例如web服務器創建的異步任務應該只在所在的區域被看到)。

下一個要考慮的是硬件資源。這個可以粗略的氛圍三中:存儲,計算和緩存。

存儲

Instagram主要是用兩種后端數據庫系統:PostgreSQL和Cassandra。他們都有成熟的復制框架來很好的作為全局的一致數據存儲。

全局數據整齊地映射到這些服務器上存儲的數據。目標是在不同的數據中心間保持這些數據的最終一致性,每一個區域有一個讀復制,來避免web服務器的跨數據中心讀。

但是,對PostgreSQL的寫入仍然夸數據中心,因為他們總是要寫到主服務集群上。

CPU處理

Web服務器,異步服務器都是無狀態的容易分布的計算資源,并且只需要訪問本地數據。Web服務器可以創建異步工作,這些異步工作被異步消息代理加入隊列,然后被異步服務器消費,全都在一個區域。

緩存

緩存層是web服務器最常訪問的層,并且它們需要在同一個數據中心中來避免用戶請求的延遲。這意味著對一個數據中心緩存的更新不會反映到另一個數據中心中,因此對遷移到多數據中心創建了一個挑戰。

想象一個用戶在你的最新發表的照片上評論。在一個數據中心的情況下,服務這個請求的web服務器可以僅僅在緩存中更新這個新評論。一個關注者會從同一個緩存中看到這個新評論。

然而在多數據中心的情景下,如果評論者和關注者被不同的區域服務,關注者的區域緩存將不會被更新,這個用戶就不能看到評論。

我們的解決方法是使用 PgQ , 增強它使得插入緩存失效事件到被修改的數據庫中。

在主節點:

  • Web服務器插入一條評論到PostgreSQL數據庫中
  • Web服務器在同一個數據庫中插入一個緩存失效條目

在從節點:

  • 復制主數據庫,包括新插入的評論和緩存失效條目
  • 緩存失效處理讀取緩存失效條目并且使區域緩存失效
  • Django集群從數據庫中讀到新插入的評論并且重新填充緩存

這解決了緩存一致性問題。另一方面,相對于單區域的例子,django服務器直接更新緩存而不重新讀區數據庫,多區域時會增加數據庫的讀負載。

為了減輕這個問題,我們使用了兩種辦法:1) 通過冗余計數器減少每一個讀需要的計算資源;2) 通過緩存租約減少讀的數量。

冗余計數器

最常見的緩存鍵是計數器。例如,我們使用一個計數器來確定喜歡Justin Bieber的一個具體的帖子的人數。

當只有一個區域時,我們可以從web服務器增加memcache的計數器,所以避免一個“select count(*)”的數據庫調用,這回節省幾百毫秒。

但是在有兩個區域和PgQ失效時,每一個新的喜歡對計數器創建了一個緩存失效事件。這會創建大量的“select count(*)”,尤其是在熱點對象上。

為了減少這些操作每一個需要的資源,我們對這個帖子的喜歡數量的計數器進行冗余(譯注:即在post的字段中加上likes的計數器,雖然是反范式的但帶來了性能提升)。當一個新的喜歡來到時,這個計數在數據庫中增加,因此,每個對這個計數的讀會變成一個更有效的簡單的select。

另一個在存儲喜歡這個帖子的人的同一個數據庫中進行冗余計數的好處是,更新可以被包含在一個事務中,似的這個更新總是原子的和一致的。雖然在改變前,緩存的計數器可能和數據庫中存儲的不一致,因為超時或重試等等原因。

Memcache租約

在上面來自Justin Bieber的新的帖子的例子中,在這個帖子的最初的幾分鐘,瀏覽和點贊的都會達到峰值。對每一個贊,計數器都從緩存中刪去。非常常見的情況是web服務器都嘗試從緩存中獲取同一個

計數器,但是會有“緩存未命中”發生。如果所有的這些web服務器都去數據庫服務器來獲取數據,將會導致驚群問題。

我們使用memcache租約機制來解決這個問題。它像這樣工作:

  • Web服務器發起一個“租約get”請求,不是通常的“get”請求到memcache服務器。
  • Memcache服務器在命中時返回命中的緩存值。在這種情況下和一個通常的“get”請求沒有區別。
  • 如果memcache服務器找不到對應的key,它在n秒內返回一個“首次未命中”給這段時間內請求的一個web服務器;這段時間內任何其他的“租約get”請求會得到一個“熱未命中”。
    在“熱未命中”的情況下,這個key最近從cache中刪除,它會返回過期的值。如果這個緩存的key在n秒內沒有被挺沖,它再次對一個“租約get”請求返回“首次未命中”。
  • 當一個web server收到“首次未命中”時,它進到數據庫中獲取數據并且填充緩存。
  • 當一個web server收到“熱未命中”和一個過期的值時,它可以使用這個值。如果它收到一個沒有值的“熱未命中”,它可以選擇等待緩存被“首次未命中”的web server填充。

總之,在以上的實現中,我們可以通過減少訪問數據庫的次數和每次訪問的資源來減少數據庫的負載。

這也提高了我們后端在一些熱計數器調出緩存時的可靠性,這種情形在Instagram的早期并非不常見。每次這種情形發生都會使得工程師趕忙手動修復緩存。在這樣的改變下,這些事故成為了老工程師的回憶。

從10ms延遲到60ms

目前為止,我們主要關注了當緩存變得有區域性之后的緩存一致性。數據中心之間的網絡延遲是另一個影響很多設計的挑戰。數據中心之間,一個60ms的網絡延遲可以導致數據庫復制的問題和web server更新數據庫的問題。我們需要解決以下問題來支持無縫擴展:

PostgreSQL 讀復制落后

當一個Postgres的主節點寫的時候,它生成增量日至。寫請求來的越快,這些日志生成的越頻繁。主節點們為從節點偶爾的需求存儲最近的日志文件,但是它們歸檔所有的日志到存儲中,來保證日志被保存

并且可以被任何需要更早的主節點保留的數據的從節點的訪問。這樣,主節點不會耗盡硬盤空間。

當我們創建一個新的讀復制時,讀復制開始讀主節點的一個快照。一旦完成,它需要應用從這個快照之后發生的日志。當所有的日志都應用之后,它會是最新的并且可以持續的同步主節點和服務web服務器的讀請求。

然而,當一個大數據庫的寫比率相當高時,在從節點和存儲設備中會有較多的網絡延遲,有可能日志被讀取的速率比日志創建的速率要慢,這樣從節點將會被落的越來越遠而且永遠都追不上。

我們的解決方案是在讀復制開始從主節點上傳輸基礎快照時就開啟第二個流來傳輸日志并存儲到本地磁盤上,當一個快照結束傳輸時,讀復制可以在本地讀區日志,使得恢復進程更加塊。

這不僅解決了我們在全美的數據庫復制問題,也使建造新的復制的時間減半。現在即使主節點和從節點在同一個區域,操作效率也很大程度的提高了。

總結

Instagram現在在全美運行了多個數據中心,給我們了更彈性的容量規劃和獲取,更高的可靠性,更好的為2012年發生的那樣的自然災害的準備。事實上,我們最近在一個計劃的“災難”中存活。非死book

規律性地測試它的數據中心,通過在訪問高峰的時候關閉它們。大約一個月前,我們剛剛完成遷移我們的數據到一個新的數據中心,非死book就運行了一個測試并且關停了這個數據中心。這是一個高風險

的模擬,但是幸運的是我們不被用戶注意到的度過了容量損失。Instagram遷移第二部分成功了!

原文鏈接: Instagration Pt. 2: Scaling our infrastructure to multiple data centers (翻譯:陳光)

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!