Apache Hudi X Apache Kyuubi,中國移動雲湖倉一體的探索與實踐

分享嘉賓:孫方彬 中國移動雲能力中心 軟件開發工程師

編輯整理:Hoh Xil

出品平臺:DataFunTalk

 

導讀:在雲原生 + 大數據的時代,隨着業務數據量的爆炸式增長以及對高時效性的要求,雲原生大數據分析技術,經歷了從傳統數倉到數據湖,再到湖倉一體的演進。本文主要介紹移動云云原生大數據分析 LakeHouse 的整體架構、核心功能、關鍵技術點,以及在公有云 / 私有云的應用場景。

主要內容包括:

  • 湖倉一體概述

  • 移動雲 LakeHouse 實踐

  • 應用場景

01 湖倉一體概述

1. 關於湖倉一體

“湖倉一體” 是最近比較火的一個概念,“湖倉一體” 的概念最早起源於 Databricks 公司提出的 Lakehouse 架構,它不是某個產品,而是數據管理領域中的一種開放的技術架構範例。隨着大數據和雲原生技術的發展和融合,湖倉一體更能發揮出數據湖的靈活性與生態豐富性,以及數據倉庫的成長性。這裏的成長性包括:服務器的成本,業務的性能,企業級的安全、治理等特性。

大家可以看到(左圖),在特定業務規模前,數據湖的靈活性有一定優勢,隨着業務規模的增長,數據倉庫的成長性更有優勢。

湖倉一體的 2 個關鍵點:

  • 湖和倉的數據 / 元數據在不需要用戶人工干預的情況下,可以無縫打通、自由順暢地流(包括:由外向內入湖、由內向外出湖、圍繞周邊環湖);

  • 系統根據特定的規則自動地將數據在湖倉之間進行緩存和移動,並能與數據科學相關的高級功能打通,進一步實現敏捷分析和深度智能。

2. 主要理念

隨着業務數據量的爆炸式增長以及業務對高時效性的要求,大數據分析技術經歷了從傳統數倉到數據湖,再到湖倉一體的演進。傳統基於 Hadoop 的大數據平臺架構也是一種數據湖架構,湖倉一體的核心理念以及與當前 Hadoop 集羣架構的區別大致如下:

  • 存儲多種格式的原始數據:當前 Hadoop 集羣底層存儲單一,主要以 HDFS 爲主,對於湖倉一體來說,逐漸會演進爲支持多種介質,多種類型數據的統一存儲系統

  • 統一的存儲系統:當前根據業務分多個集羣,之間大量數據傳輸,逐漸演進到統一存儲系統,降低集羣間傳輸消耗

  • 支持上層多種計算框架:當前 Hadoop 架構的計算框架以 MR/Spark 爲主,未來演進爲在數據湖上直接構建更多計算框架和應用場景

湖倉一體的產品形態大致有兩類:

  • 基於公有云上數據湖架構的產品和解決方案(例如:阿里雲 MaxCompute 湖倉一體、華爲雲 FusionInsight 智能數據湖)

  • 基於開源 Hadoop 生態的組件(DeltaLake、Hudi、Iceberg)作爲數據存儲中間層(例如:Amazon 智能湖倉架構、Azure Synapse Analytics)

02 移動雲 LakeHouse 實踐

下面介紹移動雲 LakeHouse 的整體架構及對湖倉一體的探索和實踐:

1. 整體架構

上圖是我們的整體架構圖,名字叫雲原生大數據分析 LakeHouse。雲原生大數據分析 LakeHouse 採用計算和存儲分離架構,基於移動雲對象存儲 EOS 和內置 HDFS 提供了支持 Hudi 存儲機制的湖倉一體方案,通過內置 Spark 引擎進行交互式查詢,可以快速洞察業務數據變化。

我們的架構具體包括:

  • 數據源:包括 RDB、Kafka、HDFS、EOS、FTP,通過 FlinkX 一鍵入湖

  • 數據存儲(數據湖):我們內置了 HDFS 和移動雲的 EOS,藉助 Hudi 實現 Upsert 能力,達到近實時的增量更新,我們還適當地引入 Alluxio,進行數據緩存,來達到數據分析的 SQL 查詢加速能力。

  • 計算引擎:我們的計算引擎都是 Severless 化的,跑在 Kubernetes 中。我們引入了統一資源訪問 / 調度組件 YuniKorn,類似於傳統 Hadoop 生態體系中 YARN 的資源調度,會有一些常見的調度算法,比如共性調度,先進先出等常見的調度

  • 智能元數據:智能元數據發現,就是將我們數據源的數據目錄轉化成內置存儲中的一個 Hive 表,統一進行元數據管理

  • 數據開發:SQLConsole,用戶可以直接在頁面上編寫 SQL 進行交互查詢;還有 SDK 的方式,以及 JDBC/ODBC 接口;後續我們會支持 DevIDE,支持在頁面上的 SQL 開發

2. 核心功能

核心功能主要有以下四方面:

① 存儲和計算分離:

  • 存儲層與計算層分離部署,存儲和計算支持獨立彈性擴縮容,相互之間沒有影響

  • 存儲支持對象存儲和 HDFS,HDFS 存儲結構化數據,提供高性能存儲,對象存儲存儲非結構化、原始數據、冷數據,提供高性價比

  • 計算支持多引擎,Spark、Presto、Flink 均實現 serverless 化,即開即用,滿足不同查詢場景

② 一鍵入湖:

  • 支持連接移動云云上雲下多種數據庫、存儲、消息隊列

  • 入湖流程自動化,降低用戶的配置成本

  • 降低對數據源的額外負載,控制在 10% 以內,支持根據數據源的實例規格自動調整連接數(比如在 MySQL 同步數據時,會在 MySQL 負載允許的情況下,自動調整連接數)

  • 支持增量更新(通過 Hudi 實現增量更新)

③ 智能元數據發現:

  • 基於特定的規則,智能識別結構化、半結構化文件的元數據,構建數據目錄

  • 自動感知元數據變化

  • 統一元數據,提供類 HiveMeta API,針對不同計算引擎訪問底層數據

  • 智能數據路由和權限統一管控(藉助移動雲的賬號體系和 Ranger 實現的)

④ 按量計算:

  • 存儲資源按照使用量計費

  • 計算資源支持多種計費模式

  • 支持彈性調整租戶集羣資源規格,快速擴縮容

3. 基於 RBF 的邏輯視圖

在基於 Hive 構造的數據湖體系中,每個 Hive db 通常對應一個數倉實例,共享統一的存儲 HDFS,爲了實現存儲資源的多租戶隔離特性,我們借鑑 RBF 的統一視圖隔離能力,通過 Zookeeper 上不同的 Znode 來隔離多個數倉實例 StateStore,使每個數倉擁有自己獨立的邏輯視圖,同時利用 RBF 掛載多 NameSpace 的能力來實現 NameNode 負載均衡的效果。此外,爲順應雲原生趨勢,我們將 RBF 服務容器化部署,在創建 Hive db 時指定由 RBF 構成的 HDFSschema 路徑,可以實現資源快速的創建、擴展和回收。

上圖是我們的一個簡單的架構圖,RBF 以 Pod 的形式部署在 Kubernetes 中,然後 Hivedb 分別映射爲一個 RBF 的 schema 路徑。然後,下面是藉助了 NameSpace 的負載均衡能力。

這樣,通過爲用戶提供單獨的存儲邏輯視圖,不僅可以隔離不同數倉實例之間的數據,又能借助 RBF 對底層 HDFS 的負載均衡來實現對 Hive 數據的負載均衡能力。

例如,對 Hive db 目錄 hivedbdir 通過 RBF 方式 mount 到兩個 Namespace,掛載命令如下:

$ hdfs dfsrouteradmin -add/hivedbdir ns1,ns2 /data -order HASH_ALL

4. Hive 在對象存儲的多租戶實現

在公有云場景下,不同用戶的 bucket 認證信息不同,需要多次配置並重啓 HiveServer 服務,無法在對象存儲上實現 Hive 多租戶的效果。爲解決這個問題,我們通過修改 Hive 源碼在表屬性 tblproperties 中添加 s3 的認證參數,在訪問 bucket 時加載表屬性中的認證信息至 threadlocal conf 變量,來完成 session 級別的認證參數傳遞。這樣就在不重啓 Hive 服務的情況下支持了多 bucket 認證,達到了對象存儲上的 Hive 多租戶效果。

如圖所示,如果在服務端爲用戶配置不同的參數,就需要重啓服務,這時不能夠接受的。經過我們的改造之後,建表語法就變成了下面這種格式:

create external table testcephtbl(id int) location 's3a://bucket1/tmp/testlocation' tblproperties('fs.s3a.access.key'='xxx,'fs.s3a.endpoint'='xxx','fs.s3a.secret.key'='xxx);

5. 優化引擎訪問對象存儲

在大數據生態中,多種計算引擎都可以通過 Metastore 服務訪問 Hive 中的數據,例如 SparkSQL 要訪問存在對象存儲中的 Hive 數據,需要在提交作業的 Driver 模塊中根據表的 location 信息加載對應 bucket 認證信息,SQL 提交命令如下:

$SPARK_HOME/bin/beeline-u “jdbc:hive2://host:port/default?fs.s3a.access.key=xxx;fs.s3a.endpoint=xxx;fs.s3a.endpoint=xxx”-e “selecta.id from test1 a join test2 on a.id=b.id”

也就是說,用戶需要感知數據是存在對象存儲中,並且很難確定一個 SQL 中的多個表屬於哪幾個 bucket,嚴重影響了業務開發進度。爲此,我們基於之前的 Hive 表屬性實現了獲取對象存儲認證參數插件,用戶無需感知 SQL 中的表來自哪個 bucket,也無需在提交 SQL 時指定認證參數。如上圖橙色框所示,Spark SQL 在 Driver 中實現參數,來匹配認證參數信息。對 MetaStore 來說是一個統一的訪問視圖。

最終提交 SQL 作業命令如下:

$SPARK_HOME/bin/beeline -u “jdbc:hive2://host:port/default”-e “select a.id from test1 a join test2 ona.id=b.id”

6. Serverless 實現

這裏以 Spark 爲例,通過 RBF 的多租戶實現,Spark 進程運行在安全隔離的 K8S Namespace 中,每個 Namespace 根據資源規格對應不同的計算單元(例如:1CU=1 core * 4GB)。對於微批的場景,使用 SQL Console 每提交一個 task,engine 模塊會啓動一個 Spark 集羣,爲 Driver 和 Executor 按特定的算法申請相應的計算資源來運行計算任務,任務結束後資源即刻回收;對於即席 ad-hoc 的場景,可以使用 JDBC 提交 task,engine 模塊通過 Kyuubi 服務啓動一個 session 可配置的 spark 集羣,長駐一段時間後回收資源;所有的 SQL task 只有在運行成功後按實際的資源規格計費,如果不使用是不收費的。

邏輯視圖如上,我們的 Kubernetes 通過每個 Namespace 把資源進行隔離;上面是一個統一調度的 YuniKorn 進行 Capacity Management/Job Scheduling 的調度。再往上是 SQL Parser 組件,會把 SparkSQL 和 HiveSQL 語法進行兼容;最上方,我們還提供了 Spark JAR 的方式,能夠支持分析 HBase 或者其它介質中結構化 / 半結構化的數據。

通過 Serverless 的實現,我們大大的降低了用戶的使用流程。

沒有用 Serverless 時的流程:

① 購買服務器,構建集羣

② 部署一套開源大數據基礎組件:HDFS、Zookeeper、Yarn、Ranger、Hive 等

③ 利用不同工具導入數據

④ 編寫查詢 SQL 計算,輸出結果

⑤ 各種繁瑣的運維

使用 Sercerless 後的流程:

① 註冊移動雲賬號,訂購 LakeHouse 實例

② 創建數據同步任務

③ 編寫查詢 SQL 計算,輸出結果

④ 服務全託管,全程無運維

7. 元數據管理與發現

元數據管理模塊基於特定規則,智能識別結構化、半結構化文件的元數據來構建數據目錄,通過週期性的元數據爬取實現自動感知元數據變化,並提供多種優化策略來降低爬取時對數據源的負載;同時,提供類 Hive Metastore 的 API 供多種計算引擎直接對錶進行訪問:

元數據管理模塊整體架構如左圖所示:通過元數據爬取 RDB/EOS 數據,格式有 json/parquet/avro 等常見的半結構化數據,然後是 Hive MetaStore 統一訪問層,計算引擎 hive/spark/presto 可以通過類 metastore api 來訪問存在湖中的數據,用戶通過 Web UI 進行目錄映射。

文件類元數據發現過程,如右圖所示:有一張表,下面有幾個目錄,比如按 year 分開的,然後在某個具體目錄有兩個子目錄,對於它的元數據發現過程,就會出現 3 行的數據,id、name 和 type,就會映射成同一張表,然後不同的目錄是按不同的字段進行分區。

8. Serverless 一鍵入湖

爲實現 Serverless 的入湖創建,我們採用了基於 Flink 的分佈式數據同步框架 FlinkX,來滿足多種異構數據源之間高效的數據遷移,具備以下特點:

  • 資源彈性:作業運行在 Kubernetes 上,資源隔離,支持分佈式運行和彈性擴縮容

  • 靈活性:將源 / 目標數據源抽象成 Reader/Writer 插件,支持雙向讀寫和多種數據源

  • 易用性:操作簡化,支持批流一體、斷點續傳,可自動調整數據源連接數,降低侵入性

上圖是我們通過 FlinkX 進行調度任務的流程:

  • 用戶通過 JobManager 創建並提交 task 配置,通過 Quartz 調度 task,作業運行時調用 Flink Kubernetes 客戶端訪問 Kubernetes Master 創建出 Flink Master 所需要的資源,並啓動相應的 Container;

  • Flink Master Deployment 裏面內置一個用戶 FlinkX Jar,這時 Cluster Entrypoint 就會從中去運行 main 函數,然後產生 JobGraph;之後再提交到 Dispatcher,Dispatcher 會啓動一個 JobMaster 向 KubernetesResourceManager 申請資源,RM 發現沒有可用的資源會繼續向 Kubernetes Master 申請資源,請求資源之後將其發送回去,啓動新的 TaskManager;

  • TaskManager 啓動之後再註冊回來,此時 RM 再向它申請 slot 提供給 JobMaster,最後由 JobMaster 將相應的 FlinkX Task 部署到 TaskManager 上。這樣整個 Flink 集羣的拉起,到用戶提交 Jar 都完成了。

我們的 Flink 集羣其實也是一種 serverless 的實現。

9. JDBC 支持

爲了提升不同用戶的數據分析體驗,我們基於 Apache Kyuubi 來支持多租戶、多種計算引擎的 JDBC 連接服務,Kyuubi 具有完整的認證和授權服務,支持高可用性和負載均衡,並且提供兩級彈性資源管理架構,可以有效提高資源利用率。

在接觸 Kyuubi 前,我們嘗試使用了原生的 Spark thrift server 來實現,但是它有一定的侷限性,比如不支持多租戶,單點的不具備高可用,資源是長駐的,資源調度需要自己來管理。我們通過引入 Kyuubi 來支持多租戶和高可用,通過 engine 動態申請釋放,並且 Kyuubi 支持 Yarn 和 Kubernetes 資源調度。

在使用過程中,爲了適配移動雲的賬號體系以及 LakeHouse 架構,我們對 Kyuubi 相應的模塊進行了優化和改造,部分如下:

  • 用戶認證:基於移動雲 AccessKey,SecretKey 對接移動雲認證體系。

  • 資源管理:Kyuubi 原生只支持用戶指定資源,基於雲原生適配後禁止用戶指定資源,統一由 Lakehouse 進行資源調度和分配。

  • 權限管控:適配 Lakehouse 底層權限管理體系,實現細粒度權限的管控。

  • 雲原生部署:基於 Helm3 的 kyuubi server 雲原生部署,支持高可用和負載均衡

  • 對象存儲:支持對象存儲表識別和動態 ak,sk 權限認證

10. 增量更新

我們使用 Hudi 作爲數據存儲中間層,能夠基於 HDFS、對象存儲等底層存儲,支持 ACID 語義、實現快速更新能力。常見的流場景如下:

  • 將 Kafka/MySQL binlog 中的數據藉助 DeltaStreamer/CDC 通過定時 Flink 任務寫入到 Hudi 表中

  • 通過 Flink/Spark 任務同步 Hive 元數據

  • 部分源數據修改

  • 用戶訪問和查詢數據

如右圖所示,我們封裝了 Hudi 自帶的 DeltaStreamer / CDC,自定義 FlinkX 的 Reader / Writer 特性,實現 serverless 入湖和數據同步。

如左圖所示,我們比較了兩種數據格式:

  • 對於實時性要求不高的場景儘量使用 COW(寫時複製)表類型,如果對數據新鮮度有一定要求則可使用 MOR(讀寫合併)

  • MOR 會比 COW 更容易產生小文件並且對資源需求更高

以上就是移動雲 Lakehouse 實現的細節。

03 應用場景

最主要的場景是構建雲原生大數據分析平臺:LakeHouse 支持多樣化數據來源,包括但不限於應用自身產生的數據、採集的各類日誌數據、數據庫中抽取的各類數據,並提供離線批處理、實時計算、交互式查詢等能力,節省了搭建傳統大數據平臺需投入的大量軟硬件資源、研發成本及運維成本。

另外,在私有云場景下,在充分利用現有集羣架構的前提下,以新增組件方式引入 Lakehouse 能力;引入數倉能力,適配多種數據統一存儲和管理;統一元數據,形成湖倉一體的元數據視圖:

  • Hadoop 平臺視圖:Lakehouse 作爲 Hadoop 平臺上一個組件,能夠提供 SQL 查詢能力,並支持多種數據源

  • 湖倉視圖:基於 LakeHouse 提供數據湖倉平臺,HDFS/OceanStor 提供存儲,計算雲原生,多種服務統一元數據管理。

今天的分享就到這裏,謝謝大家。

分享嘉賓:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章