24 年初,我們和客戶 H 進(jìn)行了交流。當(dāng) 23 年大家都在訓(xùn)練自己的大模型,H 客戶擴(kuò)大了已有的 GPU 集群規(guī)模,加上既有自建 IT 基礎(chǔ)設(shè)施,開啟了大模型訓(xùn)練之路。在大模型加持下,新的業(yè)務(wù)效果很快得到了證明。隨著時(shí)間推移,大模型業(yè)務(wù)的不斷擴(kuò)大,基礎(chǔ)設(shè)施層面碰到了一些跟存儲(chǔ)相關(guān)的問題:
類似客戶 H 遇到的這些問題的例子還有不少。他們中大多都經(jīng)歷了從自建 IT 基礎(chǔ)設(shè)施到開源大數(shù)據(jù)生態(tài)的時(shí)期,并嘗試將以前的經(jīng)驗(yàn)復(fù)制到 AI 場景。
的確,過去由數(shù)據(jù)庫、數(shù)倉、ETL 等技術(shù)驅(qū)動(dòng)的商業(yè)智能成為業(yè)務(wù)的強(qiáng)大助推器,但這種圍繞預(yù)定義 schema 層層裁剪模式所設(shè)計(jì)的存算架構(gòu)在 AI 面前顯露出不少弊端,尤其是受系統(tǒng)擴(kuò)展性和成本的制約,大量原始數(shù)據(jù)不得不被舍棄。
但是,數(shù)據(jù)正是大模型時(shí)代的黃金和石油,當(dāng)業(yè)務(wù)希望從這些寶貴的原始數(shù)據(jù)中重新構(gòu)建智能、提煉新的價(jià)值時(shí),往往發(fā)現(xiàn)為時(shí)已晚。
對于這位 H 客戶,我們給的建議是擁抱云原生數(shù)據(jù)湖。其中最核心的主張就是將各類原始數(shù)據(jù)統(tǒng)一入湖,集中存儲(chǔ)到同一數(shù)據(jù)底座,再以開放統(tǒng)一的接口提供給各類上層計(jì)算和應(yīng)用。這種方式最大限度保留了數(shù)據(jù)的 Single Source of Truth,同時(shí)也解決了這位客戶的困擾:
當(dāng)然,這些優(yōu)勢不僅局限于 AI 場景,在大數(shù)據(jù)場景下同樣能發(fā)揮很大的價(jià)值。除了比 HCFS 擁有更好的擴(kuò)展性、資源彈性和成本優(yōu)勢外,類似 Hudi、Iceberg 等新一代存儲(chǔ)格式和計(jì)算范式也在圍繞對象存儲(chǔ)的這些特性進(jìn)行設(shè)計(jì)優(yōu)化。可以看到,基于對象存儲(chǔ)的數(shù)據(jù)湖已成為云原生時(shí)代的事實(shí)標(biāo)準(zhǔn)。
回到 H 客戶的例子。雖然對象存儲(chǔ)解決了他的海量數(shù)據(jù)規(guī)模和存儲(chǔ)成本的問題,但存儲(chǔ)拖慢訓(xùn)練的問題仍然沒有解決,甚至在某些情況下可能更差!要弄清楚原因,我們?nèi)砸?AI 訓(xùn)練為例展開分析。
如圖展示了一個(gè)典型的 AI 訓(xùn)練過程。每一輪訓(xùn)練首先需要對原始數(shù)據(jù)進(jìn)行遍歷和打散,然后以多個(gè) batch 喂給 GPU 完成訓(xùn)練迭代,多次迭代間還會(huì)保存 checkpoint 用于中斷恢復(fù)。
我們注意到大多數(shù)訓(xùn)練尤其是視覺、多模態(tài)訓(xùn)練往往依賴大量小文件作為輸入。因此除讀寫 checkpoint 外,訓(xùn)練與存儲(chǔ)的交互主要集中在兩個(gè)方面:一是大目錄下海量文件的遍歷,對應(yīng)對象存儲(chǔ)的 LIST 操作;二是小文件的高頻重復(fù)讀,對應(yīng) HEAD 和 READ 操作。
再從對象存儲(chǔ)側(cè)來看。雖然其平坦目錄結(jié)構(gòu)、糾刪碼編碼方式和存算分離架構(gòu)解決了擴(kuò)展性、成本和彈性問題,但也導(dǎo)致 LIST 和對小文件的 HEAD、READ 性能可能比不上傳統(tǒng)的 HCFS 架構(gòu):
類似地,對大數(shù)據(jù)場景進(jìn)行分析也會(huì)看到同樣的問題。我們將 AI 和大數(shù)據(jù)各類典型場景總結(jié)如下,發(fā)現(xiàn)部分場景依靠對象存儲(chǔ)自身能力就能很好地滿足,但另一些場景則需要額外的存儲(chǔ)加速,才能保證計(jì)算效率,減少算力和帶寬資源的浪費(fèi)。
早在數(shù)據(jù)湖被提出之前,隨著高性能計(jì)算(HPC)需求的產(chǎn)生,存儲(chǔ)性能的提升就已經(jīng)得到了廣泛關(guān)注。這一階段,HPC 等應(yīng)用開始由 NAS 類容量型存儲(chǔ)轉(zhuǎn)向以并行文件系統(tǒng)為代表的高性能存儲(chǔ)。
并行文件系統(tǒng),代表產(chǎn)品如 GPFS、Lustre、BeeGFS,最初面向復(fù)雜多媒體處理、氣象分析、工程計(jì)算、生命科學(xué)等超算場景設(shè)計(jì)。通過客戶端到后端數(shù)據(jù)節(jié)點(diǎn)的直連、數(shù)據(jù)條帶化、MPI-I/O 等機(jī)制實(shí)現(xiàn)并行讀寫,從而在當(dāng)時(shí)主流的 HDD 上也能提供出眾的存儲(chǔ)性能。后來基于 SSD 實(shí)現(xiàn)了更極致的性能,被廣泛應(yīng)用于 HPC 和 AI 場景,成為很長時(shí)間內(nèi)性能場景下近乎唯一的選擇。
不難想象,假如經(jīng)費(fèi)無限,將所有數(shù)據(jù)全部放入并行文件系統(tǒng),幾乎就能滿足應(yīng)用對高性能存儲(chǔ)的所有訴求。但實(shí)際上對于數(shù)據(jù)密集型業(yè)務(wù)來說,完全基于一套大容量的并行文件系統(tǒng),存儲(chǔ)成本勢必成為不容忽視的問題。
面對巨大的成本問題,研發(fā)工程師們會(huì)提出什么樣的方案來解決呢?
在 HPC 和 AI 場景,近年來開始將并行文件系統(tǒng)與對象這類低成本存儲(chǔ)組合使用。在這套組合中,兩者并不是對等的,而是處于上下兩層。根據(jù)數(shù)據(jù)入口和存儲(chǔ)中心所屬層級的變遷,可細(xì)分為兩個(gè)階段。
第一階段,數(shù)據(jù)入口和存儲(chǔ)中心仍然在并行文件系統(tǒng),對象存儲(chǔ)只作為其過期數(shù)據(jù)沉降或備份的冷存儲(chǔ)層。
第二階段,隨著數(shù)據(jù)湖進(jìn)入大家的視野,數(shù)據(jù)入口和存儲(chǔ)中心開始下移至對象存儲(chǔ)底座,而計(jì)算所需的熱數(shù)據(jù)向上導(dǎo)入并行文件系統(tǒng)。這種形態(tài)下,我們已經(jīng)可以把并行文件系統(tǒng)視為對象存儲(chǔ)的緩存加速層。不過這種加速方案有兩個(gè)問題需要改進(jìn):
面對不透明性問題,研發(fā)工程師又是如何解決的?
出于對上述兩個(gè)問題的改進(jìn),大家開始思考更透明、性價(jià)比更高的方案。誕生于 UC Berkeley 的 Alluxio 就提供了其中一條演進(jìn)思路。
Alluxio 最初的思想是在計(jì)算側(cè)構(gòu)建一層虛擬的分布式文件系統(tǒng),從而對各類上層業(yè)務(wù)屏蔽底層存儲(chǔ)差異。這種統(tǒng)一訪問界面之下的數(shù)據(jù)編排能力,可實(shí)現(xiàn)底層異構(gòu)存儲(chǔ)間的數(shù)據(jù)流動(dòng),因此被大量用于跨系統(tǒng)、跨云的統(tǒng)一存儲(chǔ)業(yè)務(wù)架構(gòu)。實(shí)際上這跟 VFS 在 Linux 操作系統(tǒng)中的角色非常相似。
Alluxio 的另一個(gè)貢獻(xiàn)則是促進(jìn)了近計(jì)算分布式緩存的發(fā)展。這讓大家意識到如果將計(jì)算節(jié)點(diǎn)空閑的內(nèi)存、SSD 等資源統(tǒng)一托管起來,用作對象存儲(chǔ)的透明緩存,不僅不增加成本,還能獲得非常好的加速效果。相對于對象存儲(chǔ)引擎內(nèi)部的緩存機(jī)制,這類近計(jì)算緩存直接工作在業(yè)務(wù) VPC 的 overlay 網(wǎng)絡(luò)中,時(shí)延能降低一個(gè)數(shù)量級,同時(shí)與計(jì)算框架配合實(shí)現(xiàn)數(shù)據(jù)協(xié)同調(diào)度的發(fā)揮空間也更大。因此近年來,各大云服務(wù)商紛紛推出了自己的緩存加速產(chǎn)品,比如 AWS 的 FileCache、百度智能云的 RapidFS、阿里云的 JindoFS、騰訊云的 GooseFS 等,在 AI 和大數(shù)據(jù)的大部分場景下都能取得接近并行文件系統(tǒng)的加速效果。
Alluxio 這類真正的緩存系統(tǒng)用于對象存儲(chǔ)加速,相對于采用并行文件系統(tǒng)的加速方案,最大的區(qū)別在于兩層間的數(shù)據(jù)關(guān)聯(lián)和雙向流轉(zhuǎn)完全透明化,從而能做到:
當(dāng)然,緩存系統(tǒng)也有其固有的問題,在使用中需要注意:
為了解決對象存儲(chǔ)在大數(shù)據(jù)場景寫能力上不足的問題,研發(fā)工程師是如何設(shè)計(jì)新的解決方案的?
事實(shí)上,上面提到的緩存系統(tǒng)寫操作的局限性來自元數(shù)據(jù)和數(shù)據(jù)語義兩個(gè)層面。元數(shù)據(jù)層面,對象存儲(chǔ)平坦目錄結(jié)構(gòu)導(dǎo)致 rename 這類子樹操作實(shí)際上需要對子樹下所有對象依次操作,非原子、耗時(shí)長。而數(shù)據(jù)層面,底層存儲(chǔ)引擎只提供一次寫入能力,不支持流式追加寫。針對這兩個(gè)問題,業(yè)界提供了兩類解法。
這種方式是在對象存儲(chǔ)之上重新構(gòu)建一層近計(jì)算的文件系統(tǒng),用來解決文件語義和性能加速兩個(gè)問題。對象存儲(chǔ)層只提供持久化數(shù)據(jù)底座,繼續(xù)發(fā)揮其擴(kuò)展性、彈性和成本優(yōu)勢。
以 JuiceFS 為代表,上層重新組織層級目錄結(jié)構(gòu)的文件元數(shù)據(jù),并存儲(chǔ)在 Redis、TiKV 這類外部元數(shù)據(jù)引擎中。而數(shù)據(jù)切塊后寫入對象存儲(chǔ),將以前對整個(gè)對象的更新縮小到對其中一個(gè)小數(shù)據(jù)塊的更新,從而滿足追加寫、邊寫邊讀等語義需求,因此這種方案在大數(shù)據(jù)場景得到了較為廣泛的應(yīng)用。性能上,對于存在大量共享數(shù)據(jù)需要加速的高性能場景,可以使用其商業(yè)版提供的分布式緩存功能。
不過在實(shí)際應(yīng)用中還需要考慮由此帶來的數(shù)據(jù)侵入性問題。
由于文件切塊后持久化,因此對象存儲(chǔ)層丟失了路徑、文件名中所包含的關(guān)鍵業(yè)務(wù)信息。這樣就很難再完全利用對象存儲(chǔ)的生態(tài)能力進(jìn)行數(shù)據(jù)處理、數(shù)據(jù)管理、生命周期流轉(zhuǎn)和成本優(yōu)化。為了緩解這個(gè)問題,JuiceFS 最近的版本支持了存量對象導(dǎo)入和文件到對象的導(dǎo)出,可以實(shí)現(xiàn)一次性的單向拷貝。不過,當(dāng)建設(shè)多套業(yè)務(wù)系統(tǒng)時(shí),需要同時(shí)建設(shè)多個(gè)近計(jì)算文件系統(tǒng)實(shí)例,因此可能需要多次導(dǎo)入導(dǎo)出才能滿足多套業(yè)務(wù)系統(tǒng)間數(shù)據(jù)交換的需求。
為了原生支持完備語義,一些云服務(wù)商又探索出第二種解法,即直接在對象存儲(chǔ)層內(nèi)部實(shí)現(xiàn)元數(shù)據(jù)和數(shù)據(jù)兩個(gè)層面的文件對象融合。緩存系統(tǒng)仍然在近計(jì)算側(cè)提供性能加速。
采用這種文件對象融合存儲(chǔ)作為數(shù)據(jù)底座和數(shù)據(jù)流動(dòng)的主管道,疊加各業(yè)務(wù)環(huán)節(jié)的近計(jì)算緩存,既能滿足完備語義、性能加速和透明流轉(zhuǎn)的需求,又能避免對業(yè)務(wù)數(shù)據(jù)的侵入,獲得更多對象存儲(chǔ)的豐富功能和原生體驗(yàn)。
上面我們對數(shù)據(jù)湖存儲(chǔ)加速的誕生和發(fā)展進(jìn)行了總結(jié)。雖然市面上各產(chǎn)品的思路和具體實(shí)現(xiàn)有差異,但在需要解決的關(guān)鍵問題上又是大致相同的,不外乎元數(shù)據(jù)加速、數(shù)據(jù)讀寫加速、數(shù)據(jù)流端到端提效三個(gè)方面。從這幾個(gè)方面一探究竟,可以幫助我們更好地理解其原理并挑選出適合自身業(yè)務(wù)的存儲(chǔ)加速方案。
存儲(chǔ)系統(tǒng)的元數(shù)據(jù)是用來管理數(shù)據(jù)的數(shù)據(jù),比如目錄結(jié)構(gòu)、文件名稱、大小、修改時(shí)間等。業(yè)務(wù)發(fā)起讀寫操作前,都需要先與元數(shù)據(jù)交互,尤其在大數(shù)據(jù) AD-HOC、AI 訓(xùn)練等涉及大量小文件或小 I/O 的場景中,元數(shù)據(jù)耗時(shí)的占比甚至接近數(shù)據(jù)讀寫本身。因此其性能好壞對存儲(chǔ)的整體表現(xiàn)有很大影響。
大多數(shù)業(yè)務(wù)程序已習(xí)慣本地文件系統(tǒng)的用法和層級目錄視圖。而前面提到,對象存儲(chǔ)用平坦目錄來模擬層級目錄的開銷,以及較長的網(wǎng)絡(luò)距離和請求處理路徑都對元數(shù)據(jù)性能帶來負(fù)向影響。因此幾種加速方案都繞不開近計(jì)算原生層級目錄樹這一做法。
數(shù)據(jù)讀寫是計(jì)算跟存儲(chǔ)交互最多的部分。如果讀寫慢于計(jì)算則會(huì)導(dǎo)致任務(wù)等待和算力浪費(fèi)。尤其當(dāng)面對價(jià)格不菲的 GPU 算力時(shí),這個(gè)問題愈發(fā)受到關(guān)注。
對于對象存儲(chǔ)來說,影響讀寫性能的主要因素:一是存算分離架構(gòu)導(dǎo)致的網(wǎng)絡(luò)距離和帶寬限速問題;二是 HDD 介質(zhì)性能和存儲(chǔ)引擎能力的限制;三是較長的請求處理路徑對時(shí)延的影響。因此數(shù)據(jù)讀寫加速的思路也大致圍繞這幾個(gè)方面展開。
第一,近計(jì)算訪問:在分析元數(shù)據(jù)加速時(shí)已經(jīng)提到,加速層近計(jì)算部署可以明顯縮短網(wǎng)絡(luò)距離,降低讀寫時(shí)延,對于數(shù)據(jù)面來說更是如此。并且對同一份數(shù)據(jù)的多次重復(fù)讀,可通過近計(jì)算緩存節(jié)省大量帶寬,避免對象存儲(chǔ)主動(dòng)限速的影響。
第二,采用高規(guī)格硬件和優(yōu)化的存儲(chǔ)引擎:加速層通常采用 NVME SSD 存儲(chǔ)介質(zhì)、與之匹配的高性能單機(jī)引擎和 RDMA 高性能網(wǎng)絡(luò),相對于直接訪問對象存儲(chǔ)可帶來數(shù)量級的時(shí)延降低。而在對象存儲(chǔ)層內(nèi)部,一些產(chǎn)品也通過原生支持流式存儲(chǔ)引擎,相對過去的 Blob 引擎提供了更接近文件系統(tǒng)的讀寫表現(xiàn)。
第三,軟件架構(gòu)和 I/O 鏈路優(yōu)化:有了近計(jì)算網(wǎng)絡(luò)環(huán)境和高規(guī)格硬件,如何將它們充分利用起來,需要依靠加速層的軟件架構(gòu)設(shè)計(jì)和 I/O 鏈路優(yōu)化。在這一點(diǎn)上各產(chǎn)品的做法不盡相同,但基本思路不外乎兩點(diǎn),提高擴(kuò)展能力和縮短 I/O 路徑。以讀加速為例:
當(dāng)然,對于寫加速也有類似的優(yōu)化手段。例如緩存系統(tǒng)的單端寫,可先寫計(jì)算節(jié)點(diǎn)本地的內(nèi)存和 SSD 即返回(縮短 I/O 路徑),然后異步將這些數(shù)據(jù)按不同區(qū)段并行寫入底層對象存儲(chǔ)的大資源池(提高擴(kuò)展能力),從而成倍提升端到端寫吞吐。
有了上面介紹的元數(shù)據(jù)和數(shù)據(jù)讀寫加速,還有一個(gè)關(guān)鍵問題是在業(yè)務(wù)流中如何將這些能力串起來、利用好,最終實(shí)現(xiàn)端到端提效。事實(shí)上,在對實(shí)際業(yè)務(wù)的長期觀察中發(fā)現(xiàn),數(shù)據(jù)流轉(zhuǎn)不暢往往成為降低業(yè)務(wù)效率的更重要因素。
我們可從三個(gè)層面來分析這一問題。
第一,業(yè)務(wù)如何低成本接入:對象存儲(chǔ)通常提供 HTTP API 的訪問接口,但不論從性能還是兼容性來看,這種接口對大數(shù)據(jù)和 AI 業(yè)務(wù)都不夠友好。存儲(chǔ)加速產(chǎn)品往往會(huì)提供更低成本的接入方式。例如對于大數(shù)據(jù),提供業(yè)界廣泛采用的 HCFS SDK 客戶端,可與 Hadoop 生態(tài)無縫對接;對于 AI,則提供 POSIX 兼容的掛載客戶端,使得基于本地盤和傳統(tǒng)自建存儲(chǔ)的數(shù)據(jù)科學(xué)家能將各類實(shí)驗(yàn)和生產(chǎn)任務(wù)無感遷移上來,大大降低了業(yè)務(wù)的適配成本。
第二,單個(gè)業(yè)務(wù)環(huán)節(jié)內(nèi)如何高效數(shù)據(jù)流轉(zhuǎn):對于業(yè)務(wù)流中的某個(gè)具體節(jié)點(diǎn),只有讓數(shù)據(jù)在合適的時(shí)機(jī)出現(xiàn)在合適的位置,才能發(fā)揮好存儲(chǔ)加速的作用。在這一點(diǎn)上,緩存系統(tǒng)通常能提供最為靈活的機(jī)制和策略,通過與上下層配合來優(yōu)化數(shù)據(jù)調(diào)度和緩存效率。
第三,多個(gè)業(yè)務(wù)環(huán)節(jié)間如何做到數(shù)據(jù)暢通:實(shí)際業(yè)務(wù)往往涉及上下游多個(gè)環(huán)節(jié)的配合。例如大數(shù)據(jù) ETL 將一級輸出作為下一級的輸入,數(shù)據(jù)預(yù)處理的輸出作為 AI 訓(xùn)練的輸入,訓(xùn)練產(chǎn)出的模型作為推理的輸入等。這些業(yè)務(wù)節(jié)點(diǎn)間的數(shù)據(jù)流動(dòng)和共享就是貫穿其中的關(guān)鍵。
最后,回到本文開篇提到的案例,客戶 H 最終需要一個(gè)什么樣的數(shù)據(jù)湖存儲(chǔ)加速方案呢,除了技術(shù)因素之外,還有其他維度需要考慮嗎?