原作者:Davies(來(lái)自豆瓣)
原文發(fā)表于:https://www.douban.com/note/637760886/
我和存儲(chǔ)的故事要從 10 年前在豆瓣的工作開(kāi)始。 2007 年的 8 月鼻忠,那會(huì)豆瓣還只有 4 臺(tái)機(jī)器万细,支撐每日三百多萬(wàn)的? PV ,存儲(chǔ)也用的是單機(jī)的本地存儲(chǔ),條目的照片按照類(lèi)別放在一個(gè)目錄里,一百多萬(wàn)的小文件,即使用了對(duì)小文件支持很好的? reiserfs 笨农,也已經(jīng)沒(méi)辦法用 ls 或者 rsync 來(lái)訪問(wèn)或者備份了。 Web? 服務(wù)器是? Lighttpd 帖渠,配置了合適的緩存策略谒亦,在沒(méi)有任何 CDN 緩存的情況下勉強(qiáng)能撐。但很危險(xiǎn)空郊,如果那塊硬盤(pán)掛了的話(huà)份招,很多條目圖片就沒(méi)了。后來(lái)我們將目錄結(jié)構(gòu)調(diào)整成兩級(jí)狞甚,第二級(jí)最多 10000 個(gè)文件脾还,這樣就實(shí)現(xiàn)了正常訪問(wèn)和備份。
一年后入愧,豆瓣搬到了兆維工業(yè)園鄙漏,服務(wù)器也更多了嗤谚。我們發(fā)現(xiàn)服務(wù)器上的硬盤(pán)空間使用很不均衡,機(jī)器間的相互備份也很麻煩怔蚌,想找一個(gè)分布式的存儲(chǔ)方案來(lái)把所有硬盤(pán)空間統(tǒng)一成全局的存儲(chǔ)系統(tǒng)巩步。先嘗試了 GlusterFS ,它優(yōu)雅的設(shè)計(jì)以及跟單機(jī)文件系統(tǒng)的兼容性很吸引人桦踊,可以把單機(jī)的文件系統(tǒng)原封不動(dòng)地加入到 GlusterFS 中提供對(duì)外訪問(wèn)椅野。可惜那會(huì)的 GlusterFS? 還不夠成熟籍胯,弄不好就死機(jī)了竟闪,好在不會(huì)丟數(shù)據(jù),得益于前面說(shuō)的那個(gè)兼容性杖狼。后來(lái)有幸發(fā)現(xiàn)了 MooseFS (簡(jiǎn)稱(chēng) MFS )炼蛤,上手非常容易,也很穩(wěn)定蝶涩。當(dāng)時(shí)也在調(diào)研 Hadoop 和 HDFS 理朋,但 MooseFS 的 POSIX API 使得它更容易使用也能支撐更多的應(yīng)用場(chǎng)景,就被大范圍使用了绿聘,從一開(kāi)始的數(shù)據(jù)備份嗽上,到跨機(jī)器數(shù)據(jù)共享,再到后來(lái)的大數(shù)據(jù)分析熄攘,基本上都是用它兽愤。最大的 MFS 集群是掛載在 /mfs,? 由于使用太頻繁,導(dǎo)致很長(zhǎng)一段時(shí)間兩只手都會(huì)下意識(shí)的輸入? mfs 挪圾。
為了能夠掌控 MFS 浅萧,我在調(diào)研時(shí)就開(kāi)始通過(guò)閱讀它的源代碼來(lái)了解運(yùn)作機(jī)制,結(jié)合之前已經(jīng)學(xué)習(xí)過(guò)多次的 Google? 的那篇 GFS 論文洛史,對(duì)分布式文件系統(tǒng)怎么運(yùn)作算是有了比較清楚的認(rèn)識(shí),當(dāng)使用 MFS 碰到問(wèn)題時(shí)酱吝,就自己打補(bǔ)丁來(lái)解決也殖,并同時(shí)提交給上游,不少被官方接受(接受代碼或者他們自己重新實(shí)現(xiàn)一下)务热。我們從一開(kāi)始的 1.5 忆嗜,一直跟著官方升級(jí),并維護(hù)少量自己的補(bǔ)丁崎岂,在 Gentoo 上維護(hù)補(bǔ)丁也挺愉快的捆毫。絕大部分時(shí)候都表現(xiàn)很好,時(shí)常光顧它的 WebUI 也是我喜歡干的一件事冲甘。幾年下來(lái)也碰到過(guò)一兩次事故绩卤,其中一次是在做故障切換時(shí)操作不當(dāng)途样,導(dǎo)致 mfsmaster 啟動(dòng)時(shí)使用了初始化狀態(tài),文件系統(tǒng)是空的濒憋, chunk server 連接上 mfsmaster 并匯報(bào)自己擁有的數(shù)據(jù)塊何暇,被 mfsmaster 認(rèn)為那些塊不應(yīng)該存在,就命令 chunk server 把它們刪掉凛驮。還好發(fā)現(xiàn)得及時(shí)裆站,只被刪了少部分?jǐn)?shù)據(jù),也都是我們收集的內(nèi)部日志數(shù)據(jù)黔夭,而不是更重要的用戶(hù)數(shù)據(jù)宏胯。事后給 MFS 打了補(bǔ)丁,延緩刪除這種未知數(shù)據(jù)塊本姥。
2008? 年豆瓣開(kāi)始往社區(qū)方向發(fā)展肩袍,做了用戶(hù)相冊(cè),這對(duì)在線存儲(chǔ)提出了更高的要求扣草。我們當(dāng)時(shí)調(diào)研了 MogileFS 了牛,經(jīng)過(guò)一段時(shí)間的使用之后感覺(jué)性能不太好,一方面是 MySQL 容易成為瓶頸辰妙,小文件直接放本地文件系統(tǒng)上的性能也不好鹰祸,數(shù)據(jù)遷移很慢。那會(huì) Amazon 的 Dynamo? 論文流傳很廣密浑,簡(jiǎn)化的 KV 系統(tǒng)以及最終一致性給存儲(chǔ)系統(tǒng)的實(shí)現(xiàn)打開(kāi)了另一扇門(mén)蛙婴。當(dāng)時(shí)還沒(méi)有成熟的開(kāi)源系統(tǒng)可以用,我們就自己開(kāi)始做 Beansdb 尔破,經(jīng)過(guò)了幾次迭代街图,從一開(kāi)始基于文件系統(tǒng)的 Merkle 樹(shù),到 TokyoDB 懒构,再到 Bitcask,慢慢穩(wěn)定和成熟胆剧,支撐了上百個(gè)節(jié)點(diǎn)和接近 PB 的數(shù)據(jù)量。過(guò)去兩年豆瓣的同學(xué)們又對(duì) Beansdb 做了大的升級(jí)篙悯,目前還沒(méi)有開(kāi)源,具體細(xì)節(jié)我就不知道了鸽照。
2009 年之后,豆瓣的存儲(chǔ)架構(gòu)算是比較穩(wěn)定和成熟了矮燎, MFS 和 Beansdb 承載了豆瓣的絕大部分?jǐn)?shù)據(jù)定血。 MFS 負(fù)責(zé)離線部分漏峰,用來(lái)管理幾乎所有機(jī)器的剩余磁盤(pán)空間,存放各種日志浅乔、備份,甚至開(kāi)發(fā)的代碼以及相關(guān)的各種數(shù)據(jù)靖苇。 MFS 的 POSIX API 給工程師帶來(lái)了很大便利,包括后來(lái)能夠快速開(kāi)發(fā) DPark 并投入生產(chǎn)環(huán)境使用也是受益于 MFS 的 POSIX API 贤壁。 Beansdb 則負(fù)責(zé)了在線系統(tǒng)的絕大部分?jǐn)?shù)據(jù)(圖片和長(zhǎng)文本等),結(jié)構(gòu)化數(shù)據(jù)仍然是 MySQL 脾拆,一開(kāi)始設(shè)想的用 KV 系統(tǒng)取代 MySQL 因?yàn)樽罱K一致性帶來(lái)的諸多問(wèn)題未能實(shí)現(xiàn)。我有幸參與了這兩套系統(tǒng)的很多工作名船,也對(duì) POSIX API 的便利性和最終一致性系統(tǒng)的局限性有了很深的體會(huì)绰上。
在 2013 年離開(kāi)豆瓣前夕渠驼,我嘗試改進(jìn) MFS 以滿(mǎn)足豆瓣日益增長(zhǎng)的性能和可用性需求。一方面是把它的網(wǎng)絡(luò)層從 poll 改成 epoll 迷扇,大大降低 mfsmaster 的 CPU 占用,以支撐上千的節(jié)點(diǎn)蜓席;同時(shí)也嘗試把部分元數(shù)據(jù)緩存到客戶(hù)端來(lái)降低 mfsmaster 的請(qǐng)求數(shù),提升可擴(kuò)展能力厨内;實(shí)現(xiàn)多 master (鏡像)來(lái)解決它的單點(diǎn)問(wèn)題。那段時(shí)間很開(kāi)心地寫(xiě)了很多 C 代碼隘庄,而且能很快看到改動(dòng)上線后大大地提升系統(tǒng)性能癣亚,就更開(kāi)心了∈鑫恚可惜因?yàn)闀r(shí)間關(guān)系街州,離職前未能把這三部分做到更完善,豆瓣在使用了一段時(shí)間后遇到了一些問(wèn)題唆缴,不想繼續(xù)維護(hù)這個(gè)分支,就又切換到官方版本上去了艳丛。這些改進(jìn)都發(fā)布在 github 上,尤其是雙 master 鏡像方案氮双,給 MFS 社區(qū)不少啟發(fā),官方把大部分重新實(shí)現(xiàn)了一下戴差,在閉源的 Pro 版本里面實(shí)現(xiàn)了 HA ,另一個(gè)開(kāi)源分支 LizardFS 也是實(shí)現(xiàn)了類(lèi)似的機(jī)制(然后號(hào)稱(chēng)有 HA 支持)暖释。用 epoll 和客戶(hù)端緩存來(lái)提升 master 的支撐能力, MFS 和 LizardFS 到現(xiàn)在都沒(méi)有實(shí)現(xiàn)球匕,很可惜肛真。
2013 年秋天我到了 Facebook 谐丢,因?yàn)榍皫讉€(gè)月在 MFS 上的愉快經(jīng)歷蚓让,想繼續(xù)做做分布式存儲(chǔ)方面的事,就在 Bootcamp 后進(jìn)入了 HDFS 組历极,希望能夠繼續(xù)探索分布式文件系統(tǒng)領(lǐng)域,給廣大 FB 工程師更好的存儲(chǔ)體驗(yàn)趟卸。當(dāng)時(shí) FB 除了大范圍使用 HDFS? (百 PB 級(jí)別),也是使用了其他 POSIX 文件系統(tǒng)的物喷,一個(gè)是購(gòu)買(mǎi)的商業(yè) NAS 存儲(chǔ) (PB? 級(jí)別)邻邮,另外一個(gè)是 GlusterFS 竣况。這兩個(gè)都有擴(kuò)展能力問(wèn)題筒严, GlusterFS 尤其在元數(shù)據(jù)方面性能比較差情萤,記得 ls 一個(gè)很大的備份目錄需要幾分鐘摹恨!基于已有的經(jīng)驗(yàn)判斷筋岛,應(yīng)該能夠做出一個(gè)類(lèi)似于 HDFS 的架構(gòu)晒哄,能夠支撐 10PB 以上的 POSIX 文件系統(tǒng),作為那個(gè) NAS 和 GlusterFS 的更好替代寝凌,甚至部分取代 HDFS ×蚶迹可惜當(dāng)時(shí)作為一個(gè)初來(lái)乍到的中國(guó)工程師(英語(yǔ)還說(shuō)不流利),要想推進(jìn)這樣一個(gè)重量級(jí)的項(xiàng)目實(shí)在是困難重重劫映。雖然我在技術(shù)實(shí)現(xiàn)上已經(jīng)有很大進(jìn)展,并在尋求早期內(nèi)部客戶(hù)的過(guò)程中泳赋,還是沒(méi)有得到上級(jí)的支持,只好作罷校坑,轉(zhuǎn)頭繼續(xù)改進(jìn) HDFS 了。另外耍目,也參與了另一個(gè)更大規(guī)模的存儲(chǔ)系統(tǒng)的早期設(shè)計(jì),因?yàn)?FB 還沒(méi)對(duì)外說(shuō)它邪驮,暫時(shí)就不公開(kāi)討論了。
因?yàn)楦矚g小公司的做事方式毅访, 2014 年到了 Databricks 盘榨,做另一個(gè)我也非常喜歡的領(lǐng)域:分布式計(jì)算框架喻粹, Apache Spark 草巡。因?yàn)橹霸诙拱曜鲞^(guò) DPark ,到? Databricks? 工作算是興趣和經(jīng)驗(yàn)的很好匹配。 Databricks? 是圍繞? Apache Spark 做一個(gè)云服務(wù),讓工程師或者數(shù)據(jù)分析人員能夠很容易地使用 Apache Spark 做大數(shù)據(jù)分析萍歉。整個(gè)服務(wù)都部署在 AWS ,因?yàn)槊庥谶\(yùn)維和低成本等多種因素枪孩, Databricks 選擇 S3 為存儲(chǔ)方案。 Spark 依賴(lài)于 HDFS 的 API 蔑舞,而 S3 只是一個(gè)最終一致性的 KV 存儲(chǔ)系統(tǒng),只好在客戶(hù)端把 S3 模擬成文件系統(tǒng)攻询,勉強(qiáng)能用,但是有好多問(wèn)題低零。我們花了很多精力去繞過(guò)那些問(wèn)題,最新的 DBIO 有了不少突破掏婶。 AWS 的 S3 團(tuán)隊(duì)也無(wú)法給出解決那些問(wèn)題的時(shí)間表,因?yàn)楹芏鄦?wèn)題是由系統(tǒng)設(shè)計(jì)造成的雄妥,考慮到現(xiàn)有系統(tǒng)的兼容性等諸多因素依溯,很可能永遠(yuǎn)解決不了老厌。
S3 的優(yōu)點(diǎn)已經(jīng)被廣泛認(rèn)識(shí)(可擴(kuò)展黎炉,低成本,免運(yùn)維)拜隧,簡(jiǎn)單列一下 S3 的幾個(gè)問(wèn)題: 1) S3? 缺乏真的目錄結(jié)構(gòu)和原子改名,相當(dāng)于一個(gè)不可以改表結(jié)構(gòu)的數(shù)據(jù)庫(kù)洪添,導(dǎo)致 Spark 不能保證計(jì)算結(jié)果的正確和穩(wěn)定提交; 2)? 文件不方便修改痊焊,會(huì)導(dǎo)致產(chǎn)生大量小文件,之后訪問(wèn)會(huì)很慢? 3) S3? 的元數(shù)據(jù)訪問(wèn)很慢并且很貴薄啥,我們 S3 的成本一半是遍歷文件列表產(chǎn)生的? 4 )不正確的元數(shù)據(jù)緩存導(dǎo)致應(yīng)用經(jīng)常被告知該存在的文件不存在,導(dǎo)致應(yīng)用在隨機(jī)的地方 crash 垄惧。另外, Databricks 又在 S3 的 Java SDK 之上做了一個(gè)簡(jiǎn)單封裝 DBFS 到逊,導(dǎo)致 Python 和 R 用戶(hù)訪問(wèn)數(shù)據(jù)更不方便。我給內(nèi)部的封裝做了一個(gè)挺挫的 FUSE 接口( Python 實(shí)現(xiàn)的)給客戶(hù)用脑题,雖然性能很差,用的人還蠻多叔遂。
過(guò)去幾年中在離線應(yīng)用中被 S3 坑過(guò)太多次争剿,? 一直在思考有什么更好地替代方案掏熬。 AWS 在? 2016? 年正式推出了 EFS 秒梅,可惜定價(jià)太高實(shí)在不適合大數(shù)據(jù)應(yīng)用旗芬。自己維護(hù) HDFS 或者 MFS 也是個(gè)大挑戰(zhàn)捆蜀,連 Databricks 也不想趟這渾水,而且運(yùn)行成本也很高誊薄,據(jù) Airbnb 測(cè)算, HDFS 的成本是 S3 的 15 倍呢蔫,但因?yàn)?S3 的諸多問(wèn)題他們?nèi)匀皇谴罅渴褂?HDFS 飒筑。
鑒于現(xiàn)有解決方案都不理想片吊,也在思考能不能做一個(gè)方案來(lái)解決這些問(wèn)題协屡,尤其是在公有云這個(gè)場(chǎng)景中,并嘗試做一些原型來(lái)驗(yàn)證想法肤晓。像 S3 這樣的對(duì)象存儲(chǔ)幾乎成了公有云的標(biāo)配认然,因?yàn)?API 簡(jiǎn)單且一致性要求低漫萄,很容易做到大規(guī)模可擴(kuò)展和低成本毕骡。但它欠缺的是好用的 API 和一致性保證,或許可以基于它實(shí)現(xiàn)一個(gè) POSIX 文件系統(tǒng)。去年有了實(shí)質(zhì)性的進(jìn)展葵孤,并找了幾個(gè)公司做內(nèi)測(cè),效果還不錯(cuò)箫津。
今年 6 月從 Databricks 離職,在華創(chuàng)和清源等投資人的幫助下創(chuàng)立了 Juicedata 苏遥,致力于幫企業(yè)客戶(hù)解決數(shù)據(jù)訪問(wèn)和管理問(wèn)題。我們做的 JuiceFS (https://juicefs.io/) 是一個(gè)基于公有云對(duì)象存儲(chǔ)的 POSIX 文件系統(tǒng)赡模,能夠跟 S3 一樣按需伸縮和低成本,沒(méi)有維護(hù)的煩惱漓柑,還跟 MFS 一樣方便使用。目前在公測(cè)階段瞬矩, 10 月份會(huì)開(kāi)始正式商用锋玲。歡迎有興趣的同學(xué)試用景用,或者一起探討存儲(chǔ)方面的問(wèn)題和技術(shù)等惭蹂。 Juicedata? 才剛剛開(kāi)始,我們會(huì)努力提供最好的存儲(chǔ)解決方案蜂怎,也歡迎志同道合的同學(xué)們加入置尔。
如果你對(duì)我們的產(chǎn)品感興趣杠步,請(qǐng)到網(wǎng)站上注冊(cè),1TB 以下的存儲(chǔ)免費(fèi)朵锣。如果你對(duì)我們的團(tuán)隊(duì)感興趣甸私,歡迎投簡(jiǎn)歷到 rsu at juicedata.io