Facebook圖片存儲(chǔ)架構(gòu)的學(xué)習(xí)
當(dāng)前位置:點(diǎn)晴教程→知識(shí)管理交流
→『 技術(shù)文檔交流 』
分享照片是Facebook上最流行的的功能之一。截至目前,用戶(hù)已經(jīng)上傳超過(guò)15億張照片,這使得Facebook成為最大的照片共享網(wǎng)站。對(duì)于每一個(gè)上傳的照片,F(xiàn)acebook都生成并存儲(chǔ)四個(gè)大小不同的圖像,從而轉(zhuǎn)化為共60億張照片,總?cè)萘砍^(guò)1.5PB。目前以每周220萬(wàn)新照片的速度增長(zhǎng),相當(dāng)于每周要額外增加25TB存儲(chǔ)。在高峰期每秒需要傳輸55萬(wàn)照片。這些數(shù)字對(duì)Facebook的照片存儲(chǔ)基礎(chǔ)設(shè)施的一個(gè)重大的挑戰(zhàn)。 舊的 NFS 照片架構(gòu) 老的照片系統(tǒng)架構(gòu)分以下幾個(gè)層:
因?yàn)槊繌堈掌家晕募问絾为?dú)存儲(chǔ),這樣龐大的照片量導(dǎo)致非常龐大的元數(shù)據(jù)規(guī)模,超過(guò)了 NFS 存儲(chǔ)層的緩存上限,導(dǎo)致每次請(qǐng)求上傳都包含多次I/O操作。龐大的元數(shù)據(jù)成為整個(gè)照片架構(gòu)的瓶頸。這就是為什么 Facebook 主要依賴(lài) CDN 的原因。為了解決這些問(wèn)題,他們做了兩項(xiàng)優(yōu)化: 因?yàn)槊繌堈掌家晕募问絾为?dú)存儲(chǔ),大量為目錄及文件在NFS 存儲(chǔ)層上產(chǎn)生了大量的元數(shù)據(jù), 這個(gè)規(guī)模的元數(shù)據(jù)量遠(yuǎn)遠(yuǎn)超過(guò)了超過(guò)了NFS 存儲(chǔ)層的緩存上限,導(dǎo)致每次招聘請(qǐng)求會(huì)上傳都包含多次I/O操作。龐大的元數(shù)據(jù)成為整個(gè)照片架構(gòu)的瓶頸。這就是為什么 Facebook主要依賴(lài) CDN 的原因。為了解決這些問(wèn)題,他們做了兩項(xiàng)優(yōu)化:
新的 Haystack 照片架構(gòu) 新的照片架構(gòu)將輸出層和存儲(chǔ)層合并為一個(gè)物理層,建立在一個(gè)基于HTTP 的照片服務(wù)器上,照片存儲(chǔ)在一個(gè)叫做haystack 的對(duì)象庫(kù),以消除照片讀取操作中不必要的元數(shù)據(jù)開(kāi)銷(xiāo)。新架構(gòu)中,I/O 操作只針對(duì)真正的照片數(shù)據(jù)(而不是文件系統(tǒng)元數(shù)據(jù))。haystack 可以細(xì)分為以下幾個(gè)功能層:
在下面的介紹中,我們會(huì)對(duì)于上述的每個(gè)功能層做詳細(xì)的講述。 存儲(chǔ)空間 Haystack 部署在商業(yè)存儲(chǔ)刀片服務(wù)器上,典型配置為一個(gè)2U的服務(wù)器,包含:
每個(gè)刀片服務(wù)器提供大約10TB的存儲(chǔ)能力,使用了硬件 RAID-6, RAID 6在保持低成本的基礎(chǔ)上實(shí)現(xiàn)了很好的性能和冗余。不佳的寫(xiě)性能可以通過(guò)RAID控制器和NVRAM緩存回寫(xiě)解決,寫(xiě)由于讀取大多是隨機(jī)的,NVRAM緩存是完全用于寫(xiě)入的。 文件系統(tǒng) Haystack 對(duì)象庫(kù)是建立在10TB容量的單一文件系統(tǒng)之上。 圖片讀取請(qǐng)求需要在讀取系統(tǒng)調(diào)用這些文件的位置偏移,但是為了執(zhí)行讀取操作,文件系統(tǒng)必須先找到實(shí)際物理卷上的數(shù)據(jù)。文件系統(tǒng)中的每個(gè)文件都被一個(gè)叫做inode結(jié)構(gòu)標(biāo)識(shí)。inode包含了一個(gè)磁盤(pán)上邏輯文件偏移和物理區(qū)塊偏移的映射。在使用的特殊類(lèi)型文件系統(tǒng)時(shí)大文件塊映射可能相當(dāng)大。 基于文件系統(tǒng)的區(qū)塊為給個(gè)邏輯區(qū)塊和大文件保存映射。這些信息通常不適合保存在inode的緩存中,而是存儲(chǔ)在在間接地址塊。所以在讀取文件的時(shí)候必須按照特定的流程。這里可以多個(gè)是間接地址塊,所以一個(gè)讀取會(huì)產(chǎn)生多個(gè)I/O取決于是否間接地址塊被緩存。 該系統(tǒng)只為連續(xù)范圍的區(qū)塊保持映射。一個(gè)連續(xù)的大文件的塊映射可以只由一個(gè)范圍的標(biāo)識(shí),這樣是適應(yīng)inode的系統(tǒng)需求的。但是,如果該文件是一個(gè)被切割的不連續(xù)的塊的話(huà),他的塊地圖可能非常的大。以上可以通過(guò)文件系統(tǒng)主動(dòng)為大的物理文件分配大塊的空間來(lái)減少碎片。 目前使用的文件系統(tǒng)為XFS,一個(gè)很大程度提供高效的文件預(yù)分配系統(tǒng)。 Haystack 對(duì)象存儲(chǔ) Haystack 是一個(gè)簡(jiǎn)單的日志結(jié)構(gòu)(只能追加),存儲(chǔ)著其內(nèi)部數(shù)據(jù)對(duì)象的指針。一個(gè) Haystack 包括兩個(gè)文件,包括指針和索引。下面的圖片將描述haystack存儲(chǔ)文件的布局: haystack最前面的8K存儲(chǔ)是被超級(jí)塊占用。緊隨超級(jí)塊是針,每針組成的一個(gè)頭部,數(shù)據(jù)和尾部: 一個(gè)針被他的 在haystack存儲(chǔ)文件中有每針相應(yīng)的的索引記錄,并且包含針?biāo)饕涗浀捻樞虮仨毢蚳aystack存儲(chǔ)文件相關(guān)的針的順序相匹配。按照規(guī)定索引文件的最低需求是找到一個(gè)特定的針在haystack存儲(chǔ)文件的元數(shù)據(jù)。載入和組織索引記錄到一個(gè)有效的查找數(shù)據(jù)結(jié)構(gòu)是Haystack程序的責(zé)任。索引文件是不是很關(guān)鍵,因?yàn)槿绻枰梢詮膆aystack存儲(chǔ)文件重建。索引的主要職責(zé)是讓針元數(shù)據(jù)無(wú)需通過(guò)較大的Haystack存儲(chǔ)文件,快速加載到內(nèi)存中。原因是其可以讓索引編程原來(lái)存儲(chǔ)的1%。 Haystack 寫(xiě)操作 Haystack 寫(xiě)操作同步將指針追加到 haystack 存儲(chǔ)文件,當(dāng)指針?lè)e累到一定程度,就會(huì)生成索引寫(xiě)到索引文件。由于索引文件是不是很關(guān)鍵,為了能有更快的性能所以采用異步的方式進(jìn)行寫(xiě)入。 為了降低硬件故障帶來(lái)的損失,索引文件還會(huì)定期寫(xiě)到存儲(chǔ)空間中。在崩潰或突然斷電的情況下,將haystack恢復(fù)處理器存儲(chǔ)中任何殘缺的針和截?cái)鄅aystack存儲(chǔ)中最后一個(gè)有效的針。接下來(lái),它會(huì)把丟失的針的索引記錄 寫(xiě)到haystack文件的最后。 Haystack不允許重寫(xiě)現(xiàn)有的針偏移,如果一個(gè)針數(shù)據(jù)需要被重寫(xiě),那么新版本必須使用相同的 Haystack 讀操作 傳到 haystack 讀操作的參數(shù)包括指針的偏移量,健,備用鍵,Cookie 以及數(shù)據(jù)大小。Haystack為數(shù)據(jù)大小添加頭部和尾部的長(zhǎng)度,然后根據(jù)數(shù)據(jù)尺寸從文件中讀取整個(gè)指針。讀取操作成功的關(guān)鍵就是作為參數(shù)傳遞的健,備用鍵,Cookie是否匹配,數(shù)據(jù)是否通過(guò)了校驗(yàn),并且針沒(méi)有被刪除掉。 Haystack 刪除操作 刪除操作比較簡(jiǎn)單 – 只需要在 Haystack 存儲(chǔ)的指針字段中的“刪除”位標(biāo)記一下即可。并且,相關(guān)的索引記錄不會(huì)做任何的修改。是最終的應(yīng)用程序引用到的是一個(gè)刪除的針。像這樣一個(gè)讀取刪除針的操作將會(huì)返回一個(gè)相應(yīng)的錯(cuò)誤給應(yīng)用程序。空間對(duì)已刪除的針不做任何的回收,只有這樣,才能使 haystack 的空間非常的緊湊。 照片存儲(chǔ)服務(wù)器 照片存儲(chǔ)服務(wù)器負(fù)責(zé)接受 HTTP 請(qǐng)求,并轉(zhuǎn)換成相應(yīng)的 Haystack 操作。為了盡量減少服務(wù)器檢索照片時(shí)的I/O操作,該服務(wù)器維護(hù)著全部 Haystack 中文件索引的緩存。服務(wù)器啟動(dòng)時(shí),系統(tǒng)就會(huì)將這些索引讀到緩存中。由于每個(gè)節(jié)點(diǎn)都有數(shù)百萬(wàn)張照片,必須保證索引的容量不會(huì)超過(guò)服務(wù)器的物理內(nèi)存。在內(nèi)存中僅需要保存查找照片所需的少量元數(shù)據(jù)即可。 對(duì)于用戶(hù)上傳的圖片,系統(tǒng)分配一個(gè)64位的獨(dú)立ID,照片接著被縮放成4種不同尺寸,每種尺寸的圖像擁有相同的隨機(jī) Cookie 和64位的密鑰,圖片尺寸描述(大,中,小,縮略圖)被存在代用key 中。接著上傳服務(wù)器通知照片存儲(chǔ)服務(wù)器將這些資料連同圖片存儲(chǔ)到 haystack 中。 每張圖片的索引緩存包含以下數(shù)據(jù): 由于Google的開(kāi)源 sparse hash data 結(jié)構(gòu)對(duì)于每個(gè)條目只有2bit的開(kāi)銷(xiāo),所以Haystack使用它來(lái)保證內(nèi)存中的索引緩存盡可能小。 照片存 儲(chǔ)的寫(xiě)/修改操作 寫(xiě)操作將照片數(shù)據(jù)寫(xiě)到 Haystack 存儲(chǔ)并更新內(nèi)存中的索引。如果該索引記錄中包含了相同的鍵,那么這是一次對(duì)現(xiàn)有的照片進(jìn)行修改的操作。并且只要修改索引記錄中的偏移來(lái)反應(yīng)新圖像在haystack存儲(chǔ)文件的位置。照片存儲(chǔ)始終假定,如果有重復(fù)的圖像(圖像具有相同的鍵),有較大的偏移量的那個(gè)存儲(chǔ)是有效的。 照片存儲(chǔ)的讀操作 傳遞給一個(gè)讀操作的參包括Haystack ID,照片的 Key, 尺寸以及 Cookie。服務(wù)器事先在緩存中按照照片的Key和所需文件的偏移進(jìn)行查找。如果找到了它,并向haystack發(fā)出讀取詞圖像的請(qǐng)求。按照上面說(shuō)的,haystack的刪除操作并不更新它的索引記錄,因此添加到內(nèi)存中的索引可以包含以前刪除的照片的內(nèi)容。當(dāng)閱讀以前的刪除的照片失敗后,系統(tǒng)將在內(nèi)存的索引中色繪制詞圖片的偏移量為0. 照片存儲(chǔ)的刪除操作 通知 Haystack 執(zhí)行刪除操作之后,內(nèi)存中的索引緩存會(huì)被更新,將偏移量設(shè)置為0,表示照片已被刪除。 重新整理(壓縮) 重新整理(壓縮)是一種回收刪除和重復(fù)的針(針使用相同的Key)的在線(xiàn)操作。它會(huì)通過(guò)復(fù)制針跳過(guò)任何重復(fù)或刪除的條目創(chuàng)建一個(gè)新的haystack。一旦此操作完成它就回去替換掉內(nèi)存中的文件和結(jié)構(gòu)。 HTTP 服務(wù)器 Http 框架使用的是簡(jiǎn)單的基于開(kāi)源的libevent庫(kù)的 evhttp 服務(wù)器。使用多線(xiàn)程,每個(gè)線(xiàn)程都可以單獨(dú)處理一個(gè) HTTP 請(qǐng)求。因?yàn)槲覀兊南到y(tǒng)消耗大多是I/O操作,HTTP服務(wù)器的性能并不很重要。 結(jié)束語(yǔ) Haystack 是一個(gè)基于 HTTP 的對(duì)象存儲(chǔ),包含指向?qū)嶓w數(shù)據(jù)的指針,該架構(gòu)消除了文件系統(tǒng)元數(shù)據(jù)的開(kāi)銷(xiāo),并實(shí)現(xiàn)將全部索引直接存儲(chǔ)到緩存,以最小的 I/O 操作實(shí)現(xiàn)對(duì)照片的存儲(chǔ)和讀取。 該文章在 2012/5/2 16:33:00 編輯過(guò) |
關(guān)鍵字查詢(xún)
相關(guān)文章
正在查詢(xún)... |