在2013年,約莫是我們插手Facebook一周年后,每個月有2億人利用Instagram并且我們存儲了200億照片。絕不躊躇的,我們開始了“Instagration”——從AWS處事器移動到Facebook的基本架構(gòu)。
兩年后,Instagram已經(jīng)生長為月活4億有400億照片和視頻的社區(qū),每秒處事高出100萬請求。為了保持對這種增長的支持和確保社區(qū)在Instagram上有一個靠得住的體驗,我們抉擇在地理上擴展我們的基本架構(gòu)。
本文將接頭為什么我們要將基本架構(gòu)從一個數(shù)據(jù)中心擴展到三個,和在擴展中碰著的一些技能挑戰(zhàn)。
念頭
Mike Krieger, Instagram的連系首創(chuàng)人和CTO,近期寫了一篇文章,文章中提到了一個故事,約莫在2012年的時候,弗吉尼亞州的一場颶風(fēng)癱瘓了快要一半的(處事器)實例。
在接下來的36小時里,這個小團隊重建了險些我們?nèi)康幕炯軜?gòu),這種體驗是他們永遠(yuǎn)不想反復(fù)的。
像這樣的自然災(zāi)害有大概對數(shù)據(jù)中心造成姑且的和永久的傷害——我們需要擔(dān)保在用戶體驗上有最小的損失。
其他的在地理上擴容的念頭包羅:
區(qū)域妨礙的規(guī)復(fù): 比自然災(zāi)害越發(fā)常見的是網(wǎng)絡(luò)短線、電力問題,等等。譬喻在我們擴展我們的處事到俄勒岡州不久,我們的一個基本構(gòu)件,包羅memecache和異步層處事器,被關(guān)機了,導(dǎo)致了用戶請求的大局限一場。
在我們的新架構(gòu)下,我們可以或許將流量從該區(qū)域轉(zhuǎn)移走,以減輕我們在從電力妨礙中規(guī)復(fù)時的問題。
彈性容量擴展: Facebook有不少數(shù)據(jù)中心。當(dāng)我們的基本架構(gòu)籌備好擴展到一個區(qū)域甚至當(dāng)網(wǎng)絡(luò)上有不小的延遲時,可以很是容易的將Instagram的容量擴展到所有可用的容量中。這輔佐我們快速抉擇為用戶籌備好新的成果而不消Scramble for基本架構(gòu)資源來支持他們。
從一到二
所以我們怎么開始這件工作的? 首先讓我們來看一下Instagram的整體基本架構(gòu)棧。
擴展到大都據(jù)中心的要害是區(qū)分全局?jǐn)?shù)據(jù)和局部數(shù)據(jù)。全局?jǐn)?shù)據(jù)需要在差異的數(shù)據(jù)中心間復(fù)制,而局部數(shù)據(jù)在每個區(qū)域大概差異(譬喻web處事器建設(shè)的異步任務(wù)應(yīng)該只在地址的區(qū)域被看到)。
下一個要思量的是硬件資源。這個可以大致的氣氛三中:存儲,計較緩和存。
存儲
Instagram主要是用兩種后端數(shù)據(jù)庫系統(tǒng):PostgreSQL和Cassandra。他們都有成熟的復(fù)制框架來很好的作為全局的一致數(shù)據(jù)存儲。
全局?jǐn)?shù)據(jù)整齊地映射到這些處事器上存儲的數(shù)據(jù)。方針是在差異的數(shù)據(jù)中心間保持這些數(shù)據(jù)的最終一致性,每一個區(qū)域有一個讀復(fù)制,來制止web處事器的跨數(shù)據(jù)中心讀。
可是,對PostgreSQL的寫入仍然夸數(shù)據(jù)中心,因為他們老是要寫到主處事集群上。
CPU處理懲罰
Web處事器,異步處事器都是無狀態(tài)的容易漫衍的計較資源,而且只需要會見當(dāng)?shù)財?shù)據(jù)。Web處事器可以建設(shè)異步事情,這些異步事情被異步動靜署理插手行列,然后被異步處事器消費,全都在一個區(qū)域。
緩存
緩存層是web處事器最常會見的層,而且它們需要在同一個數(shù)據(jù)中心中來制止用戶請求的延遲。這意味著對一個數(shù)據(jù)中心緩存的更新不會反應(yīng)到另一個數(shù)據(jù)中心中,因此對遷移到大都據(jù)中心建設(shè)了一個挑戰(zhàn)。
想象一個用戶在你的最新頒發(fā)的照片上評論。在一個數(shù)據(jù)中心的環(huán)境下,處事這個請求的web處事器可以僅僅在緩存中更新這個新評論。一個存眷者會從同一個緩存中看到這個新評論。
然而在大都據(jù)中心的情景下,假如評論者和存眷者被差異的區(qū)域處事,存眷者的區(qū)域緩存將不會被更新,這個用戶就不能看到評論。
我們的辦理要領(lǐng)是利用PgQ, 加強它使得插入緩存失效事件到被修改的數(shù)據(jù)庫中。
在主節(jié)點:
Web處事器插入一條評論到PostgreSQL數(shù)據(jù)庫中 Web處事器在同一個數(shù)據(jù)庫中插入一個緩存失效條目
在從節(jié)點:
復(fù)制主數(shù)據(jù)庫,包羅新插入的評論緩和存失效條目 緩存失效處理懲罰讀取緩存失效條目而且使區(qū)域緩存失效 Django集群從數(shù)據(jù)庫中讀到新插入的評論而且從頭填充緩存
這辦理了緩存一致性問題。另一方面,相對付單區(qū)域的例子,django處事器直接更新緩存而不從頭讀區(qū)數(shù)據(jù)庫,多區(qū)域時會增加數(shù)據(jù)庫的讀負(fù)載。
為了減輕這個問題,我們利用了兩種步伐:1) 通過冗余計數(shù)器淘汰每一個讀需要的計較資源;2) 通過緩存租約淘汰讀的數(shù)量。
冗余計數(shù)器
最常見的緩存鍵是計數(shù)器。譬喻,我們利用一個計數(shù)器來確定喜歡Justin Bieber的一個詳細(xì)的帖子的人數(shù)。
當(dāng)只有一個區(qū)域時,我們可以從web處事器增加memcache的計數(shù)器,所以制止一個“select count(*)”的數(shù)據(jù)庫挪用,這回節(jié)減幾百毫秒。
可是在有兩個區(qū)域和PgQ失效時,每一個新的喜歡對計數(shù)器建設(shè)了一個緩存失效事件。這會建設(shè)大量的“select count(*)”,尤其是在熱點工具上。