
在開源大資料領域,存儲/計算分離已經成為共識和标準做法,資料湖架構成為大資料平台的首要選擇。基于這一範式,大資料架構師需要考慮三件事情:
- 第一,選擇什麼樣的存儲系統做資料湖(湖存儲)?
- 第二,計算和存儲分離後,出現了性能瓶頸,計算如何加速和優化(湖加速)?
- 第三,針對需要的計算場景,選擇什麼樣的計算引擎(湖計算)?
湖存儲可以基于我們熟悉的HDFS,在公共雲上也可以選擇對象存儲,例如阿裡雲OSS。在公共雲上,基于對象存儲建構資料湖是目前業界最主流的做法,我們這裡重點探讨第二個問題,結合阿裡雲上的EMR JindoFS優化和實踐,看看資料湖怎麼玩“加速”。
湖加速
在資料湖架構裡,湖存儲(HDFS,阿裡雲OSS)和湖計算(Spark,Presto)都比較清楚。那麼什麼是湖加速?大家不妨搜尋一下…(基本沒有直接的答案)。湖加速是阿裡雲EMR同學在内部提出來的,顧名思義,湖加速即為資料湖加速,是指在資料湖架構中,為了統一支援各種計算,對資料湖存儲提供适配支援,進行優化和緩存加速的中間層技術。這裡面出現較早的社群方案應該是Alluxio,Hadoop社群有S3A Guard,AWS有EMRFS,都适配和支援AWS S3,Snowflake在計算側有SSD緩存,Databricks有DBIO/DBFS,阿裡雲有EMR JindoFS,大體都可以歸為此類技術。
那麼為什麼需要湖加速呢?這和資料湖架構分層,以及相關技術演進具有很大關系。接下來,我們從三個方面的介紹來尋找答案。分别是:基礎版,要适配;标配版,做緩存;高配版,深度定制。JindoFS同時涵蓋這三個層次,實作資料湖加速場景全覆寫。
基礎版:适配對象存儲
以Hadoop為基礎的大資料和在AWS上以EC2/S3為代表的雲計算,在它們發展的早期,更像是在平行的兩個世界。等到EMR産品出現後,怎麼讓大資料計算(最初主要是MapReduce)對接S3,才成為一個真實的技術命題。對接S3、OSS對象存儲,大資料首先就要适配對象接口。Hadoop生态的開源大資料引擎,比如Hive和Spark,過去主要是支援HDFS,以Hadoop Compatible File System(HCFS)接口适配、并支援其他存儲系統。機器學習生态(Python)以POSIX接口和本地檔案系統為主,像TensorFlow這種深度學習架構當然也支援直接使用HDFS 接口。對象存儲産品提供REST API,在主要開發語言上提供封裝好的SDK,但都是對象存儲語義的,是以上述這些流行的計算架構要用,必須加以适配,轉換成HCFS接口或者支援POSIX。這也是為什麼随着雲計算的流行,适配和支援雲上對象存儲産品成為Hadoop社群開發的一個熱點,比如S3A FileSytem。阿裡雲EMR團隊則大力打造JindoFS,全面支援阿裡雲OSS并提供加速優化。如何高效地适配,并不是設計模式上增加一層接口轉換那麼簡單,做好的話需要了解兩種系統(對象存儲和檔案系統)背後的重要差異。我們稍微展開一下:
第一,海量規模。
對象存儲提供海量低成本存儲,相比檔案系統(比如HDFS),阿裡雲OSS更被使用者認為可無限擴充。同時随着各種BI技術和AI技術的流行和普及,挖掘資料的價值變得切實可行,使用者便傾向于往資料湖(阿裡雲OSS)儲存越來越多不同類型的資料,如圖像、語音、日志等等。這在适配層面帶來的挑戰就是,需要處理比傳統檔案系統要大許多的資料量和檔案數量。千萬級檔案數的超大目錄屢見不鮮,甚至包含大量的小檔案,面對這種目錄,一般的适配操作就失靈了,不是OOM就是hang在那兒,根本就不可用。JindoFS一路走來積累了很多經驗,我們對大目錄的listing操作和du/count這種統計操作從記憶體使用和充分并發進行了深度優化,目前達到的效果是,千萬檔案數超大目錄,listing操作比社群版本快1倍,du/count快21%,整體表現更為穩定可靠。
第二,檔案和對象的映射關系。
對象存儲提供key到blob對象的映射,這個key的名字空間是扁平的,本身并不具備檔案系統那樣的層次性,是以隻能在适配層模拟檔案/目錄這種層次結構。正是因為要靠模拟,而不是原生支援,一些關鍵的檔案/目錄操作代價昂貴,這裡面最為知名的就是rename了。檔案rename或者mv操作,在檔案系統裡面隻是需要把該檔案的inode在目錄樹上挪動下位置即可,一個原子操作;但是在對象存儲上,往往受限于内部的實作方式和提供出來的标準接口,擴充卡一般需要先copy該對象到新位置,然後再把老對象delete掉,用兩個獨立的步驟和API調用。對目錄進行rename操作則更為複雜,涉及到該目錄下的所有檔案的rename,而每一個都是上述的copy+delete;如果目錄層次很深,這個rename操作還需要遞歸嵌套,涉及到數量巨大的用戶端調用次數。對象的copy通常跟它的size相關,在很多産品上還是個慢活,可以說是雪上加霜。阿裡雲OSS在這方面做了很多優化,提供Fast Copy能力,JindoFS充分利用這些優化支援,結合用戶端并發,在百萬級大目錄rename操作上,性能比社群版本接近快3X。
第三,一緻性。
為了追求超大并發,不少對象存儲産品提供的是最終一緻性(S3),而不是檔案系統常見的強一緻性語義。這帶來的影響就是,舉個栗子,程式明明往一個目錄裡面剛剛寫好了10個檔案,結果随後去list,可能隻是部分檔案可見。這個不是性能問題,而是正确性了,是以在适配層為了滿足大資料計算的需求,Hadoop社群在S3A适配上花了很大力氣處理應對這種問題,AWS自己也類似提供了EMRFS,支援ConsistentView。阿裡雲OSS提供了強一緻性,JindoFS基于這一特性大大簡化,使用者和計算架構使用起來也無須擔心類似的一緻性和正确性問題。
第四,原子性。
對象存儲自身沒有目錄概念,目錄是通過适配層模拟出來的。對一個目錄的操作就轉化為對該目錄下所有子目錄和檔案的用戶端多次調用操作,是以即使是每次對象調用操作是原子的,但對于使用者來說,對這個目錄的操作并不能真正做到原子性。舉個例子,删除目錄,對其中任何一個子目錄或檔案的删除操作失敗(包含重試),哪怕其他檔案删除都成功了,這個目錄删除操作整體上還是失敗。這種情況下該怎麼辦?通常隻能留下一個處于中間失敗狀态的目錄。JindoFS在适配這些目錄操作(rename,copy,delete and etc)的時候,結合阿裡雲 OSS 的擴充和優化支援,在用戶端盡可能重試或者復原,能夠很好地銜接資料湖各種計算,在pipeline 上下遊之間保證正确處理。
第五,突破限制。
對象存儲産品是獨立演化發展的,少不了會有自己的一些獨門秘籍,這種特性要充分利用起來可能就得突破HCFS抽象接口的限制。這裡重點談下對象存儲的進階特性Concurrent MultiPartUpload (CMPU),該特性允許程式按照分片并發上傳part的方式高效寫入一個大對象,使用起來有兩個好處,一個是可以按照并發甚至是分布式的方式寫入一個大對象,實作高吞吐,充分發揮對象存儲的優勢;另外一個是,所有parts都是先寫入到一個staging區域的,直到complete的時候整個對象才在目标位置出現。利用阿裡雲OSS這個進階特性,JindoFS開發了一個針對MapReduce模型的Job Committer,用于Hadoop,Spark 和類似架構,其實作機制是各個任務先将計算結果按照part寫入到臨時位置,然後作業commit的時候再complete這些結果對象到最終位置,實作無須rename的效果。我們在Flinkfile sink connector支援上也同樣往計算層透出這方面的額外接口,利用這個特性支援了Exactly-Once的語義。
标配版:緩存加速
資料湖架構對大資料計算的另外一個影響是存/算分離。存儲和計算分離,使得存儲和計算在架構上解耦,存儲朝着大容量低成本規模化供應,計算則向着彈性伸縮,豐富性和多樣化向前發展,在整體上有利于專業化分工和大家把技術做深,客戶價值也可以實作最大化。但是這種分離架構帶來一個重要問題就是,存儲帶寬的供應在一些情況下可能會跟計算對存儲帶寬的需求不相适應。計算要跨網絡通路存儲,資料本地性消失,通路帶寬整體上會受限于這個網絡;更重要的是,在資料湖理念下,多種計算,越來越多的計算要同時通路資料,會競争這個帶寬,最終使得帶寬供需失衡。我們在大量的實踐中發現,同一個OSS bucket,Hive/Spark數倉要進行ETL,Presto要互動式分析,機器學習也要抽取訓練資料,這個在資料湖時代之前不可想象,那個時候也許最多的就是MapReduce作業了。這些多樣化的計算,對資料通路性能和吞吐的需求卻不遑多讓甚至是變本加厲。常駐的叢集希望完成更多的計算;彈性伸縮的叢集則希望盡快完成作業,把大量節點給釋放掉節省成本;像Presto這種互動式分析業務方希望是越快越好,穩定亞秒級傳回不受任何其他計算影響;而GPU訓練程式則是期望資料完全本地化一樣的極大吞吐。像這種局面該如何破呢?無限地增加存儲側的吞吐是不現實的,因為整體上受限于和計算叢集之間的網絡。有效地保證豐富的計算對存儲帶寬的需求,業界早已給出的答案是計算側的緩存。Alluxio一直在做這方面的事情,JindoFS核心定位是資料湖加速層,其思路也同出一轍。下面是它在緩存場景上的架構圖。
JindoFS在對阿裡雲OSS适配優化的同時,提供分布式緩存和計算加速,剛剛寫出去的和重複通路的資料可以緩存在本地裝置上,包括HDD,SSD和記憶體,我們都分别專門優化過。這種緩存加速是對使用者透明的,本身并不需要計算額外的感覺和作業修改,在使用上隻需要在OSS适配的基礎上打開一個配置開關,開啟資料緩存。疊加我們在适配上的優化,跟業界某開源緩存方案相比,我們在多個計算場景上都具有顯著的性能領先優勢。基于磁盤緩存,受益于我們能夠更好地balance多塊磁盤負載和高效精細化的緩存塊管理,我們用TPC-DS 1TB進行對比測試,SparkSQL性能快27%;Presto大幅領先93%;在HiveETL場景上,性能領先42%。JindoFS 的 FUSE支援完全采用 native 代碼開發而沒有 JVM 的負擔,基于SSD緩存,我們用TensorFlow程式通過JindoFuse來讀取JindoFS上緩存的OSS資料來做訓練,相較該開源方案性能快40%。
在資料湖架構下在計算側部署緩存裝置引入緩存,可以實作計算加速的好處,計算效率的提升則意味着更少的彈性計算資源使用和成本支出,但另一方面毋庸諱言也會給使用者帶來額外的緩存成本和負擔。如何衡量這個成本和收益,确定是否引入緩存,需要結合實際的計算場景進行測試評估,不能一概而論。
高配版:深度定制,自己管理檔案中繼資料
我們在JindoFS上優化好OSS适配,把Jindo分布式緩存性能做到效能最大化,能滿足絕大多數大規模分析和機器學習訓練這些計算。現有的JindoFS大量部署和使用表明,無論Hive/Spark/Impala這種數倉作業,Presto互動式分析,還是TensorFlow訓練,我們都可以在計算側通過使用阿裡雲緩存定制機型,來達到多種計算高效通路OSS資料湖的吞吐要求。可是故事并沒有完,資料湖的架構決定了計算上的開放性和更加多樣性,上面這些計算可能是最主要的,但并不是全部,JindoFS在設計之初就希望實作一套部署,即能覆寫各種主要場景。一個典型情況是,有不少使用者希望JindoFS能夠完全替代HDFS,而不隻是Hive/Spark夠用就可以了,使用者也不希望在資料湖架構下還要混合使用其他存儲系統。整理一下大概有下面幾種情況需要我們進一步考慮。
第一、上面讨論對象存儲适配的時候我們提到,一些檔案/目錄操作的原子性需求在本質上是解決不了的,比如檔案的rename,目錄的copy,rename和delete。徹底解決這些問題,完全滿足檔案系統語義,根本上需要自己實作檔案中繼資料管理,像HDFS NameNode那樣。
第二、HDFS有不少比較進階的特性和接口,比如支援truncate,append,concat,hsync,snapshot和Xattributes。像HBase依賴hsync/snapshot,Flink依賴truncate。資料湖架構的開放性也決定了還會有更多的引擎要對接上來,對這些進階接口有更多需求。
第三、HDFS重度使用者希望能夠平遷上雲,或者在存儲方案選擇上進行微調,原有基于HDFS的應用,運維和治理仍然能夠繼續使用。在功能上提供Xattributes支援,檔案權限支援,Ranger內建支援,甚至是auditlog支援;在性能上希望不低于HDFS,最好比HDFS還好,還不需要對NameNode調優。為了也能夠享受到資料湖架構帶來的各種好處,該如何幫助這類使用者基于OSS進行架構更新呢?
第四、為了突破S3這類對象存儲産品的局限,大資料業界也在針對資料湖深度定制新的資料存儲格式,比如Delta,Hudi,和Iceberg。如何相容支援和有力優化這類格式,也需要進一步考慮。
基于這些因素,我們進一步開發和推出JindoFS block模式,在OSS對象存儲的基礎上針對大資料計算進行深度定制,仍然提供标準的HCFS接口,因為我們堅信,即使同樣走深度定制路線,遵循現有标準與使用習慣對使用者和計算引擎來說更加容易推廣和使用,也更加符合湖加速的定位和使命。JindoFS block模式對标HDFS,不同的是采取雲原生的架構,依托雲平台我們做了大量簡化,使得整個系統具有彈性,輕量和易于運維的特點和優勢。
如上圖示,是JindoFS在block模式下的系統架構,整體上重用了JindoFS緩存系統。在這種模式下,檔案資料是分塊存放在OSS上,保證可靠和可用;同時借助于本地叢集上的緩存備份,可以實作緩存加速。檔案中繼資料異步寫入到阿裡雲OTS資料庫防止本地誤操作,同時友善JindoFS叢集重建恢複;中繼資料在正常讀寫時走本地RocksDB,記憶體做LRU緩存,是以支撐的檔案數在億級;結合中繼資料服務的檔案/目錄級别細粒度鎖實作,JindoFS在大規模高并發作業高峰的時候表現比HDFS更穩定,吞吐也更高。我們用HDFS NNBench做并發測試,對于最關鍵的open和create操作,JindoFS的IOPS比HDFS高60%。在千萬級超大目錄測試上,檔案listing操作比HDFS快130%;檔案統計du/count操作比HDFS快1X。借助于分布式Raft協定,JindoFS支援HA和多namespaces,整體上部署和維護比HDFS簡化太多。在IO吞吐上,因為除了本地磁盤,還可以同時使用OSS帶寬來讀,是以在同樣的叢集配置下用DFSIO實測下來,讀吞吐JindoFS比HDFS快33%。
JindoFS在湖加速整體解決方案上進一步支援block模式,為我們拓寬資料湖使用場景和支援更多的引擎帶來更大的想象空間。目前我們已經支援不少客戶使用HBase,為了受益于這種存/算分離的架構同時借助于本地管理的儲存設備進行緩存加速,我們也在探索将更多的開源引擎對接上來。比如像Kafka,Kudu甚至OLAP新貴ClickHouse,能不能讓這些引擎專注在它們的場景上,将它們從壞盤處理和如何伸縮這類事情上徹底解放出來。原本一些堅持使用HDFS的客戶也被block模式這種輕運維,有彈性,低成本和高性能的優勢吸引,通過這種方式也轉到資料湖架構上來。如同對OSS的适配支援和緩存模式,JindoFS這種新模式仍然提供完全相容的HCFS和FUSE支援,大量的資料湖引擎在使用上并不需要增加額外的負擔。
總結
行文至此,我們做個回顧和總結。基于資料湖對大資料平台進行架構更新是業界顯著趨勢,資料湖架構包括湖存儲、湖加速和湖分析,在阿裡雲上我們通過 JindoFS 針對各種場景提供多種資料湖加速解決方案。阿裡雲推出的專門支援資料湖管理的Data Lake Formation,可全面支援資料湖。
我們結合雲上數年的實踐經驗,沉澱了EMR JindoFS在湖加速上的各種場景、挑戰以及對應的技術方案。我們優化的思路有哪些,相較現有的社群方案,JindoFS有哪些優勢,希望通過本文讓同學們對阿裡雲上的資料湖方案有更加全面的認識,同時希望阿裡雲資料湖JindoFS/OSS + DataLake Formation + EMR能為同學們的大資料探索之旅帶來更多價值。