高性能、云原生湖倉一體存儲架構(gòu)探秘
一、湖倉一體存儲架構(gòu)的演進
1、存儲架構(gòu)的演進階段
大數(shù)據(jù)存儲系統(tǒng)的演進,分為兩個階段:機房時代和云計算時代。
第一個階段,也是最早 Hadoop誕生的時代,這個時代主要以機房的系統(tǒng)為主, HDFS 基本上是唯一的存儲選型方案。
隨著云計算的普及和發(fā)展,對象存儲逐漸成為企業(yè)主流的存儲方案。尤其是在數(shù)據(jù)湖架構(gòu)中,對象存儲以其高度可擴展性和對多樣化數(shù)據(jù)類型的支持,成為一種流行的底層存儲解決方案。我們將回顧并對比HDFS和對象存儲的架構(gòu),探討它們各自的優(yōu)劣勢以及發(fā)展趨勢。同時也會探討云原生的數(shù)據(jù)湖存儲架構(gòu)應(yīng)該如何設(shè)計。
如果從本質(zhì)上去分析 HDFS 和和對象存儲的架構(gòu)設(shè)計,會發(fā)現(xiàn)其實是兩個完全不一樣的存儲系統(tǒng)。未來在云原生時代里的存儲系統(tǒng),為大數(shù)據(jù)湖倉一體提供存儲底座,應(yīng)該具備哪些特征呢?后面我們會對此進行探討。
2、HDFS 的特征
HDFS 起源于 GFS ( Google File system ) , 于2006年正式發(fā)布。它的特點包括獨立的元數(shù)據(jù)存儲(NameNode)、多副本、存算耦合等。整個 HDFS 設(shè)計,對于大文件存儲相對來說更友好,對于小文件沒有那么友好。在存儲的規(guī)模上,一般單個命名空間(Namespace)在億這個量級。如果有更大量級的數(shù)據(jù)存儲,需要做一些擴展性的架構(gòu)調(diào)整。
3、對象存儲的特征
對象存儲 S3 也是于2006年發(fā)布,但它發(fā)布之初的目標(biāo)其實是存儲海量的非結(jié)構(gòu)化數(shù)據(jù),并不是給大數(shù)據(jù)生態(tài)使用,所以對象存儲的架構(gòu)設(shè)計和 HDFS 完全不一樣。它主打的特點,包括存儲成本低、數(shù)據(jù)的持久性足夠高等方面。它的 API 是基于 HTTP 協(xié)議,元數(shù)據(jù)設(shè)計是扁平的 KV 結(jié)構(gòu),扁平的元數(shù)據(jù)設(shè)計在大數(shù)據(jù)場景中會帶來一些問題。和 HDFS 一樣,它的數(shù)據(jù)也是不支持修改的。在一致性上,對象存儲以最終一致性為主,部分的云廠或者部分接口可以實現(xiàn)強一致性。
二、不同類型存儲系統(tǒng)比較
下面整體對比一下前面提到的 HDFS 和對象存儲在不同維度的特性。
首先存儲規(guī)模直接決定了數(shù)據(jù)平臺或者整個大數(shù)據(jù)系統(tǒng)能夠支撐的業(yè)務(wù)數(shù)據(jù)量,相比HDFS,對象存儲能做到更大的存儲規(guī)模。在日常的數(shù)據(jù)任務(wù)中,比如 ETL 或者ad-hoc,元數(shù)據(jù)操作性能會影響整體的任務(wù)效率,這一點對象存儲的性能要遠遠弱于HDFS。運維復(fù)雜度也是影響存儲選型的關(guān)鍵因素,HDFS的維護成本相比對象存儲會高不少,這其中既包括人力成本,也包括為了保證高可用和擴展性額外搭建的一些組件等。
1、HDFS的阿喀琉斯之踵-NameNode
HDFS 最大的瓶頸是 NameNode。NameNode 最開始的設(shè)計是模仿 GFS 的 Master,這是一個單點設(shè)計,所以 HDFS 也有同樣的問題。
在單點的 NameNode 擴展性問題上,社區(qū)做了一些嘗試,比如 ViewFs + Federation 的方案,后面又推出了RBF(Router-based Federation)方案,本質(zhì)上是為了解決單一命名空間下 NameNode的擴展性問題,通過多集群橫向擴展的方式保證 HDFS 集群存儲容量的規(guī)模不會受到大的限制。
除了存儲規(guī)模以外,另外一個問題就是高可用問題。在單一集群里面 NameNode 是一個單點,所以后來有了 Standby 的 NameNode,再往后有了 JournalNode。歸根結(jié)底,所有這些組件、架構(gòu)都是為了保證整個 HDFS 存儲集群能夠滿足高可用的需求,而不是一旦 Active NameNode 宕機之后整個大數(shù)據(jù)集群就不可用了。
2、對象存儲的阿喀琉斯之踵-元數(shù)據(jù)
對象存儲的問題也跟元數(shù)據(jù)相關(guān)。前面提到了對象存儲的元數(shù)據(jù)設(shè)計是一個扁平的 KV 結(jié)構(gòu)。上圖中的foo目錄有這么多子目錄或者子文件,從對象存儲角度來說,它并不是目錄結(jié)構(gòu)。我們在傳統(tǒng)的文件系統(tǒng)里面看到的是樹狀的目錄結(jié)構(gòu),但在對象存儲的設(shè)計里面并不存在一個目錄樹,而是一維扁平的 KV 結(jié)構(gòu),再通過“/” 分隔符來模擬目錄樹。
如果要在對象存儲里面實現(xiàn)目錄的重命名,例如將foo這個目錄重命名為 bar 目錄,對象存儲的實現(xiàn)上會有這樣一些步驟:第一步需要先遞歸地拷貝,如果是很深的目錄,那需要去遞歸拷貝整個目錄的數(shù)據(jù)到以 bar 為前綴的位置;第二步是更新內(nèi)部的一些索引;最后把原始的 foo 目錄下的相關(guān)數(shù)據(jù)都刪掉。
整個流程雖然看起來只是一步重命名文件夾的操作,但在對象存儲內(nèi)部拆分成了幾個大的步驟,每個步驟其實看起來都不是特別的輕量,特別是第一步和第三步。
我們自然會有一個疑問,在這個過程中,尤其是當(dāng)要重命名一個很大數(shù)據(jù)量的目錄時,一致性如何保證?其實對象存儲是沒有辦法保證的。社區(qū)有很多的組件去嘗試解決,或者基于對象存儲的接口去優(yōu)化。但也只能是盡量去規(guī)避一致性問題,并不能完全解決。因為對象存儲架構(gòu)設(shè)計上的問題是沒有辦法通過外層的組件簡單繞過的。
3、對象存儲元數(shù)據(jù)性能及API限制
在數(shù)據(jù)湖的組件里面,不管是 Hudi 還是 Iceberg,都提到過對象存儲的一些問題,比如上面這個表格是 Hudi 文檔里面提到的,在對象存儲上如果要 List 一個目錄,隨著目錄的文件數(shù)的增多,它的延遲會逐步地增長,所以 Hudi 社區(qū)才有了 Metadata Table 設(shè)計。
Iceberg 在文檔里面也提到對象存儲會有一些基于某一個固定前綴的 API QPS 限制,這樣就會導(dǎo)致頻繁訪問的目錄或者大的數(shù)據(jù)集如果觸碰到這個 API QPS 限制,任務(wù)的穩(wěn)定性會直接受到影響。特別是當(dāng)你的數(shù)據(jù)平臺的規(guī)模變得比較大以后,就很容易觸碰到云上對象存儲的 API QPS 限制。所以 Iceberg 有了 ObjectStorageLocationProvider,去盡量規(guī)避這個問題。它本質(zhì)上是一種規(guī)避的實現(xiàn)方式,在不同的Key 前面加一個隨機的哈希,這個哈希就是為了盡量把基于前綴的 QPS 限制分散到不同的前綴,從而避免很快觸碰到 API QPS 限制。
三、探索湖倉一體架構(gòu)未來的存儲選型
假設(shè)現(xiàn)在從 0 開始去設(shè)計,基于當(dāng)下云計算或者云原生的環(huán)境去構(gòu)建一個更適合現(xiàn)在和未來的存儲系統(tǒng),它應(yīng)該具備哪些能力呢?
1、技術(shù)關(guān)鍵點
這里列了對于大部分場景來說都比較重要的一些點:
首先最重要的就是擴展性的問題,隨著大數(shù)據(jù)平臺的架構(gòu)從數(shù)倉、到數(shù)據(jù)湖、到湖倉一體不斷演進,對于平臺存儲容量的要求會越來越高,不僅僅是滿足以前傳統(tǒng)數(shù)倉的存儲需求,還要盡量多地去涵蓋越來越多的業(yè)務(wù),以前在不同的存儲系統(tǒng)里面管理的數(shù)據(jù),接下來可能需要在一個地方統(tǒng)一存儲和管理,避免數(shù)據(jù)孤島的問題。
第二個很重要的點是高可用問題。整個系統(tǒng)肯定要具備高可用的能力,不能只有擴展性沒有高可用,否則也是無法滿足生產(chǎn)需求的。
第三點是性能問題。不能為了存儲大容量的數(shù)據(jù),就以犧牲性能為代價,需要一定的優(yōu)化策略保證性能,包括元數(shù)據(jù)的性能以及數(shù)據(jù)讀寫的性能。
接下來是盡量多地利用云的優(yōu)勢,云最大的特性就是彈性,計算和存儲都可以做到彈性。如果整個存儲系統(tǒng)架構(gòu)不能夠適配云的彈性伸縮特征,還沿用以前機房的存儲架構(gòu),就不能最大化發(fā)揮云的特點。
云上天然是存算分離的場景,如何將整個生態(tài)里面的計算組件和存儲組件分離,分離后還能保證整體的計算效率以及擴展性等,都是底層的存儲系統(tǒng)需要考慮的問題。
小文件管理更多是數(shù)據(jù)湖需要考慮的問題,傳統(tǒng)的大數(shù)據(jù)平臺可能還是以大文件為主,但是小文件問題會隨著 AI 或者其它領(lǐng)域的數(shù)據(jù)進來后越來越凸顯。
針對以上每一個技術(shù)關(guān)鍵點都會有一些對應(yīng)的解決思路,如上圖所示。
2、JuiceFS
今天給大家介紹的 JuiceFS,定位是強一致性的分布式文件系統(tǒng),可以認(rèn)為這個設(shè)計目標(biāo)是用來完整替代 HDFS 的。
JuiceFS的整體架構(gòu)分為三塊,跟 HDFS 很像,元數(shù)據(jù)的存儲、數(shù)據(jù)的存儲、以及不同客戶端的接口。但其實每一塊都會有一些不一樣的設(shè)計。
首先元數(shù)據(jù)在 JuiceFS 里面是插件式的引擎設(shè)計,不同的場景可以選擇不同的數(shù)據(jù)庫,比如Redis、MySQL、TiKV等等,你可以根據(jù)業(yè)務(wù)場景、業(yè)務(wù)需求,挑選最合適的數(shù)據(jù)庫來作為JuiceFS的元數(shù)據(jù)引擎。
數(shù)據(jù)存儲方面, JuiceFS 主要基于對象存儲,可以最大化利用云上的存儲資源,所有數(shù)據(jù)都放到對象存儲里,但并不是簡單地寫到對象存儲里就完了,通過 JuiceFS 客戶端寫進來的數(shù)據(jù),會做一些格式處理(類似HDFS DataNode的block設(shè)計),元數(shù)據(jù)會盡量不依賴對象存儲的元數(shù)據(jù),因為前面提到了對象存儲的元數(shù)據(jù)是有很多問題的,如一致性問題、性能問題。JuiceFS不依賴對象存儲的元數(shù)據(jù),而是由自己獨立的元數(shù)據(jù)存儲來承擔(dān)所有的元數(shù)據(jù)請求。
元數(shù)據(jù)引擎可以橫向擴展,對于海量級(比如百億級)的文件,不管是大文件還是小文件,都能夠很輕松地存儲。在JuiceFS用戶的生產(chǎn)環(huán)境里也的確做到了百億級規(guī)模,很好地證明了存儲系統(tǒng)具有優(yōu)秀的擴展性。
緩存是很重要的特性,特別是在存算分離的場景下。如果需要升級到存算分離的架構(gòu)肯定要考慮緩存功能,不管是元數(shù)據(jù)的緩存,還是數(shù)據(jù)的緩存都是有必要的。
四、湖倉一體架構(gòu)在JuiceFS上的實踐
1、湖倉一體架構(gòu)
這是整體架構(gòu)圖,最下面既包含傳統(tǒng)的結(jié)構(gòu)化數(shù)據(jù),也有很多半結(jié)構(gòu)化和非結(jié)構(gòu)化數(shù)據(jù)。存儲層是 JuiceFS 結(jié)合對象存儲提供統(tǒng)一的存儲底座。
再往上是 Delta Lake、 Hudi 或者 Iceberg 這樣的數(shù)據(jù)管理層,它會基于底層的存儲系統(tǒng) JuiceFS 、 HDFS 或者對象存儲之上,再對整個數(shù)倉進行管理。
然后是各種查詢引擎、BI 工具、計算引擎接入不同的管理層組件。
2、元數(shù)據(jù)性能比較
上圖中比較的是以 OSS 為代表的對象存儲,以及 HDFS 和 JuiceFS 。左邊是元數(shù)據(jù)的 Latency,這個值越低越好;右邊是吞吐,值越大越好。
首先看藍色的對象存儲和另外兩個相比,Latency 在不同的元數(shù)據(jù)上操作的差別會很大。特別是前面提到的 Rename操作,相比另外兩個存儲系統(tǒng)來說,在對象存儲上有非常大的性能下降。HDFS 和 JuiceFS 在架構(gòu)設(shè)計上是相似的,都有獨立的元數(shù)據(jù)存儲,所以不管是 Latency 還是吞吐上都能做到比較快的程度。右邊這個圖中 JuiceFS 相比 HDFS 在吞吐上甚至能做得更好。
3、數(shù)據(jù)查詢性能比較
上圖是數(shù)據(jù)查詢性能比較。左邊這個圖是用 Spark 在對象存儲和 JuiceFS 上做的 TPC-DS 查詢測試。右邊這個圖是用 Presto 在 HDFS 和 JuiceFS 的測試。
左邊圖中可以看到,在查詢性能上, JuiceFS 相比直接使用對象存儲能有成倍的性能提升,特別是在一些相對比較復(fù)雜的查詢上(比如第九個查詢)的性能提升會更加明顯。
右邊圖中可以看到, JuiceFS 在充分緩存的情況下,存算分離的架構(gòu)也能夠做到和 HDFS 查詢性能相當(dāng)?shù)某潭取?/span>
所以綜合來看,不管是元數(shù)據(jù)的性能測試,還是整體基于 TPC-DS 的查詢測試,JuiceFS都能夠做到性能和HDFS一致,同時相比對象存儲有著大幅的性能優(yōu)勢。
四、Q&A
Q1: HDFS 不是存算分離架構(gòu)是不是意味著會被淘汰?
A1: 我覺得從中短期來看的話, HDFS 肯定不會被淘汰,因為它還是大數(shù)據(jù)生態(tài)里面事實意義上的標(biāo)準(zhǔn)。只是在大數(shù)據(jù)平臺上云之后,大家會重新思考在云上怎么搭建大數(shù)據(jù)平臺的存儲系統(tǒng)。有些公司可能還會選擇把機房的整套基礎(chǔ)設(shè)施都搬到云上,其實這樣做在成本上可能會比在機房里還高一些,不過至少保證整體架構(gòu)是經(jīng)過驗證的,但就達不到上云的初衷,沒法更多地利用云的特性。如果還是把基于 HDFS 的存算耦合架構(gòu)搬到云上其實沒有得到任何云的好處,所以很多公司開始想要去選擇對象存儲或者類似JuiceFS的新一代存儲系統(tǒng)也是基于這樣一個原因。
Q2: S3 對象存儲設(shè)計本身有 KV 設(shè)計的缺陷,那是不是也意味著淘汰?
A2: 是不一樣的定位,因為 S3 最初的定位不是為大數(shù)據(jù)生態(tài)設(shè)計,它的定位是很清晰的:存儲海量的非結(jié)構(gòu)化數(shù)據(jù),很容易擴展,可靠性足夠高,數(shù)據(jù)不能丟,存儲的成本要足夠的低(所以它用了像 EC這樣的技術(shù))。這些都是 S3 的優(yōu)勢,只要有這樣需求的場景,都會非常適用。但像大數(shù)據(jù)或者 AI 這類場景比較特別的一點在于,并不只是需要滿足存儲規(guī)模的需求就夠了,還需要滿足各種各樣其他的需求,比如性能的需求,整體對于業(yè)務(wù)的影響等等我們認(rèn)為更苛刻的需求,S3或?qū)ο蟠鎯κ菦]有辦法簡單滿足的,所以才需要有一些新的設(shè)計或者新的系統(tǒng),怎么基于對象存儲做進一步的改進和提升。S3 本身肯定是不會被淘汰的。
Q3: 存算分離架構(gòu),存算一體,哪個存儲架構(gòu)更適合哪些場景?
A3: 一般講存算分離或者存算耦合,更多是基于你當(dāng)下的整體架構(gòu)。如果是考慮在云上搭建整個數(shù)據(jù)平臺或者 AI 平臺的話,天然地就會去考慮更多利用云上的資源。云上資源的彈性能力要最大化發(fā)揮必然是要去朝著存算分離這個方向走的。即使一開始可能是存算耦合的架構(gòu),長遠來看還是需要去朝存算分離架構(gòu)走。如果沒有必要上云,而是在機房里有自己的一套私有云架構(gòu),用不用存算分離或者存算耦合,區(qū)別不大。更多還是怎么在存算分離的架構(gòu)下發(fā)揮云的優(yōu)勢。
Q4: JuiceFS 和 Alluxio 的差異。
A4: 這個問題問得挺好。在 JuiceFS 官方文檔里面有專門一篇比較 JuiceFS 和Alluxio,大家有興趣可以去官方文檔里看一下。簡單講一下,JuiceFS 的設(shè)計目標(biāo)或定位是分布式文件系統(tǒng),對標(biāo)的是 HDFS 這類傳統(tǒng)的分布式文件系統(tǒng)。我理解Alluxio的設(shè)計定位更多是一個緩存層,這個 緩存層的目標(biāo)并不是實現(xiàn)完整的文件系統(tǒng)特性,比如不需要去完整地兼容 POSIX,不需要提供各種各樣針對非大數(shù)據(jù)以外場景的特性。但是 JuiceFS 定位為分布式文件系統(tǒng),所以我們需要考慮很多文件系統(tǒng)需要考慮的點。可能 Alluxio和 JuiceFS 在某些特性上(比如緩存)有一些重合的地方,不代表這兩個項目的設(shè)計方向是一樣的。
Q5: 存算分離架構(gòu)效率比一體是不是要差一些。
A5: 如果只是簡單地把存儲和計算分離,不做任何優(yōu)化,效率肯定是會變低的。即使到現(xiàn)在網(wǎng)絡(luò)硬件技術(shù)已經(jīng)發(fā)展得很好的情況下,可能還是沒有本地的 I/O 效率高。所以只是簡單地拆分存儲和計算效率肯定會下降,因此才需要考慮存算分離之后怎么進一步地去優(yōu)化性能。盡量不要降低業(yè)務(wù)或損害業(yè)務(wù)的一些日常指標(biāo)。