
作者 | Vineyard 團隊
來源 |
阿裡巴巴雲原生公衆号
Vineyard 是一個專為雲原生環境下大資料分析場景中端到端工作流提供記憶體資料共享的分布式引擎,我們很高興宣布 Vineyard 在 2021 年 4 月 27 日被雲原生基金會(CNCF)TOC 接受為沙箱(Sandbox)項目。
Vineyard 項目開源位址:
https://github.com/alibaba/v6d項目介紹
現有的大資料分析場景中,對于端到端任務,不同的子任務之間通常使用例如 HDFS、S3、OSS 這樣的分布式檔案系統或對象存儲系統,來共享任務之間的中間資料,這種方式在運作效率和研發效率上存在諸多問題,以下圖所示的一個風控作業工作流為例:
- 工作流中不同任務之間為了共享中間資料,前一個任務将結果寫入檔案系統,完成之後,後一個再将檔案讀出作為輸入,這個過程帶來了額外的序列化及反序列化、記憶體拷貝、以及網絡、IO 的開銷,我們從曆史任務中觀察到有超過 60% 的任務為此花費了 40% 以上的執行時間。
- 對于生産環境,為了高效地解決某一個特定範式的問題往往會引入一個新系統(例如分布式圖計算),但這樣的系統往往難以直接與工作流中的其他系統無縫銜接,需要很多重複的 IO、資料格式轉換和适配的研發工作。
- 使用外部檔案系統共享資料給工作流帶來了額外的中斷,因為往往隻有當一個任務完全寫完所有結果,下一個任務才能開始讀取和計算,這使得跨任務的流水線并行無法被應用。
- 現有的分布式檔案系統在共享中間資料時,特别是在雲原生環境下,并沒有很好的處理分布式資料的位置問題,造成網絡開銷的浪費,進而降低端到端執行效率。
為了解決現有大資料分析工作流中存在的上述問題,我們設計和實作了分布式記憶體資料共享引擎 Vineyard。
Vineyard 從以下三個角度來應對上述幾個問題:
- 為了使端到端工作流中任務之間的資料共享更加高效,Vineyard 通過記憶體映射的方式,支援系統間零拷貝的資料共享,省去了額外的 IO 開銷。
- 為了簡化新計算引擎接入現有系統所需要的适配和開發,Vineyard 對常見的資料類型,提供了開箱即用的抽象,例如 Tensor、DataFrame、Graph,等等,進而不同計算引擎之間共享中間結果不再需要額外的序列化和反序列。同時,Vineyard 将 IO、資料遷移、快照等可複用的元件以插件的形式實作,使其能夠很靈活地按需注冊到計算引擎中去,降低與計算引擎本身無關的開發成本。
- Vineyard 提供一系列 operators,來實作更高效靈活的資料共享。例如 Pipeline operator 實作了跨任務的流水線并行,使得後續任務可以随着前序任務輸出的産生,同時進行計算,提高了端到端整體效率。
- Vineyard 與 Kubernetes 內建,通過 Scheduler Plugin,讓任務的排程能夠感覺所需要的資料的局部性,在 Kubernetes 讓單個任務的 Pod 盡可能地排程到與 Pod 所需的輸入資料對其的機器上,來減小資料遷移需要的網絡開銷,提升端到端性能。
在初步的對比實驗中,相比于使用 HDFS 來共享中間資料,對于評測任務,Vineyard 能夠大幅降低用于交換中間結果引入的額外開銷,對于整個工作流的端到端時間有 1.34 倍的提升。
核心功能
接下來從 Vineyard 核心的設計與實作,以及 Vineyard 如何助力雲原生環境中大資料分析任務兩個方面來介紹 Vineyard 的核心功能。
1. 分布式記憶體資料共享
Vineyard 将記憶體中的資料表示為 Object。Object 可以是 Local 的,也可以是 Global 的,以分布式執行引擎 Mars 和 Dask 為例,一個 DataFrame 往往被拆分成很多個 Chunk 以利用多台機器的計算能力,每台機器上有多個 Chunk,這些 Chunk 是 Vineyard 中的 LocalObject,這些 Chunk 一起構成了一個全局的視圖,即 GlobalDataFrame。這個 GlobalDataFrame 能夠直接共享給其他計算引擎,如 GraphScope,作為圖資料的輸入。有了這些資料類型的抽象,Vineyard 上的不同計算引擎之間就可以無縫地共享中間結果,将一個任務的輸出直接用作下一個任務的輸出。
更具體地,Vineyard 中又是如果表達一個特定類型的 Object,使之能夠很容易地适配到不同的計算引擎中去呢?這得益于 Vineyard 在 Object 的表示上提供的靈活性。Vineyard 中,一個 Object 包括兩個部分,Metadata,以及一組 Blob。Blob 中存儲着實際的資料,而 Metadata 則用于解釋這些 Blob 的語義。例如對于 Tensor,Blob 是一段連續記憶體,存儲着 Tensor 中所有的元素,而 Metadata 中記錄了 Tensor 的類型、形狀、以及行主序還是列主序等屬性。在 Python 中,這個 Object 可以被解釋為一個 Numpy 的 NDArray,而在 C++ 中,這個 Object 可以被解釋為一個 xtensor 中的 tensor。這兩種不同程式設計語言的 SDK 中,共享這個 Tensor 不會帶來額外的 IO、拷貝、序列化/反序列化、以及類型轉換的開銷。
同時,Vineyard 中的 Metadata 是可嵌套的,這使得我們通過很容易地将任何複雜的資料類型描述為 Vineyard 中的 Object,不會限制計算引擎的表達能力。以 GlobalDataFrame 為例,見下圖中 Metadata 的結構。
2. 雲原生環境中資料與任務的協同排程
對于一個真實部署的大資料分析流水線,僅僅有任務之間的資料共享是遠遠不夠的。在雲環境中,一個端到端流水線中包含的多個子任務在被 Kubernetes 排程時僅僅考慮了需要的資源限制,連續的兩個任務的 co-locate 無法保證,在兩個任務之間共享中間結果時仍然有資料遷移引入的網絡開銷,如下圖,在運作 Task B 時,因為兩個任務的 Pod 沒有對齊,資料分片 A3、A4 需要被遷移到 Pod 所在的 Vineyard 執行個體上。
對此,Vineyard 通過 CRD 将叢集中的資料(Vineyard Objects)表示為可觀測的資源,并基于 Kubernetes 的 Scheduler Framework 設計和實作了一個考慮資料局部性的排程器插件。目前一個任務 Task A 完成後,從結果對象的 Metadata 中,排程器插件可以知道所有分片的位置,在啟動下一個任務時,排程器給資料所在的節點(圖中的 Node 1、Node 2)更高的優先級,使任務 Task B 也盡可能地被排程到對應的節點上,進而省去了資料遷移引入的額外開銷,來改善端到端的性能。
快速上手
Vineyard 內建了 Helm 以友善使用者安裝和部署:
helm repo add vineyard https://vineyard.oss-ap-southeast-1.aliyuncs.com/charts/
helm install vineyard vineyard/vineyard
安裝之後,系統中會部署一個 Vineyard DaemonSet,并暴露一個 UNIX domain socket 用于與應用的任務 Pod 之間的共享記憶體和 IPC 通信。
此外,還可以參考 Vineyard 的示範視訊:
https://www.youtube.com/watch?v=vPbF1l5nwwQ&list=PLj6h78yzYM2NoiNaLVZxr-ERc1ifKP7n6&t=585未來展望
Vineyard 已經作為分布式科學計算引擎 Mars 和一站式圖計算系統 GraphScope 的存儲引擎,Vineyard 助力大資料分析任務離不開與雲原生社群的緊密互動,未來Vineyard 會進一步地完善與社群其他項目如 Kubeflow、Fluid 等的內建,助力更多雲上大資料分析任務。
Vineyard 将繼續與社群同行,支援關注社群的回報,緻力于推動雲原生技術在大資料分析領域的生态建設和應用。歡迎大家關注 Vineyard 項目,加入 Vineyard 社群并參與項目的共建與落地!
2021 阿裡雲開發者大會重磅開啟!
數字時代,如何更好地利用雲的能力?什麼是新型、便捷的開發模式?如何讓開發者更高效地建構應用?科技賦能社會,技術推動變革,拓展開發者的能量邊界,一切,因雲而不同。
點選立即報名活動,
2021 阿裡雲開發者大會将給你答案。