Haystack 太强了!存 2600 亿图片
作者 | 奇伢
來源 |?奇伢云存儲(chǔ)
小文件存儲(chǔ)
小文件存儲(chǔ),老生常談的問題。先聊聊小文件存儲(chǔ)重點(diǎn)關(guān)注的是什么?
以前我們提過,對于磁盤來說,小 io 吃 iops,大塊 io 吃吞吐。
劃重點(diǎn):小文件的重點(diǎn)是 io 次數(shù)。
為什么每次提到海量小文件的時(shí)候,總說傳統(tǒng)的文件系統(tǒng)不合適呢?
因?yàn)樗脑獢?shù)據(jù)操作太惹人眼球了。假設(shè)有 1K 的數(shù)據(jù),元數(shù)據(jù)如果搞個(gè) 1K ,這個(gè)開銷就太大了,空間大一倍,性能下降一倍。所以,只要是針對小文件的存儲(chǔ)優(yōu)化,基本上都會(huì)在元數(shù)據(jù)上下點(diǎn)功夫。
Haystack 的背景
Haystack 是 Facebook 為了解決他們圖片存儲(chǔ)而專門設(shè)計(jì)的一套存儲(chǔ)架構(gòu),2012 年發(fā)表論文《 Finding a needle in Haystack: Facebook’s photo storage 》。
文中提到當(dāng)時(shí)( 2012 年 )他們已經(jīng)有 2600 億張圖片,超過 20 PB 的數(shù)據(jù),用戶每周上傳 10 億張,大約 60 TB 的數(shù)據(jù)。
從這個(gè)數(shù)據(jù)量來看,確實(shí)談得上海量的文件。算出來的圖片平均大小 64K 左右吧,不大,就是以前普通圖片的大小。
64K 不知道怎么算的?
用 60 TB 除一個(gè) 10 億就知道了。
Haystack 的特點(diǎn)
接下來聊聊 Haystack 的設(shè)計(jì)到底有什么神奇特點(diǎn)呢?可以歸納下面四點(diǎn):
Write Once
Read Often
Nerver Modify
Rarely Deleted
大白話就是,只寫一次,從不更新,不定期會(huì)讀,極少刪除。這個(gè) Haystack 特點(diǎn)是適配 Facebook 的圖片場景的。
注意,是先有 facebook 的業(yè)務(wù)場景特點(diǎn),然后才把 Haystack 設(shè)計(jì)成這樣的。因果關(guān)系不要搞反了哦。
海量的文件的挑戰(zhàn)在哪里?
每一次文件存儲(chǔ)會(huì)涉及到元數(shù)據(jù)和數(shù)據(jù)兩部分的操作。當(dāng)數(shù)量是海量的時(shí)候,無論是對存儲(chǔ)容量和元數(shù)據(jù)的量都會(huì)帶來巨大的影響。
存儲(chǔ)容量這個(gè)自不用提,這是用戶的數(shù)據(jù),它是你必須要存儲(chǔ)的,通常這里考慮的是存儲(chǔ)效率,考慮用更少的介質(zhì)、更高的可靠性,來存儲(chǔ)更多的數(shù)據(jù),通常這里的選型是副本和糾刪碼。
元數(shù)據(jù)就有意思了,因?yàn)檫@個(gè)是內(nèi)部的設(shè)計(jì)導(dǎo)致的冗余數(shù)據(jù)(為了索引用戶數(shù)據(jù)而產(chǎn)生的數(shù)據(jù)),元數(shù)據(jù)的設(shè)計(jì)則會(huì)影響到用戶的體驗(yàn),特別是海量的場景。
童鞋思考個(gè)問題:海量、小文件 的前提下,為什么元數(shù)據(jù)會(huì)帶來挑戰(zhàn)?挑戰(zhàn)主要是哪些方面?
?1???存儲(chǔ)成本有挑戰(zhàn)
劃重點(diǎn):任何的評估不能脫離場景。
舉個(gè)簡單的例子,假如每個(gè)文件 1K ,每個(gè)文件對應(yīng)元數(shù)據(jù)也 1K ,這開銷大不大?
太大了嘛。一倍的浪費(fèi)。在海量的背景下,用戶存儲(chǔ) 1P 的數(shù)據(jù),就要存儲(chǔ) 1P 的元數(shù)據(jù),浪費(fèi)在元數(shù)據(jù)的成本無法容忍。
那元數(shù)據(jù)設(shè)計(jì)成 1K 的是錯(cuò)誤的嗎?
不一定。
比如說,如果是每個(gè)文件 1G,對應(yīng)每個(gè)元數(shù)據(jù) 1K 呢,這個(gè)開銷大不大?
不大,因?yàn)?1K/1G 才是 0.00009% ,也就是說,用戶存儲(chǔ) 1P 的數(shù)據(jù),元數(shù)據(jù)消耗為 0.092 TB ,這成本幾乎可以忽略。
所以,前提很重要,設(shè)計(jì)好壞并不是絕對的,都是相對而言的,任何架構(gòu)都要適配自己的場景。
?2???存儲(chǔ)性能有挑戰(zhàn)
接著上面的例子,每個(gè)文件 1K ,每個(gè)文件對應(yīng)元數(shù)據(jù)也 1K ,這性能開銷大不大?
太大了嘛。性能是一倍的損耗。每個(gè)文件 1K ,本該一次磁盤 IO 就能解決,但是另外還要加一次元數(shù)據(jù)操作的磁盤 IO 。也就是說磁盤極限如果 1 萬的 iops ,用戶只能獲取到 5000 的 iops 性能。內(nèi)部損耗一半。
那如果是每個(gè)文件 1G,對應(yīng)每個(gè)元數(shù)據(jù) 1K 呢,這個(gè)開銷大不大?
不大嘛,假設(shè)每筆 io 是 4K 的定長大小。1G 的數(shù)據(jù)寫 262144 次。只是多加一次元數(shù)據(jù) IO ,無關(guān)緊要。
?3???Hasystack 的突圍方向
劃重點(diǎn):小文件的場景,元數(shù)據(jù)的成本消耗和性能消耗會(huì)顯得更突出。再加上海量的前提下,這個(gè)是必須要解決的挑戰(zhàn)。
那 Haystack 應(yīng)該怎么做呢?兩個(gè)方面:
重新設(shè)計(jì)元數(shù)據(jù)結(jié)構(gòu),而不是使用文件系統(tǒng)的結(jié)構(gòu),要精簡元數(shù)據(jù)的大小;
削減元數(shù)據(jù)的 io 的次數(shù),甚至從 io 路徑上徹底消除元數(shù)據(jù)它;
你如果理解了上面的栗子,對于這兩個(gè)優(yōu)化方向的導(dǎo)出應(yīng)該也是水到渠成的。
Haystack 的目標(biāo)
高吞吐,低延遲
高可靠,具備故障容錯(cuò)能力;
架構(gòu)簡單,底成本
Haystack 的架構(gòu)設(shè)計(jì)
?1???整體架構(gòu)
Haystack 的架構(gòu)非常簡單,截取論文中的圖片:
圖中表明了三個(gè)核心組件:
Haystack Directory
Haystack Cache
Haystack Store
Store 就是一個(gè)單機(jī)的存儲(chǔ)引擎,上層告訴它寫哪,它就寫哪。管理的單位是一個(gè)個(gè)大塊文件。Haystack 里面叫做 Physical Volume ,其實(shí)就是一個(gè)個(gè)大文件而已啦。
劃重點(diǎn):Haystack 也是基于文件系統(tǒng)之上的。
Physical Volume 有一個(gè)閾值,比如寫滿 100 GB就不寫了。可以把它理解成一個(gè)大日志文件,數(shù)據(jù)的寫入方式也是 log 日志的方式,append 寫入。
Directory 是最上層的一個(gè)抽象,上面提到 Store 管理的是 Physical Volume ,上報(bào)到 Directory 組件,Directory 把這些底層的 Physical Volume 按照副本關(guān)系組織起來形成 Logical Volume 。Logical Volume 就是提供給用戶寫入數(shù)據(jù)用的。
舉個(gè)簡單的例子,如果是三副本的 Haystack 系統(tǒng),那么一個(gè) Logical Volume 由 3 個(gè) Physical Volume 組成副本鏡像。
Cache 這個(gè)就不用說了,就是一個(gè)單純的緩存組件。
?2???數(shù)據(jù)怎么組織
奇伢用幾個(gè)問題的形式來闡述數(shù)據(jù)的組織。
問題一:Physical Volume 是什么?
其實(shí)就是大文件,Haystack Store 是基于文件系統(tǒng)之上的。Physical Volume 就實(shí)現(xiàn)形式來講就是文件,可以是 ext4 的文件,也可以是 xfs 的文件。只不過這個(gè)文件有名字( Physical Volume ID ),也是一個(gè)閾值,比如 100 GB 。
問題二:Logical Volume 是什么?
抽象出來的結(jié)構(gòu)。由多個(gè) Physical Volume 組成。它的個(gè)數(shù)由副本數(shù)決定,比如一個(gè) 3 副本 Logical Volume 由 3 個(gè) Physical Volume 組成。
問題三:Physical Volume 內(nèi)部又是有什么構(gòu)成呢?
一個(gè)叫做 Needle 的東西。
Needle 其實(shí)就是用戶數(shù)據(jù)加一些頭部,加一些尾部構(gòu)成的一個(gè)整體結(jié)構(gòu)。Physical Volume 就是由這一個(gè)個(gè) Needle 組成的。
問題四:Needle 的頭尾有啥用?
主要幾個(gè)方面:
用來構(gòu)建元數(shù)據(jù)索引用的,里面有 key,size 等關(guān)鍵數(shù)據(jù);
用來校驗(yàn)數(shù)據(jù)是否損壞,里面有 magic,crc 等;
用來標(biāo)識(shí)數(shù)據(jù)是否刪除,里面有 Flags 標(biāo)記位;
這些頭尾數(shù)據(jù)就是 Haystack 給每個(gè)用戶對象重新設(shè)計(jì)的元數(shù)據(jù)了,相比文件系統(tǒng)的元數(shù)據(jù),這個(gè)太精簡了。
在內(nèi)存中的內(nèi)存表,甚至只需要一個(gè) 16 個(gè)字節(jié)就夠了,8 字節(jié)的 key ,4 字節(jié)的 offset,4 字節(jié)的 size 。這個(gè)比內(nèi)核文件系統(tǒng)動(dòng)輒幾百字節(jié)甚至幾 K 字節(jié)要好太多了。
問題四:元數(shù)據(jù)現(xiàn)在多大了?
元數(shù)據(jù)分為磁盤元數(shù)據(jù)(持久化了的)和內(nèi)存元數(shù)據(jù)。
磁盤元數(shù)據(jù)可以看上面的 Needle 結(jié)構(gòu)體,具體實(shí)現(xiàn)在 32 字節(jié)左右。內(nèi)存元數(shù)據(jù)可以控制在 16 個(gè)字節(jié)。
?3???讀、寫、刪
數(shù)據(jù)寫入的流程:
Web 接入點(diǎn)先去 Haystack Directory 選一個(gè) Logical Volume ;
把數(shù)據(jù)發(fā)往 Haystack Store ,寫到對應(yīng)的三個(gè) Physical Volume 即可(注意,append 寫入哦);
數(shù)據(jù)讀取的流程:
Web 接入點(diǎn)先去 Haystack Directory 拿到指定對象的元數(shù)據(jù);
然后請求發(fā)給 Haystack Store ,讀取數(shù)據(jù)(這里就不提 Haystack Cache 或者 CDN 的邏輯了,過于簡單);
數(shù)據(jù)刪除的流程:
Web 接入點(diǎn)先去 Haystack Directory 拿到指定對象的元數(shù)據(jù);
然后把刪除請求發(fā)給 Haystack Store ,就地更新 Needle 的標(biāo)記位,標(biāo)記成刪除;
劃重點(diǎn):Haystack 的刪除是就地更新,而不是 append 寫入。這里跟純粹的 log 文件不大一樣。 但由于刪除是極少的,所以就算不是 append 寫入,也不影響大局。
?4???空間回收
Haystack 也和 LSM,Bitcask 等設(shè)計(jì)類似,刪除是刪除,回收是回收,這是兩個(gè)步驟。
空間回收就是 Compact ,太簡單了,論文甚至都沒稀的提它,寥寥數(shù)語說了兩句,原文描述如下:
A Store machine compacts a volume file by copying needles into a new file while skipping any duplicate or deleted entries.
實(shí)現(xiàn)很簡單,和以前提過的 Compact 并無二樣。邏輯就是遍歷 Volume 文件,把重復(fù)的和標(biāo)記刪除了的 Needle 跳過,有效的 Needle 讀出來寫到新的地方,即可。
不一樣的思考
回想一下這個(gè)架構(gòu),思考一下它做到了它立的 flag 嗎?
?1???它的目標(biāo):高吞吐,低延遲,怎么實(shí)現(xiàn)的呢?
對于寫請求,全都化為 append 請求,極力的保持磁盤的順序性能。并且得益于 Needle 的設(shè)計(jì),Haystack 把數(shù)據(jù)和元數(shù)據(jù)放在一起,一次性落盤,相當(dāng)于省去了元數(shù)據(jù)的 IO 寫開銷。
當(dāng)然,這種設(shè)計(jì)也必然有代價(jià),由此帶來的代價(jià)就是加載時(shí)間變長。
對于讀請求,通過元數(shù)據(jù)的精簡,讓內(nèi)存 hold 住所有的元數(shù)據(jù),去除了元數(shù)據(jù)的 IO 開銷,這樣讀操作也就只剩用戶數(shù)據(jù)的 IO 。
注意:Haystack 刪除不是 append 哦,而是覆蓋寫,但之前已經(jīng)說過了,Haystack 的適用場景就是“極少刪除” 。
?2???高可靠,故障容錯(cuò)怎么實(shí)現(xiàn)的呢?
這個(gè)很簡單,通過副本冗余來做的。Volume 的組織邏輯放在 Directory 組件中,一份數(shù)據(jù)存儲(chǔ)多份,并且分散在不同的位置。當(dāng)其中一份故障,則只需要拷貝其他副本即可。
?3???畢竟 2012 年的論文,Haystack 的實(shí)踐過時(shí)了嗎?
論文中提到,Facebook 當(dāng)時(shí)的實(shí)踐是用 2U 的刀片服務(wù)器,48G 內(nèi)存,搭配 12 * 1TB 的 SATA 盤。
如果按照一個(gè)文件 64 KB 算,一個(gè) needle 內(nèi)存元數(shù)據(jù) 16 字節(jié)(這個(gè)很極限了),只需要 3 G 的內(nèi)存,單機(jī) 48 GB 的物理內(nèi)存應(yīng)對這整機(jī)的元數(shù)據(jù)確實(shí)綽綽有余。
但現(xiàn)在很多服務(wù)器已經(jīng)升級(jí)到 64 盤,單盤 16 TB,滿載的話需要 256 G 的內(nèi)存裝元數(shù)據(jù)。這個(gè)內(nèi)存配比就不大合適了,如果元數(shù)據(jù)再稍微大點(diǎn),就更不行了。
但話說回來,并不是每個(gè)人都用 64 盤 16 T 的高密服務(wù)器,所以并不能一概而論,還是要看自己的需求場景。
就算過去 10 年,我覺得它還能秀。
總結(jié)
Haystack 最核心的優(yōu)化是?重新設(shè)計(jì)元數(shù)據(jù)的結(jié)構(gòu),使得內(nèi)存元數(shù)據(jù)只有十幾個(gè)字節(jié),極大的減輕了負(fù)擔(dān),且設(shè)計(jì)的 Needle 結(jié)構(gòu)可以完整恢復(fù)內(nèi)存元數(shù)據(jù);
得益于元數(shù)據(jù)的精簡,Haystack 就能把單機(jī)全量元數(shù)據(jù)放在內(nèi)存;
讀的時(shí)候,元數(shù)據(jù)在內(nèi)存,只有用戶數(shù)據(jù)的 IO 消耗,極大的提高了性能;
寫的時(shí)候,得益于 Needle 的設(shè)計(jì),元數(shù)據(jù)更新操作不單獨(dú)刷,而是和用戶數(shù)據(jù)在一起刷,相當(dāng)于省掉了元數(shù)據(jù) IO 的開銷;
和 Bitcask 類似,為了提高內(nèi)存加載速度,也有索引(Index 文件)的實(shí)現(xiàn);
Haystack 并不過時(shí),可以結(jié)合自己的場景,煥發(fā)生機(jī);
往期推薦
為什么還有這么多的網(wǎng)絡(luò)故障?
k8s集群居然可以圖形化安裝了?
用了HTTPS,沒想到還是被監(jiān)控了
將 k8s 制作成 3D 射擊游戲,好玩到停不下來
點(diǎn)分享
點(diǎn)收藏
點(diǎn)點(diǎn)贊
點(diǎn)在看
總結(jié)
以上是生活随笔為你收集整理的Haystack 太强了!存 2600 亿图片的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Node18 即将支持 import H
- 下一篇: 华为汪涛:走向智能世界2030,无线网络