命中率80%,磁盤(pán)I/O減半,F(xiàn)lashcache的發(fā)展史
***版發(fā)布的3年后,F(xiàn)acebook開(kāi)源了新版Flashcache。對(duì)比舊版本,新版本緩存命中率由原來(lái)的60%提升到80%,磁盤(pán)讀寫(xiě)更減少了一半。 近日該公司數(shù)據(jù)庫(kù)工程師Domas Mituzas撰文盤(pán)點(diǎn)了Flashcache在Facebook的發(fā)展歷程,以下為譯文:
Flashcache 在 Facebook 的歷史
Facebook 于2010年***使用Fashcache。那時(shí),工程師仍在做基于SAS或SATA硬盤(pán)和完全基于閃存方案的選擇。然而,這兩個(gè)方案都不盡人意:2010年,SATA讀寫(xiě)慢,SAS需要很多硬盤(pán),而閃存的價(jià)格又居高不下。
其中一個(gè)可行的方法就是把我們的數(shù)據(jù)庫(kù)分成多層——一部分處理請(qǐng)求最多的數(shù)據(jù),這些層需要高性能的硬件設(shè)備做支撐,而在需求較少冷數(shù)據(jù)的處理上,性能低的設(shè)備也能跑起來(lái)。當(dāng)時(shí),這種方法在技術(shù)是可行的,因?yàn)槲覀兊臄?shù)據(jù)存取模式呈現(xiàn)為典型的Zipfian分布:即使我們使用了很多RAM緩存機(jī)制(memcache、TAO、InnoDB 緩沖池),通常熱數(shù)據(jù)的存取要高出普通數(shù)據(jù)10倍。但缺點(diǎn)是該方法卻相對(duì)復(fù)雜,依當(dāng)時(shí)的數(shù)據(jù)規(guī)模,額外增加復(fù)雜性顯然不是一個(gè)明智的選擇。

2010年,我們嗅到了從軟件層解決這個(gè)問(wèn)題的機(jī)會(huì)。于是評(píng)估了直接在InnoDB中為L(zhǎng)2緩存增加支持的可行性,結(jié)果發(fā)現(xiàn)為MySQL等設(shè)備加緩存效果會(huì)更理想。因此,選擇把Flashcache做成Linux內(nèi)核設(shè)備映射模塊,并大規(guī)模地將其部署到生產(chǎn)環(huán)境。
性能分析和優(yōu)化
在隨后的幾年中,系統(tǒng)的性能狀況發(fā)生了變化:借助InnoDB 的壓縮性能,我們存儲(chǔ)更多的邏輯數(shù)據(jù),它們通常要求較高的IOPS;隨后一些舊數(shù)據(jù)被遷移到其他層,并進(jìn)行了相應(yīng)的優(yōu)化,在不影響正常讀取的前提下盡可能使其少占空間。隨后因負(fù)載需求磁盤(pán)IO也不斷增加,某些服務(wù)器上的硬盤(pán)IO限制達(dá)到飽和。鑒于此,深入探究生產(chǎn)環(huán)境中的Flashcache的性能也被提上臺(tái)面,我們開(kāi)始查看性能進(jìn)一步提升的可能。
不同類型磁盤(pán)驅(qū)動(dòng)器運(yùn)行特性由多個(gè)因素決定,其中包括了硬盤(pán)轉(zhuǎn)速、磁頭速度以及每一轉(zhuǎn)所讀取的次數(shù)等。過(guò)去,SATA硬盤(pán)性能普遍不敵企業(yè)版SAS組件,因此,就像到了優(yōu)化軟件棧來(lái)提升系統(tǒng)性能。
雖然在很多情況下,“iostat”之類的工具對(duì)理解系統(tǒng)的整體性能有所幫助,但是卻無(wú)助于深層次的研究。這里使用了Linux的blktrace工具來(lái)跟蹤數(shù)據(jù)庫(kù)軟件發(fā)起的每一次請(qǐng)求,并分析閃存、硬件緩存機(jī)制如何處理這些請(qǐng)求。從而得到了3處可以提升的地方:讀寫(xiě)分布、緩存回收和高效地寫(xiě)操作。
1. 讀寫(xiě)分布
通過(guò)分析后發(fā)現(xiàn)寫(xiě)操作集中在硬盤(pán)上的少數(shù)區(qū)域,而讀操作分布很不均勻。我們?cè)贔lashcache中增加了更多的設(shè)備來(lái)監(jiān)控工作負(fù)載,以更好地測(cè)量緩存行為。從高層次上看,情況大抵是這樣的:

為了簡(jiǎn)化緩存維護(hù)操作,緩存設(shè)備被分割為許多大小為2M的單元,總體存儲(chǔ)中2M大小的部分線性映射到緩存。然而,這種架構(gòu)導(dǎo)致熱點(diǎn)表排列在相同的緩存單元上,冷表則占用了其它閑置的單元。(這與“生日悖論”沒(méi)有什么不同,“生日悖論”指的是與大多數(shù)人的期望相反的是——兩人生日是同一天的概率要達(dá)到50%的話,至少要有23個(gè)人。)
要解決這個(gè)問(wèn)題,要么是有好的配置算法能夠?qū)⑿K緩存考慮在內(nèi),或是增加某一單元內(nèi)的數(shù)據(jù)類型。經(jīng)過(guò)簡(jiǎn)單的策略調(diào)整后,果斷的選擇了后一個(gè)方案。
將硬盤(pán)端的相關(guān)數(shù)據(jù)從2M降至256K (使用RAID陣列)
將閃存端的相關(guān)數(shù)據(jù)從2M增加到16M(每單元為4096頁(yè)而不是512頁(yè))
用隨機(jī)哈希取代替線性映射
以上變動(dòng)將熱數(shù)據(jù)打散至更多的緩存區(qū)域。下圖顯示了這樣做帶來(lái)的好處:

變動(dòng)前,50%的緩存“貢獻(xiàn)”了80%的硬盤(pán)操作。而變動(dòng)后,同比例的緩存,硬盤(pán)操作僅為50%。
2. 緩存回收
在Facebook,數(shù)據(jù)庫(kù)服務(wù)器使用小型的邏輯塊——壓縮過(guò)的InnoDB表僅用4或8K,而未壓縮過(guò)的用16K大小的邏輯塊。用2M大小的緩存單元的話,各緩存回收算法,F(xiàn)IFO和LRU,并沒(méi)有明顯差別。z在增加Flashcache單元大小后,工作負(fù)載隨之改變,因此不得不開(kāi)始尋找FIFO的替代方案。
由于使用了blktrace子系統(tǒng)提供的跟蹤功能,因此不再需要實(shí)現(xiàn)整套機(jī)制來(lái)為不同的緩存回收算法的表現(xiàn)建模?;厥账惴ㄍǔ7浅:?jiǎn)單——因?yàn)樗鼈円芾硭薪?jīng)過(guò)緩存的動(dòng)作,它們不得不簡(jiǎn)單有效。用Python寫(xiě)的LRU裝飾器僅有不到20行代碼,加上中點(diǎn)插入功能不過(guò)是增加了15行代碼( 示例)。最終我們寫(xiě)了簡(jiǎn)單的模擬器來(lái)為回收算法在我們的數(shù)據(jù)集上的不同表現(xiàn)建模。我們發(fā)現(xiàn)帶中點(diǎn)插入功能的LRU較為有效——但是我們?nèi)匀恍枰_定LRU中的***中點(diǎn)以插入新讀入的數(shù)據(jù)塊。
我們發(fā)現(xiàn)被多次引用的數(shù)據(jù)塊由中點(diǎn)移到了LRU的頭部。如果在***次被讀取時(shí),把這些數(shù)據(jù)塊置于LRU的頭部,很多只讀一次的數(shù)據(jù)塊將會(huì)把讀操作更頻繁的頁(yè)面推出LRU。如果我們把它們置于LRU的中部,它們將處于第50百分位。如果我們把它們置于頭部,它們將處于0百分位。如圖所示,插入點(diǎn)至少要到第85百分位,緩存才有效。

這種行為是基于特定工作負(fù)載的,理解這一點(diǎn)有助于提升Flashcache的效率。當(dāng)前,我們使用Flashcache時(shí)是在第75百分位使用中點(diǎn)(實(shí)現(xiàn)為L(zhǎng)RU-2Q)插入單元。該設(shè)置有些保守,它允許25%的舊頁(yè)面存在,但仍然要比標(biāo)準(zhǔn)的LRU要出色,因?yàn)橹貥?gòu)、遷移等緩存行為在先前的建模中是沒(méi)有考慮在內(nèi)。
在Facebook,每臺(tái)機(jī)器上運(yùn)行多個(gè)數(shù)據(jù)庫(kù)實(shí)例,我們優(yōu)先選用運(yùn)行時(shí)間最長(zhǎng)的實(shí)例的舊表區(qū)域,對(duì)新表則謹(jǐn)慎對(duì)待。
3. 寫(xiě)操作的效率
另一個(gè)需要解決的問(wèn)題是寫(xiě)操作效率。Flashcache能夠充當(dāng)可靠的寫(xiě)入前高速緩存,對(duì)硬盤(pán)的很多寫(xiě)操作可以事先合并到閃存中。
之前,我們嘗試固定每緩存單元的臟頁(yè)占比。由于不同的緩存單元有不同的行為,在這種模型下,我們最終會(huì)為修改過(guò)的頁(yè)面配置underallocating或overallocating緩存。有些部分被不停地寫(xiě)入,有的臟頁(yè)被緩存一周,這嚴(yán)重影響了讀緩存。
為了解決這個(gè)問(wèn)題,我們實(shí)現(xiàn)了不再分離讀寫(xiě)操作的臟數(shù)據(jù)回收方法。所有的數(shù)據(jù)同等對(duì)待,如果緩存要重用一頁(yè)面,它只須查找LRU中最舊的那頁(yè)即可。如果最舊的頁(yè)面是臟的,緩存調(diào)用后臺(tái)的回收算法回收該頁(yè)面,重用次舊頁(yè)來(lái)緩存新數(shù)據(jù)。
在***化地保留寫(xiě)入前高速緩存的寫(xiě)-合并效率和速寫(xiě)能力的同時(shí),解決了寫(xiě)操作問(wèn)題。它還增加了可用于讀操作的空間,并從整體上提升了緩存效率。
未來(lái)工作
實(shí)現(xiàn)了以上三處改進(jìn),目光被投到未來(lái)的工作上。首先調(diào)整了元數(shù)據(jù)結(jié)構(gòu)來(lái)提升數(shù)據(jù)讀取的效率,但是要讓Flashcache支持下一代建立在TB級(jí)的緩存設(shè)備和硬盤(pán)存儲(chǔ)的系統(tǒng),仍然存在許多挑戰(zhàn)。為了支持多核CPU的并行數(shù)據(jù)讀取,細(xì)粒度鎖機(jī)制的開(kāi)發(fā)也正在進(jìn)行中。
同時(shí),雖然每G閃存的價(jià)格在下降,但離理想?yún)^(qū)間還有段距離。價(jià)格下降也對(duì)容量規(guī)劃帶來(lái)了挑戰(zhàn)。SSD寫(xiě)次數(shù)有限,這里還必須確保寫(xiě)的次數(shù)不會(huì)超過(guò)上限。將數(shù)據(jù)寫(xiě)入閃存時(shí),緩存的數(shù)據(jù)會(huì)丟失,所以使用太小的閃存設(shè)備存在隱患。在這種情況下,***使用轉(zhuǎn)速不要太快的硬盤(pán),因?yàn)槿魏尉彺鎸蛹?jí)取決于多層間的巨大的性能差距。
有了這些改進(jìn),F(xiàn)lashcache已經(jīng)成為Facebook軟件棧的構(gòu)建模塊。我們?cè)谛碌姆种吓艹汕先f(wàn)的服務(wù)器,其性能自flashcache-1系列有大幅提高。我們最繁忙的系統(tǒng)的讀操作I/O下降了40%,寫(xiě)操作I/O下降了75%。自此,高效地服務(wù)于10億用戶只須輕彈一內(nèi)核模塊。flashcache-3系列的代碼已經(jīng)提交到 GitHub。