天天看點

融合趨勢下基于 Flink Kylin Hudi 湖倉一體的大資料生态體系

既然聊湖倉一體,我們先了解一下什麼是湖,什麼是倉。資料湖是一個很老的概念,在近些年又被熱炒。業界對于資料湖到現在也沒有一個統一的定義。AWS 是最早在雲上推出資料湖解決方案的雲服務提供商,在這裡我們便引用 AWS 對資料湖的定義:“資料湖是一個集中式的存儲庫,允許存儲任意結構的資料并且能将它應用于大資料處理,以及進行實時分析和機器學習等相關的應用場景。” 同樣我們也借助于 AWS 對資料倉庫做這樣的定義:“資料倉庫是資訊的一個中央存儲庫。” 這裡的資訊是可對其進行分析,并且可做出更明智的決策。

這個定義還有詳細的展開。AWS 這張圖通過展示了從湖到倉的資料流向的關系,來示範資料湖與資料倉庫之間的差別和聯系。首先資料最初是存在于資料湖或是資料庫中,然後經過資料篩選和準備之後,就會流向資料倉庫來進行一些高價值的分析。這個對比表格很直覺的從資料、Schema、成本效益、資料品質、使用者和分析這 6 個次元給出資料湖和倉的對比。

融合趨勢下基于 Flink Kylin Hudi 湖倉一體的大資料生态體系

今年我們聽說阿裡巴巴提及的“湖倉一體”的概念。不知道大家有沒有想過湖倉一體在業界是否有成功的先例?我個人認為是有的。今年 (2020年)9 月份,一家叫 Snowflake 的公司在紐交所上市。Snowflake 是一家做雲數倉的公司,基于雲廠商提供的基礎設施提供 SaaS 平台,面向中小企業提供資料的托管和分析服務。Snowflake 自稱自己是一家雲數倉公司,并且在 16 年的資料頂會上發表了一篇論文來介紹他們彈性數倉的架構以及一些技術的細節。

Snowflake 其實是基于雲上的對象存儲,一份存儲多份計算,并且計算與存儲分離的這樣一套架構。其實這就是 AWS 以及現在主流雲廠商所主推的這個資料湖的架構。Snowflake上市的首日,他的市值就飙升到了 700 億美元的規模。是以我個人認為 Snowflake 可以算是實行湖倉一體的一個最成功的先例。大家可以去了解一下剛談到的這篇論文。我摘出了這 5 個點來和大家做簡單的分享:

首先第一點,是沒有走現在傳統數倉所廣泛應用的 Shared-Nothing 這個架構,而是轉向 Shared-Data 這個架構。

其次,論文中重點提及的存儲和計算分離,是文中我覺得最有價值的一個觀點。他提出了統一存儲然後彈性計算的這樣一個觀念。

第三,數倉及服務是我認為他們商業化最成功的點。它将數倉提供了一個 SaaS 化的體驗,并且摒棄傳統上大家認為的數倉是大而重的偏見。

第四,高可用這一塊是提高使用者體驗和容錯的很關鍵的一個點。

最後,結構化延伸到半結構化這一塊已經展現當時他們能夠探索湖上通用資料的能力。

這雖然是 16 年的一篇論文,但裡面的觀念并不算陳舊并且仍然值得我們去學習。後續我們會簡單介紹幾個被我們吸收并且将會去實踐的一些點,而且這些點也是 T3 出行在實作湖倉一體上很關鍵的地方。

首先,作為一個被很多傳統的數倉廣泛應用的一個架構,Shared-Nothing 還是有一些架構上的優勢:

第一點,Table 上的資料可以進行跨節點的水準分區,并且每個節點有自己的本地存儲。每個節點的計算資源,隻關注處理每個節點自己存儲的資料。

是以它的另一個優點就是它的處理機制相對簡單,是數倉領域很典型的一個架構。

融合趨勢下基于 Flink Kylin Hudi 湖倉一體的大資料生态體系

這套架構其實也有一些不足的地方:

最大的一點就是他耦合了計算與存儲資源,

同時也帶來第二個問題,就是彈性不足。具體可以展現在 2 個方面。

a、叢集在擴縮容的時候,資料需要被大量重分布

b、沒有辦法簡單地解除安裝不用的計算資源

第三個問題是,耦合計算和存儲資源同時也就造成了它的可用性是相當有限的。由于這些稱之為有狀态的計算,是以在失敗或者是更新的時候會顯著影響性能,并會導緻服務整體不可用的狀态。

最後是同構的資源與異構的負載的問題。因為在數倉的場景中,我們有很多異構的負載,比如說批量的加載,查詢,報表的大規模計算分析等等。但 Shared-Nothing 架構的資源是同構的,是以這帶來兩者之間的碰撞。

融合趨勢下基于 Flink Kylin Hudi 湖倉一體的大資料生态體系

基于這些問題,Snowflake 提出了一個叫做 Multi-Cluster Shared-Data 架構。這裡我們對官方的圖做了一個簡單的微調。

這個架構的第一個優勢是它沒有資料孤島,是一個統一的存儲。這也就能夠将存儲從計算中進行解耦。

第二個優勢是基于現在的對象存儲去容納結構化和非結構化資料。

第三,它的叢集規模是可以彈性作用的。

第四,上述特征同時也帶來了按需計算這個低成本優點。

融合趨勢下基于 Flink Kylin Hudi 湖倉一體的大資料生态體系

接下來我們以分層的形式來 review 這個架構。從整體上來看,它的結構大緻分為三個層次。

最底層是雲廠商提供的對象存儲,也就是使用者的存儲。

中間層是多用途多份的計算叢集。

再往上是資料湖的管理服務,它存載的是一個大的 SaaS 化的平台,是對整個底層存儲以及計算叢集的管理的角色。

融合趨勢下基于 Flink Kylin Hudi 湖倉一體的大資料生态體系

接下來一個點是這個架構的高可用。這裡可以簡單分解為 2 個方面。第一個是失敗容錯,第二個是線上更新。

首先,作為一個 SaaS 化的應用,它的容錯性是需要展現在整體架構上。這裡我們同樣分層來回顧一下。

最底層的存儲層利用了雲廠商的對象存儲能力,他本身是一個跨中心複制以及接近無限擴容的一個機制,是以使用者基本無需關心。

再往上是多元的計算叢集。每個計算叢集是在同一個資料中心内,來保證它網絡傳輸的性能。這裡就提到一個問題,有可能某一個計算叢集會有節點失敗的問題。假如在一次查詢中有一個節點失敗,這些計算節點會将這個狀态傳回上面的服務層。服務層在接受這個失敗後,會将這個計算再次傳遞到可用的節點中進行二次查詢。是以 Shared-Data 存儲和計算分離的這種架構上節點近乎是無狀态的計算。這種架構的一個節點失敗就不是一個非常大的問題。

再往上服務層對于中繼資料的存儲也是利用了對象存儲的這個能力。是以這個服務層基本上可以看做是無狀态的服務。

最上層是一個負載均衡器,可以進行服務的備援和負載的均攤。

融合趨勢下基于 Flink Kylin Hudi 湖倉一體的大資料生态體系

第二點線上更新這一塊主要利用兩個設計,其實這也并不是很新穎的做法。一個是在計算層和服務層的多方面的映射,然後灰階的切換。這裡可以看到在計算層是分多版本的,并且這些版本之間會共享本地的 Cache。服務層的中繼資料管理也是在多方面共享。這其實也是架構内的子 Shared-Data,對于多版本之間的資料共享能做到再更新和平滑灰階的能力。

融合趨勢下基于 Flink Kylin Hudi 湖倉一體的大資料生态體系

接下來我的同僚(王祥虎)會跟大家介紹這 3 個架構以及它們是如何融合并最終支撐 T3 湖倉一體的實踐。在介紹第二個議題前他會先介紹我們的主架構,Hudi 和 Kylin 架構,然後再介紹他們三者之間是如何兩兩融合。最後再介紹T3是如何建構湖倉一體的。

首先來了解一下 Hudi 是什麼。Hudi 最初是由 Uber 的工程師為了滿足他們的資料分析需求設計開發的一個資料湖架構。它于 2019 年 1 月份加入到 Apache 孵化器,并于 2020 年 5 月順利畢業,成為 Apache 的頂級項目。Hudi 的名字來源于 Hadoop Upserts Deletes and Incrementals 的縮寫。也就是說,Hudi 是一個支援插入、更新、删除、以及增量處理的資料湖架構。除此之外,它還支援事務性 ACID 增量處理、存儲管理和時間管理。Hudi 能夠管理雲上超大規模上百 PB 的分析型資料集,對于所有的雲服務都開箱即用,非常的友善,而且已經在 Uber 内部穩定運作了接近 4 年。

融合趨勢下基于 Flink Kylin Hudi 湖倉一體的大資料生态體系

下圖是 Hudi 的插件化架構。我們可以看到,Hudi 在存儲、資料處理引擎、表類型、索引類型、查詢視圖和查詢引擎方面都有比較寬松的支援。也就是說,他不與某一個元件綁定。

在存儲方面,Hudi 可以支援 HDFS,OSS 和 S3。

在資料處理引擎方面,Hudi 支援 Flink 和 Spark。Java 和 Python 用戶端已經在社群支援中。Hudi 支援兩種表,COW 和 MOR,這兩種表分别對應低延遲的查詢和快速攝入兩種場景。

在索引方面,Hudi 支援 Bloom 和 HBase 等 4 種索引類型。底層用了 Parquet 和 Avro 存儲資料,社群還正在做 ORC 格式的支援以及 SQL支援,相信不久的将來會跟大家見面。

Hudi 支援 3 種查詢,讀優化查詢,增量查詢和快照查詢。而在查詢引擎方面,有 Spark 、Presto、Hive 和 Impala,實際上一些其他的元件已經支援了。

融合趨勢下基于 Flink Kylin Hudi 湖倉一體的大資料生态體系

下面詳細的介紹一下存儲模式和視圖。

第一個是 Copy On Write 模式,對應到 Hudi 的 COW 表。它是一種側重低延時的資料查詢場景的表,底層使用 Parquet 資料檔案存儲資料,能夠支援快照查詢和增量查詢兩種查詢方式。在查詢引擎方面,大家可以看到上面有 5 個引擎,他們對快照查詢、增量查詢和讀優化 3 種視圖都有不同程度的支援。

Merge On Read 表對 Copy On Write 有不同層面的互補,可以看到它側重于快速的資料攝入場景。使用 Parquet 檔案來存儲具體的資料,使用行式 Avro 增量檔案來存儲記錄檔,類似于 HBase WAL。它支援 Hudi 所有 3 種視圖,可以看到 Hive,Spark SQL,Spark Datasource, Presto 和 Impala 對于讀優化查詢都是支援的。而 Hive, Spark SQL 隻支援到了快照查詢。這種元件支援的資訊大家以後可以到官網上查詢。

融合趨勢下基于 Flink Kylin Hudi 湖倉一體的大資料生态體系

在出行業務中,訂單會有支付長尾的屬性。也就是說一個訂單開始之後,它的支付環節可能會拖的比較久。換言之,它可能會在這個使用者下一次出行前才進行支付(也或許會更久,甚至永遠不支付)。這種長尾屬性将會導緻一個超長的業務閉環視窗,會導緻我們無法準确預測資料的更新時機。如果存在多級更新的話,鍊路會比較長,更新成本也非常的高。

下圖是我們的長尾更新引發的冷資料頻繁更新示意圖。左側是業務庫,右側是有依賴關系的 3 張示意表。當業務庫有資料更新時,右側需要更新的資料可能已經歸檔到性能相對較差的裝置上,增加資料更新成本。而且如果這次資料更新會引發長鍊路級聯更新的話,這種慢速的 I/O 還會被進一步放大。

融合趨勢下基于 Flink Kylin Hudi 湖倉一體的大資料生态體系

資料的可靠性也是資料 ETL 中不可避免的問題。可能由于機器故障或者計算邏輯導緻加工處理的資料失真或者完全不對,就會給營運的決策造成很大的影響。數字延遲性方面,在基于 Hive 構件的傳統架構中,由于 Hive 缺少索引機制,是以資料更新大都會導緻資料分區重寫,且沒有辦法原地删除。其次小檔案問題會增加 NameNode 存儲和查詢的負擔,拖慢程序,在一定程度上增加資料延遲性。

融合趨勢下基于 Flink Kylin Hudi 湖倉一體的大資料生态體系

我們再來介紹一下這個 Kylin 架構。相比較 Hudi,大家應該會對 Kylin 相對熟悉一些,它是一個開源的分布式分析型資料倉庫,能夠提供 Hadoop/Spark SQL 之上的資料查詢視窗。最初是由 eBay 開放并貢獻到開源社群,能夠在亞秒内查詢巨大的表。它的秘訣其實就是做預計算,針對一個星型拓撲結構資料立方體,預算多個次元組合的度量把結果寫出到輸出表,對外暴露查詢接口實作實時查詢,也就是用空間來換取存取時間。

Kylin 在今年的 9 月份釋出了 4.0 alpha 版本,這是在 Kylin3 之後一個重大架構更新。使用 Parquet 代替 Hbase 存儲,進而提升了檔案的掃描性能,也減輕甚至消除了 Hbase 的維護負擔。Kylin4 重新實作 Spark 建構引擎和查詢引擎,使得計算和存儲分離,也更加适用雲原生的技術趨勢。

融合趨勢下基于 Flink Kylin Hudi 湖倉一體的大資料生态體系

伴随 Kylin3.1 釋出,Kylin 與 Flink 就融合已經完成。這個特性是在 2019 年完成的,Kylin 與 Flink 的內建開始于去年 1 月,通過 Flink Batch 實作。關于 Hudi 融合,可以說 Kylin 和 Hudi 天生就是相容的,因為 Hudi 可以将自己暴露成一張 Hive 表,使用者可以像讀取 Hive 一樣使用 Hudi 的資料,這樣對Kylin會非常友好。因為 Kylin 可以把 Hudi 當成一張 Hive 表無縫使用資料。Hudi 和 Flink 融合這個特性是我今年對社群的主要貢獻。這個兩張截圖對應 Hudi 和 Flink 融合路上的2個裡程碑式的PR。

第一個 Hudi client 支援多引擎,将 Hudi 與 Spark 解耦,讓 Hudi 支援多引擎成為可能。

第二個是 Flink 用戶端基本實作貢獻到社群,讓 Hudi 可以真正意義上寫入 Flink 資料表。這 2 個改動非常大,加在一起已經超過了 1 萬行的代碼,也可以說是今年 Hudi 社群比較亮眼的一個特性。

融合趨勢下基于 Flink Kylin Hudi 湖倉一體的大資料生态體系

下面來詳細介紹下 Hudi 和 Flink 融合過程。Hudi 原本隻支援 Spark 引擎,是以第一步是将 Hudi 與 Spark 解耦之後再去內建我們想要的引擎。

解耦的難點在于 Hudi 最初沒有考慮多引擎的支援,是以從資料源讀取資料到最終将資料寫出到 Hudi 表,RDD 無處不在。連普通的工具類都會使用 RDD 作為基本的操作單元。與 Spark 解耦,我們評估到他的改動非常的大。其次是 Flink 與 Spark 核心抽象上的差異。Spark 認為資料是有限的資料集,而 Flink 認為資料是無界的,是一種資料流。這種抽象上的差異導緻我們很難統一出一個通用的抽象。

融合趨勢下基于 Flink Kylin Hudi 湖倉一體的大資料生态體系

這次改動對于 Hudi 來說是傷筋動骨的,是以我們決定要優先保證原版 Hudi 的功能和性能,當然也犧牲了部分 Flink Stream API。讓 Flink 來操作 list,而用Spark 操作 RDD。這樣就可以抽取一個泛型出來形成一個統一的抽象層。

抽象原則:

統一使用泛型 I、K、O 代替。

去 Spark 化,抽象層 API 都是引擎無關的,難以在抽象層實作的,我們會把它改為抽象方法下推到 Spark 子類實作。

不影響原版,抽象層盡量的減少改動,以保證固定的功能性。

引入 HoodieEngineContext 代替 JavaSparkContext, 提供運作時的上下文。

融合趨勢下基于 Flink Kylin Hudi 湖倉一體的大資料生态體系

下面說 Flink Client DAG,這裡主要分了 5 部分,

第一部分是 Kafka Streaming Source,主要用來接收Kafka資料并轉換成 List。

第二個是 InstantGeneratorOperator,一個 Flink 算子, 用來生成全局唯一的 instant。

第三是 KeyBy 分區操作,根據 partitionPath 分區避免多個子任務将資料寫入同一個分區造成沖突。

第四個是 WriteProcessOperator,這也是我們自定義的一個算子。這個算子是寫操作實際發生的地方。

第五個是 CommitSink,他會接受上遊 WriteProcessOperator 發來的資料,根據上遊資料判斷是否送出事務。

融合趨勢下基于 Flink Kylin Hudi 湖倉一體的大資料生态體系

下面是 Flink 更新的代碼示例。左側是原版裡面 HoodieWriteClient 簡化的版本,

可以看到 insert 函數的入參是 RDD,傳回值也是 RDD。右側抽象之後的 abstract 可以看到它的入參變成了泛型I,傳回值變成了 O,有興趣的話大家可以去了解一下。

融合趨勢下基于 Flink Kylin Hudi 湖倉一體的大資料生态體系

下面是我們對 Flink 如何融合的另外一個想法,就是希望做出一個 streaming source,使用 Flink 建構一個完整的從 Hudi 表讀資料,再寫出到 Hudi 表的 ETL 管道。

然後是我們初步的設想。左側灰色的圖裡面有 5 列的 Hudi 中繼資料。最左側是 hoodie_commit_time 事務清單。每一個 hoodie_commit_time 對應一個事務,每一個事務對應一批的資料。每一批資料中的每一條記錄都會有一個送出的序列号,就是第 2 列 hoodie_commit_seqno 序列号。hoodie_commit_time 和 hoodie_commit_seqno 這種映射關系跟 Kafka 中的分區和 offset 的這種映射關系非常類似。後期我們可能會基于這種特點實作一個 Hoodie Streaming Source。

融合趨勢下基于 Flink Kylin Hudi 湖倉一體的大資料生态體系

基于這 3 個架構之間的融合關系,我們發現分别用于計算、分析、存儲的這 3 個引擎之間是互相相容的。并且他們能夠支援湖倉一體,向雲原生體系靠攏。

最後我們來看一看 T3 出行是如何建構湖倉一體的。這是我們 T3 出行車聯網的架構,可以看到是從底向上,從基礎支援到上層不停的賦能,并與車企的資訊系統、國家資訊平台做互動。作為一家車聯網驅動的出行公司,我們收集到了人、車、路等相關的資料,每一種資料都有它自己的應用場景, 資料之間并不孤立,互相賦能,共同支援 T3 智慧出行。

融合趨勢下基于 Flink Kylin Hudi 湖倉一體的大資料生态體系

這是我們的存儲和計算分離的資料庫架構,整個架構分為了兩層,一層是計算層,一層是存儲層。

計算層我們用到了 Flink、Spark、Kylin 和 Presto 并且搭配 ES 做任務排程。資料分析和展示方面用到了達芬奇和 Zeppelin。

在存儲層,我們使用了阿裡雲 OSS 并搭配 HDFS 做資料存儲。資料格式方面使用 Hudi 作為主要的存儲格式,并配合 Parquet、ORC 和 Json 檔案。在計算和存儲之前,我們加了一個 Alluxio 來加速提升資料處理性能。資源管理方面我用到了 Yarn,在後期時機成熟的時候也會轉向 K8s。

融合趨勢下基于 Flink Kylin Hudi 湖倉一體的大資料生态體系

在目前存儲計算分離的趨勢下,我們也是以湖存儲為核心,在它周圍建構了湖加速湖計算、OLAP 分析、互動式查詢、可視化等等一整套的大資料生态體系。

融合趨勢下基于 Flink Kylin Hudi 湖倉一體的大資料生态體系

下面是我們 T3 内部對 Hudi 的幾個應用場景。

一個是近實時的流資料管道。我們可以從左側通過 Log、MySQL 或者直接讀取業務資料的 Kafka,把資料導入到資料管道中,再使用 Flink 或者原版的 DeltaStreamer 将流式資料輸入到清單中。

融合趨勢下基于 Flink Kylin Hudi 湖倉一體的大資料生态體系

近實時的流式資料處理的 Flink UI 界面上可以看到之前介紹的 DAG 的幾個算子都在裡面,比如 source、instant_generator 等。

融合趨勢下基于 Flink Kylin Hudi 湖倉一體的大資料生态體系

另一個是近實時的資料分析場景。我們使用 Hive、Spark 或 Presto 查詢資料,并最終用達芬奇或者 Zeppelin 做最終的資料報表。

融合趨勢下基于 Flink Kylin Hudi 湖倉一體的大資料生态體系

這是我們用 Hudi 建構的增量資料管道。最左側 CDC 資料捕獲之後要更新到後面的一系列的表。有了 Hudi 之後,因為 Hudi 支援索引和增量資料處理,我們隻需要去更新需要更新的資料就可以了,不需要再像以前那樣去更新整個分區或者更新整個表。

融合趨勢下基于 Flink Kylin Hudi 湖倉一體的大資料生态體系

最後的一個場景是将前面介紹的用 Flink 将線上或者業務資料訂閱 ETL 到 Hudi 表中供機器學習使用。但是機器學習是需要有資料基礎的,是以我們利用 Hudi 将線上的資料增量釋出到線下環境,進行模型訓練或者調參。之後再将模型釋出到線上為我們的業務提供服務。

融合趨勢下基于 Flink Kylin Hudi 湖倉一體的大資料生态體系

繼續閱讀