天天看點

從 Hadoop 到雲原生,大資料平台如何做存算分離

作者:閃念基因

關于作者:

蘇銳,Juicedata 合夥人, JuiceFS 的1号成員,一直深度參與在開源社群中支援開發者使用 JuiceFS。曆任網際網路 O2O 汽車服務品牌功夫洗車創始人 & CEO,豆瓣電影 PM & Tech Lead。在工作期間,經曆了早期由 Hadoop 技術棧主導的大資料平台,到雲原生時代存算分離的架構變遷。

Hadoop 的誕生改變了企業對資料的存儲、處理和分析的過程,加速了大資料的發展,受到廣泛的應用,給整個行業帶來了變革意義的改變;随着雲計算時代的到來, 存算分離的架構受到青睐,企業開開始對 Hadoop 的架構進行改造。

今天與大家一起簡單回顧 Hadoop 架構以及目前市面上不同的存算分離的架構方案,他們的利弊各有哪些,希望可以給正在存算分離架構改造的企業一些參考和啟發。

01 - Hadoop 存算耦合架構回顧

2006 年 Hadoop 剛釋出,這是一個 all-in-one 的套裝,最早有三個核心的元件:MapReduce 負責計算,YARN 負責資源排程,HDFS 分布式檔案系統,負責存資料。

從 Hadoop 到雲原生,大資料平台如何做存算分離

在這三個元件中,發展最迅速和多元的是計算元件這一層,最早隻有一個 MapReduce,但業界很快在計算層上面各顯神通,造出了一大堆的輪子,包括有 MapReduce,Tez,Spark 這樣的計算架構,Hive 這類資料倉庫,還有 Presto、Impala 查詢引擎,各種各樣的元件。配合這些元件的,還有像 scoop 這樣的資料流轉采集的元件也很豐富,一共有幾十款。

從 Hadoop 到雲原生,大資料平台如何做存算分離

底層存儲經過了大概 10 年左右的時間,一直是 HDFS 一枝獨秀,帶來的一個結果就是它會成為所有計算元件預設的設計選擇。上面提到的這些大資料生态裡發展出來的各種元件,都是面向HDFS API 去做設計的。有些元件也會非常深入的利用 HDFS 的一些能力,比如深入看 Hbase,在寫 WAL log 的時候就直接利用了HDFS 的一些很核心的能力,才能達到一個低延遲時間的寫入;比如說像最早的 MapReduce 和 Spark 也提供了資料親和性(Data Locality)的能力,這些都是HDFS 提供的一些特殊的 API。

這些大資料元件面向 HDFS API 設計的做法, 為後續資料平台上雲帶來了潛在的挑戰。

下面是一個簡化的局部的架構圖,通過這張圖快速了解 Hadoop 存算耦合架構。在這張圖有三個節點,每個節點裡面它都承載了 HDFS DataNode 的存資料的角色,但同時 YARN 也會在這裡布一個 Node Manager的程序。有了 Node Manager 之後,YARN 就會認為 HDFS DataNode 的節點,在其管理範圍之内,當需要計算任務可以分發到這個節點上來完成。存儲任務和資料就在同一個機器裡了,計算的時候就可以直接讀到磁盤上的資料。

從 Hadoop 到雲原生,大資料平台如何做存算分離

為什麼 Hadoop 在設計之初是一個存儲計算耦合的架構?

一個不能忽略的重要的原因是,網絡通訊和硬體的局限。2006年,當時雲計算幾乎還沒有發展,亞馬遜才釋出第一個服務而已。

在機房裡面,當時我們面對的最大的問題就是網卡,主流的還是百兆網卡,剛開始用千兆網卡。這個時候,大資料使用的磁盤,吞吐大概是 50MB/s,對網絡帶寬來說要乘以 8,也就是 400M bps;如果一個節點裡放 8 塊盤,吞吐都跑起來,就需要幾千兆帶寬傳輸了,但是網卡最高也就1Gb。這就意味着每一個節點網絡帶寬根本不夠,無法讓這個節點裡面的所有的磁盤的能力都發揮出來。是以如果計算任務在網絡的一端,資料在資料節點在網絡的另一端,計算任務需要說通過網絡傳輸來進行,網絡帶寬是一個最明顯的瓶頸。

02 - 存算分離的需求出現

首先從,企業的需求看,從 2006 年發展到 2016 年左右,這十年我們看到了一些新的變化,第一企業資料增長很快,但是算力的需求其實長得沒那麼快。這些任務靠人開發,不會發生一天一倍的去漲的情況,但是産生的資料的速度是是非常快的,有可能是指數型的;而且有些資料産生出來,也不一定馬上知道怎麼用,但未來會用,是以企業都會先把資料盡可能全量的去存起來,再去挖掘它的價值。

在這個背景下,存算耦合的硬體的拓撲的架構就給擴容帶來了一個影響,當存儲不夠,就要去加機器。但是不能隻加機器,不能隻有硬碟,因為在存算耦合的架構上,資料的節點還需要負責計算,是以 CPU 和記憶體也不能太差。是以配置的機器都是計算與存儲配置非常平衡的機器,在提供足夠存儲容量的同時,也提供了等量的算力。但實際場景中算力的需求沒漲。這樣擴出來的算力對企業來說造成了更大的浪費,整個叢集在存儲和 I/O 上的資源使用率可能是非常不平衡的,當叢集越大,這種不平衡就越嚴重。而且另外買機器也挺難的,購買的機器必須是計算與存儲平衡的。

而且,資料排程親和性的政策在實際的業務中未必能發揮作用,因為資料有可能會有很明顯的傾斜,可能會有很局部的熱點,需要非常多的算力。大資料平台的任務可能排程到有限節點上,I/O 仍然有可能成為瓶頸。

在這個過程中硬體也有變化,給存算分離架構帶來了可行性。首先,10Gb萬兆網卡普及了,今天機房裡或者包括雲上也開始有更多的 20Gb、40Gb,甚至 50Gb,有些 AI 的場景甚至有100Gb的網卡,網絡的帶寬其實加大了比以前提升了100倍之多。

從 Hadoop 到雲原生,大資料平台如何做存算分離

存儲方面,在今天大的資料叢集裡面,許多企業還是使用磁盤來存儲,磁盤的吞吐提升了一倍,從 50MB/s 每秒提升到 100MB/s。一個配置了萬兆的網卡的執行個體,可以支援差不多 12 塊磁盤的峰值吞吐,對于大部分企業來說已經夠用了,以前網絡傳輸的瓶頸就基本不存在了。

不僅網卡,磁盤也在變化,軟體也在變化。最早的時候,我們可能用 csv 或者打一個 zip 包,現在有了更高效的壓縮算法,比如說有 snappy、lz4、zstandard 這些。而且有了 Avro、Parquet、Orc 這些列存格式。

這些變化加在一起,都進一步減小了需要傳輸的資料量。同時, 網卡在提升,再加上硬硬碟本身的吞吐沒增加多少,企業以前曾經要面對的 I/O 的瓶頸就逐漸的在弱化甚至消除,保證了存算分離的可行性。

03- 如何實作存算分離?

最初的嘗試:在雲上獨立部署 HDFS

從2013、2014年,行業内開始看到一些存算分離架構的嘗試。最初的方案比較簡單,就是獨立部署 HDFS,不再和負責計算 worker 去混合部署。這個方案在 Hadoop 生态裡,沒有引入任何的新元件。

從下面的示意圖可以看到, DataNode 節點上不再部署 Node Manager,意味着不再把計算任務發送到 DataNode 節點上。存儲成為一個獨立叢集,計算需要用到的資料都會通過網絡來傳輸,端到端的萬兆網卡去支援,網絡傳輸線沒有在下圖示出。

在這個改變裡,盡管 HDFS 最巧妙的資料本地性這個設計被舍棄了,但由于網絡通訊速度的提高, 給叢集的配置帶來更大的便利。Juicedata 創始人 Davies,2013 年在 Facebook 工作期間,團隊就做了這樣的實驗, 發現這樣的一個存算分離的改造,對整個平台性能的影響是僅僅是幾個百分點,但是給叢集的配置管理帶來了一個還很大的便利,可以獨立的部署和管理計算節點了。

但是這個嘗試沒有得到進一步發展,是什麼原因呢?最大的一個原因,當在機房做這樣的改造是可行的,但當我們去使用雲上資源的時候,這個方案的弊端就顯露了。

首先,源自 HDFS 的多副本機制在雲上會增加企業的成本。過去,企業在機房使用裸硬碟去搭建一套 HDFS,為了解決裸硬損壞的風險, HDFS 設計了多副本的機制,來保證資料安全性;同時多副本還承載着保證資料可用性的作用。除了磁盤損壞,當某一個 DataNode 的節點臨時當機了,這個節點上的資料通路不到了?多副本機制在可靠性和可用性上都發揮作用。當資料被遷移到雲上時,雲提供給使用者的是經過多副本機制存儲的雲盤,不再是裸硬碟了,企業用這塊雲盤去搭一個HDFS,又要做3副本,企業資料在雲上要存 9 副本,成本立馬飙升了好幾倍。

後來,雲也會提供一些有裸硬碟的機型,但是這類機型往往都非常少,比如說雲上有 100 款虛拟機,雲盤可以任意配置,但是有裸盤的機型隻有 5~10 款,選擇餘地比較少,這些型号不一定能比對企業的叢集需要。

第二個原因, 這個方案不能讓企業得到雲上的獨特價值,比如開箱即用,彈性伸縮,以及按量付費這些雲上最大的優勢。在雲上部署 HDFS, 需要自己建立機器,手動部署和維護,自己監控和運維,而且還不能友善地擴縮容。這種情況下,HDFS 上雲實作存算分離,仍然有其痛點。

第三個原因,HDFS 本身的局限。首先是,NameNode,隻能垂直擴充,并不能分布式擴充說擴出更多的 NameNode 節點,限制了 HDFS 單叢集去管理的檔案數量。

當 NameNode 的資源占用比較多,負載又高的時候就有可能會觸發 FullGC(Garbage Collection) 。一旦觸發這個問題之後,它會影響到整個 HDFS 叢集可用性。系統存儲可能當機,不能讀,又無法幹預 GC的過程,系統卡多久無法确定。這個也是 HDFS 高負載叢集一直以來的痛點。

根據實際運維經驗,一般在 3 億檔案以内,運維 HDFS 還是比較輕松的,3 億檔案之後運維的複雜度就會明顯提升,峰值可能就在 5 億檔案左右,就達到單機群的天花闆了。檔案量更多,需要引入 HDFS的 Federation 聯邦的機制,但是它就增加了很多的運維和管理的成本。

公有雲+ 對象存儲

随着雲計算技術的成熟,企業存儲又多了一個選項,對象存儲。不同的雲廠商有不同的英文縮寫名,例如阿裡雲的對象存儲服務叫做 OSS,華為雲 OBS,騰訊雲 COS,七牛 Kodo;對象存儲适用于大規模存儲非結構化資料的資料存儲架構,其設計的初衷是想滿足非常簡單的上傳下載下傳資料,企業存儲系統擁有超級強大的彈性伸縮的能力,還能保證低成本的存儲。

最早從 AWS 開始,後來所有的雲廠商其實都在往這個方向發展,開始推動用對象存儲去替代 HDFS。這些方案首先帶來了兩個 HDFS 無法實作的最明顯的好處:

  • 第一,對象存儲是服務化的,開箱即用,不用做任何的部署監控運維這些工作,特别省事兒。
  • 第二,彈性伸縮,企業可以按量付費,不用考慮任何的容量規劃,開一個對象存儲的 bucket ,有多少資料寫多少資料,不用擔心寫滿。

這些方案相比在雲上獨立部署 HDFS , 運維方面是有了很大的簡化。但當對象存儲被用來去支援複雜的 Hadoop 這樣的資料系統,就會發現如下的一些問題。

1. 檔案 Listing 的性能比較弱。Listing 是檔案系統中最基礎的一個操作。我們在檔案系統中 List 目錄,包括 HDFS 裡面 List 目錄,都是非常輕量快的操作。它的性能是源于在檔案系統中,資料是一個樹形結構。

對象存儲沒有樹形結構的,它的整個存儲結構是扁平的。當使用者需要存儲成千上萬,甚至數億個對象,對象存儲需要做的是用 Key 去建立一份索引,Key 可以了解為檔案名是該對象唯一辨別符。如果使用者要執行 Listing,隻能在這個索引裡面去搜尋,搜尋的性能相比樹形結構的查找弱很多。

從 Hadoop 到雲原生,大資料平台如何做存算分離

檔案系統的結構:樹狀,适用于按目錄組織資料進行計算處理

對象存儲的結構:扁平,适用于資料存儲和直接通路

2. 對象存儲沒有原子 Rename, 影響任務的穩定性和性能。在 ETL 的計算模型中,每個子任務完成會将結果寫入臨時目錄,等到整個任務完成後,把臨時目錄改名為正式目錄名即可。

這樣的改名操作在 HDFS 和其他檔案系統中是原子的,速度快,而且有事務性保證。但由于對象存儲沒有原生目錄結構,處理 rename 操作是一個模拟過程,會包含大量系統内部的資料拷貝,會耗時很多,而且沒有事務保證。

使用者在使用對象存儲時,常用檔案系統中的路徑寫法作為對象的 Key,比如 “/order/2-22/8/10/detail”。改名操作時,需要搜尋出所有 Key 中包含目錄名的對象,用新的目錄名作為 Key 複制所有的對象,此時會發生資料拷貝,性能會比檔案系統差很多,可能慢一兩個數量級,而且這個過程因為沒有事務保證,是以過程中有失敗的風險,造成資料不正确。這樣看起來很細節的差異對整個任務 pipeline 的性能和穩定性都會有影響。

對象存儲資料最終一緻性的機制,會降低計算過程的穩定性和正确性。舉個例子,比如多個用戶端在一個路徑下并發建立檔案,這是調用 List API 得到的檔案清單可能并不能包含所有建立好的檔案清單,而是要等一段時間讓對象存儲的内部系統完成資料一緻性同步。這樣的通路模式在 ETL 資料進行中經常用到,最終一緻性可能會影響到資料的正确性和任務的穩定性。

為了解決對象存儲存在無法保持強資料一緻性的問題。AWS 釋出過一個名為 EMRFS 的産品。AWS EMRFS 的做法是,因為知道 Listing 結果可能不對,是以另外準備一個 DynamoDB 資料庫, 比如 Spark 在寫檔案的時候,同時也寫一份檔案清單到 DynameDB 裡,再建立一個機制,不斷調用對象存儲的 List API,和資料庫裡面存下來的結果做比較,直到相等了再傳回。但這個機制的穩定性不好,它會受對象存儲所在的區域的負載高低影響忽快忽慢,不是一個理想的解決方式。

除了上述由于檔案系統和對象存儲本身差異帶來的問題外,在對象存儲上使用 Hadoop 的另一大問題,就是對象存儲對于 Hadoop 元件的相容性相對弱。在文章開頭 Hadoop 架構介紹中提到了 HDFS 是 Hadoop 生态早期幾乎唯一的存儲選擇,上層各種各樣的元件都是面向 HDFS API 開發的。而到了對象存儲上,資料存儲的結構變了, API 也變了。

雲廠商為了能夠與現有的這些 Hadoop 元件适配,一方面需要去改造元件和雲對象存儲之間的 connector,另一方面還需要給上層的元件去打 patch ,對于每一個元件都一一的去驗證相容性,這對公有雲廠商來說意味着巨大的工作量。是以,目前公有雲它提供的大資料元件裡面能包含的計算元件是有是有限的,一般隻能包含 Spark、 Hive、 Presto 三個常用元件,而且還隻能包含少數幾個版本。這樣就會給将大資料平台遷移上雲,或者有需要使用自己的發行版群組件需求的使用者帶來了挑戰。

企業如何能夠享受到對象存儲的強大性能,同時又兼顧檔案系統的準确性?

對象存儲 + JuiceFS

當使用者想在對象存儲上去進行複雜的資料計算、分析訓練這些場景的時候,對象存儲确實無法滿足企業的需求;這也是我們去做 JuiceFS 的一個出發點,希望能夠站在對象存儲之上去補充他不擅長的部分,與對象存儲一起以比較低廉的價格服務好密集性的資料計算、分析、訓練這些場景。

JuiceFS + 對象存儲是如何工作的呢?通過下圖 JuiceFS 在 Hadoop 叢集中的部署方式,簡單介紹原理。

從下面這個簡單的示意圖看到, YARN 管理的這些執行節點上,都帶一個 JuiceFS Hadoop SDK, 這個 SDK 可以保證完整相容 HDFS。圖檔下方可以看到, SDK 它需要通路兩個部分,左側是 JuiceFS Meta Engine,右側是 S3 bucket。Metadata engine 就相當于 HDFS裡的 NameNode,整個檔案系統的中繼資料資訊會存儲在這裡,中繼資料資訊包括目錄數、檔案名,權限時間戳這些資訊,并且相應的解決掉了 HDFS NameNode 擴充性 、GC 這些的痛點。

從 Hadoop 到雲原生,大資料平台如何做存算分離

另外一邊,資料存在 S3 bucket 裡面,這裡的 S3 bucket 等同于HDFS 中的 DataNode,可以将它看成一大堆海量的磁盤來用,它會管理好的資料存儲和副本的相關任務。JuiceFS 就是三個元件組成,JuiceFS Hadoop SDK, Metadata Engine 和 S3 Bucket。

相較于直接使用對象存儲, JuiceFS 還有哪些優勢呢?

  1. HDFS 100% 完整相容。這得益于我們最初完整相容 POSIX 的這個設計。POSIX API 的覆寫程度以及複雜程度是大于 HDFS的,HDFS 在設計的時候就是去簡化了 POSIX,因為最先去實作複雜的 API 集,再去簡化它就變得非常容易了,是以這也是 JuiceFS 能實作 100%實作 HDFS 完整相容性的一個原因。
  2. 同時, 使用者可以和 HDFS 一起使用,無需完全替換 HDFS。這也得益于 Hadoop 系統的設計,在一個 Hadoop 叢集裡,可以配置多個檔案系統,JuiceFS 和 HDFS 可以同時使用,并不是互相替代的關系,而是可以互相合作。這樣的架構給我們我們現有的叢集帶來的好處是使用者不用完整替代現有的 HDFS 叢集,完整替代的工作量和風險上都太大了。使用者可以結合着業務,結合着叢集的情況,分步分批的去做融合。
  3. 中繼資料性能強大,JuiceFS 将中繼資料引擎獨立出來不再依賴于 S3 裡面的原資料性能,保證了中繼資料的性能。使用 JuiceFS 的時候,對底層對象存儲的調用簡化到隻是 get、 put、delete 這三個最基礎的操作,像 listing, update 等指令都用不到,在這樣的架構下,使用者就避開了對象存儲中繼資料性能弱的問題,最終一緻性這些問題也都不再存在了。
  4. 原子 rename, 因為有獨立的原資料引擎,JuiceFS 也可以支援原子 rename。
  5. 緩存,有效提升熱資料的通路性能,提供了 data locality 特性。緩存可以讓熱資料緩存到執行器 worker 節點本地的一些磁盤空間上。有了緩存後,會反複通路的熱資料,不需要每次都通過網絡去對象存儲裡面讀資料。而且 JuiceFS 特意實作了HDFS 特有的資料本地性的 API,讓所有支援資料本地性的上層元件都能重新獲得資料親和性的感覺,這會讓 YARN 把自己的任務優先排程到已經建立緩存的節點上面,綜合的性能可以和存儲計算耦合的 HDFS 相當的。
  6. 相容 POSIX, 與機器學習、AI 相關的任務應用結合友善。JuiceFS 還相容 POSIX,可以和機器學習, AI相關的這些業務更便捷地融合。

小結

伴随着企業需求的更疊、基礎技術的發展,存儲和計算的架構在變,從最初的耦合到分離;實作存算分離方式多樣,各有利弊,從直接将 HDFS 部署到雲上,到使用公有雲提供相容 Hadoop的方案,再到公有雲 + JuiceFS 這樣的适合在雲上進行複雜大資料計算和存儲的方案。對于企業來說,沒有銀彈,結合自身需求做架構選型才是關鍵。

但無論選什麼,保持簡單都不會錯。

作者:蘇銳

來源:微信公衆号:Juicedata

出處:https://mp.weixin.qq.com/s?__biz=Mzg5MjUyNjExMw==&mid=2247487687&idx=1&sn=0cb8b390e531c7d0225f238304bc7be3

繼續閱讀