基於 Hologres+Flink 的曹操出行實時數倉建設

danny_2018發表於2024-01-17

摘要:本文整理自曹操出行實時計算負責人林震基於 Hologres+Flink 的曹操出行實時數倉建設的分享,內容主要分為以下六部分:

1. 曹操出行業務背景介紹

2. 曹操出行業務痛點分析 3. Hologres+Flink 構建企業級實時數倉 4. 曹操出行實時數倉實踐 5. 曹操出行業務成果分析 6. 未來展望

01

曹操出行業務背景介紹

曹操出行創立於 2015 年 5 月 21 日,是吉利控股集團佈局“新能源汽車共享生態”的戰略性投資業務,以“科技重塑綠色共享出行”為使命,將全球領先的網際網路、車聯網、自動駕駛技術以及新能源科技創新應用於共享出行領域,以“用心服務國民出行”為品牌主張,致力於打造服務口碑最好的出行品牌。

作為一家網際網路出行平臺,曹操主要提供了網約車、順風車和專車等出行服務。其中,叫車是其核心業務之一。整體業務過程大致如下: 首先,使用者在我們的平臺上下單,然後曹操平臺會給司機進行訂單的派發,司機接到訂單後,會進行履約服務。結束一次訂單服務後,乘客會在平臺上進行支付。

在整個流程中,涉及到的資料將會在我們的業務系統中流轉,主要包括有營銷、訂單、派單、風控、支付、履約這些系統。這些系統產生的資料將儲存在 RDS 中,並進一步流入實時數倉中以進行分析和處理。最終資料會進入到不同的使用場景中,比如實時的標籤,實時大屏、多維 BI 分析,還有實時業務監控以及實時演算法決策。

02

曹操出行業務痛點分析

上圖是一個傳統 lambda 架構,在這個架構中主要會分做實時資料流和離線資料流。在實時鏈路中,業務資料是存放在 RDS 中,並透過 Binlog 以 Canal 同步的方式進入 Kafka ,同時應用的日誌資料也會透過實時採集的方式進入到 Kafka 。資料準備工作完成後,在 Kafka 中構建實時資料倉儲。整個實時數倉基於數倉分層理念進行構建的,主要包括原始資料層(ODS)、資料明細層(DWD)、資料彙總層(DWS)和應用資料層(ADS)。這些層次透過 Flink Streaming SQL 進行串聯,實現資料的流轉和處理。

在離線鏈路中,資料主要是透過 DataX 定時同步任務將 RDS 中的資料同步到 HDFS 。同時應用的日誌會透過定時任務同步到 HDFS ,整個離線數倉以 Spark Sql 定時排程任務去逐層執行。資料在離線數倉中會以不同的資料域去組織滿足不同粒度的資料計算,最終資料會透過 Flink Sink 以及離線同步工具寫到不同的資料應用元件中。同時,為了保證某些應用場景中資料的一致性,可能需要對離線和實時兩條鏈路的資料進行合併處理和加工。

基於曹操出行資料生產成本和研發訴求,針對傳統 lambda 架構中可以看到一些問題:

為了適配不同應用場景,我們在架構中使用了非常豐富的資料元件。

研發成本非常高,不僅在實時鏈路中進行研發和處理,而且還需額外研發一套離線的資料鏈路。

運維效率較低,由於整個實時數倉是構建在 Kafka 上的,因此在資料探查以及進行資料訂正就會變得非常困難。

資源成本較大,主要體現在幾方面:元件多,需要專門安排人員進行運維和管理;一些需要精準一致性的場景需求,需在兩個資料鏈路中做資料的同步和合並計算;在某些計算場景中,需要 Flink 維護大狀態進行處理,也造成額外效能問題和資源的浪費。

另外從公司開發者使用的角度,我們對實時數倉提出了以下幾點訴求:

統一的元件來滿足不同資料應用場景。

複雜的實時資料鏈路中保障高效的資料訂正。

能克服在 Flink 中一些大狀態下的技術難點。

03

Hologres+Flink 構建企業級實時數倉

1. Hologres 能力分析

曹操出行作為 Hologres 的深度使用者,在前期調研與測試階段,我們對 Hologres 的相關能力做了比較詳細的分析,主要有以下優勢:

1.1 業務場景能力豐富

具備 OLAP 分析能力

具備高併發點查能力

具備半結構化日誌分析能力

具備基於 PostGIS 的擴充套件能力,支援空間地理資訊資訊資料的分析與使用,對於曹操出行的業務屬性來說非常重要。

1.2 一站式實時開發能力

契合數倉分層結構理念(可以像離線數倉一樣去構建分層體系,資料實時流動,實時儲存)

FlinkStreaming 生態高度融合 (Flink CDC 元件整合,Flink Catalog 整合)

統一的 Ad-hoc 能力,能以外表載入離線數倉中資料進行湖倉加速和聯邦分析

1.3 解決的痛點問題

全鏈路低時延

多流 Join 場景很好的提供資料打寬的能力,支援主鍵模型和行級,區域性欄位更新的能力

CountDistinct 大狀態精確去重場景的支援

2. Hologres 支援高併發更新

Hologres 的儲存架構基於分散式儲存系統,並在其上構建了儲存引擎。在底層,Hologres 使用了分散式儲存系統來管理資料的儲存和分佈。在此之上,儲存引擎包括一些關鍵元件,如 Block Cache、Shard ,每個 Shard 中包含了多個 Tablet 和 Write-Ahead Log(WAL)。

市面上主流的資料湖產品通常採用 LSM(Log-Structured Merge)架構。

主流資料主鍵模型更新模式有 Copy On Write 和 Merge On Read,這兩種場景都有各自的問題:

Copy OnWrite 具有寫放大的問題,資料的延遲會比較高。

Merge OnRead(讀時合併)模式在讀取資料時需要進行大量的資料合併操作,因此讀取效能可能較差。

在 Hologres 中,行存使用 Merge On Read 方式,列存主要基於 Merge On Write。

下面主要介紹下在基於 Merge On Write 這種模式時,一條資料在進入 Hologres 中,它首先到達 WAL Manager(Write-Ahead Log 管理器),同時也會進入到 Memtable(記憶體表)。在 Memtable 中,主要儲存三類資料:資料檔案、刪除標誌檔案(例如基於 RoaringBitmap 的檔案)和索引檔案。當 Memtable 資料積累到一定階段後,會生成不可變的 Memtable,並透過非同步執行緒定期將其重新整理(flush)到 Data File(資料檔案)中。透過這種架構,Hologres 能夠兼顧行存和列存的優勢,並透過適當的資料合併策略來提高效能和儲存效率。

3. Hologres Binlog 支援

在 Hologres 中 Binlog 也是一種物理表,其跟原表的主要區別是內建的幾種自身結構,包含自身遞增序列,資料修改型別以及資料修改時間,Binlog 本質上也是分 shard 進行儲存,所以也為一種分散式表,並且在 WAL 之前生成,因此在資料上可以與原表保證強一致性。

其次 Hologres Binlog 修改型別也還原了 Flink 中四種 RowKind 型別。在資料更新過程中會產生兩條更新記錄(update_before,update_after),並且保證了更新記錄是一個連續的儲存。右邊展示中,寫入一個資料一個pk1,然後再寫入一個 pk2 資料,pk2 的資料再做一次更新,那麼在 Binlog 中它會產生4條資料結果。

4. Hologres 資料模型介紹

Hologres 主要分做行存引擎以及列存引擎,同時也支援行列共存場景。

在聚合場景中主要是用到列存的引擎,適合 OLAP 場景,複雜查詢,統計以及關聯等場景。同時也提供了非常豐富的索引,包括有:聚簇索引,點陣圖索引,字典,以及基於時間序列的範圍索引。

在 KV 場景中主要是用到行存的引擎,主要支援高併發元件查詢。包括在 Flink中做維表反查也是非常適合。

在訂閱場景中主要是用到行存的引擎,主要在表屬性中進行宣告,比如說 Binlog 是否開啟,Binlog 的 TTL。在訂閱方的話,Hologres 支援 CDC 以及非 CDC 的模式。

在日誌場景中針對聚合場景,主要是支援 JsonB 資料型別。JsonB 資料的寫入過程中,Hologres 能夠將其自動地平鋪成列式的儲存結構,同時它可以自動對資料內容做解析,對資料型別做泛化處理,資料格式的對齊,非常適合這種非稀疏場景,因此給聚合場景提供了分析的靈活性。

04

曹操出行實時數倉實踐

1. 實時數倉架構設計

基於前面 Hologres 的能力介紹,接下來是對於曹操內部實時數倉的架構設計,最左邊是 RDS 資料庫,最右邊是應用系統,最下邊為後設資料管理,中間是實時數倉的部分。資料透過 Binlog 進入到 Kafka 的 ODS 層之後,首先透過 Flink 寫入到 Hologres 裡的 DIM 層,然後再透過 Flink 做 ODS 的多流匯聚,寫入到 Hologres 的 DWD 層。在 DWD 中可以做寬表打寬的實現。再下一層,透過 Hologres Binlog的訂閱的方式,進入到 Flink 進行處理加工再寫入到 Hologres 的 DWS 層。完成實時數倉分層建設後,再統一透過 OneService 的統一查詢服務對外提供服務。

2. dwd 寬表構建實踐

接下來介紹一下 Hologres dwd 寬表層的一個構建實踐。基於之前提到的 Hologres 列更新能力,能夠很好實現寬表 Join 能力。在整個生產過程中,還需重點關注維表的應用場景,其應用場景包含幾種情況:一種是維表是不變的,或者緩慢的變化,另一種是維表頻繁變化的。為了保障資料最終的一致,通常的設計是像離線的方式去構建一個維表拉鍊的資料,透過用過 Start Time 和 End Time 的方式去儲存維度狀態有效的一個週期。

其次需要關注維表延遲問題。在實際生產過程中,維錶鏈路與主表的鏈路通常是非同步的,可能會出現維表延遲導致主表關聯資料為空或關聯到過時的維度狀態。為處理這種情況,需要在 Hologres 中實施維度缺失記錄的過濾,並採取補償機制進行維度補償處理。同時,還需要定時排程進行維度欄位和維表對比檢查,以增量方式修正不一致的維度狀態。

3. 聚合計算場景最佳化

接下來是我們對聚合場景的最佳化,針對許多預聚合計算場景,我們將其統一收斂到 Rollup 計算模型中,主要解決以下問題:

· 在 Flink 聚合場景中經常會出現狀態相容性的問題

· 整個資料的複用性非常差,研發人員收到新的需求,例如新的指標或者新增維度粒度時,為了不影響生產資料的穩定性,新增需求需要構建新任務,導致任務管理混亂。

因此曹操出行主要進行了兩點最佳化:

· 構建 MapSumAgg 運算元,MapSum 主要透過對 SumAgg 運算元做了重新設計,使之能夠支援 Map 內部結構的求和邏輯

· 對 Grouping Sets 進行動態配置化,這樣 Grouping Sets 動態增加維度粒度,使整個任務在不重啟的情況下也能自動去做自適應

結合這兩點,把已有的指標放入 map 結構中進行封裝,這樣在不改變原有的運算元狀態,也可以得到很好的處理。在下游中可以針對不同維度組合,指標集合做好選擇,然後由同步工具做實時的資料路由,為下游提供服務。

對於第二個聚合場景的最佳化,是對精確去重場景的拆分。在前面例子中,我們把 Count Distinct 的精確去重做了剝離,主要解決兩個問題:

· 維度爆炸問題。在 Flink 的回撤機制下使用精確去重時,需要儲存全量狀態。然而,在 Cube 場景中,這種狀態的爆炸式增長對於 Flink 的可擴充套件性是一個挑戰。

· 查詢靈活性問題。解決思路是透過 Hologres 去構建細粒度的 RoaringBitmap 儲存方案。

具體流程如下:首先, 在 Hologres 中構建自身序列的 UID 維表,然後在主表中透過反差邏輯將 UID 的自身序列反查出來。接下來,在 Flink 中進行 Group by 操作,並進行聚合計算,得出 RoaringBitmap 的結果。最後,將結果寫入 Hologres 的 DWS 層,形成輕度彙總表用於 UV 計算。這種方案既能解決應用端在靈活維度查詢時的高效性需求,又能解決 Flink 中維度爆炸的問題。

4. 鏈路中吞吐能力調優

整個流鏈路中吞吐能力的調優主要涉及兩個部分:

資料寫入側:在將資料寫入 Hologres 之前,針對欄位狀態頻繁變更的場景進行了最佳化。引入了一個Union 層,在 Union 層和 ODS 層中,資料根據主鍵進行分割槽。在 Union 層中,透過一個小視窗進行預聚合計算,以減少對 Hologres 的寫入壓力,從而提高整體資料吞吐量。然而,這種方式的缺點是無法捕獲中間狀態的資料。

資料讀取側:在使用 Binlog 更新資料時,會產生連續的變更前後資料。在這種場景下,可以採用lag 開窗的方式來獲取一次變更中連續的上下游資料。透過比較這兩個資料之間的差異,可以過濾掉冗餘的變更資料,從而減輕整個處理下游資料的壓力。這種方式可以提高讀取資料的效率和吞吐量,減少不必要的資料處理。

5. 後設資料血緣的改造

後設資料血緣的改造主要解決了以下問題:

· Schema 的演進提供了一個更便利的管控

· 解決實時鏈路釋出流程中的依賴鏈問題。

· 對任務後設資料資訊進行有效的管理

曹操出行主要進行以下措施來實現上述目標:

· Flink Catalog 整合,在後設資料中去整合 Hologres 的 Catalog,也支援 Kafka Topic 表中自定義 Catalog,支援多版本 schema 和任務資料的多版本,提供更靈活的資料處理能力。

· Kafka Source 和 Kafka Sink 的改造。結合整合整個上線釋出的流程,對於資料的版本資訊,是透過 Kafka Sink 對 Header 進行記錄,Kafka Source 對 header 的版本資訊進行過濾,從而把資料版本引入到整個上下游的鏈路,提供上下游資料靈活的迭代。這種做法的好處是,在整個鏈路中可以感知到下游資料的使用情況,幫助使用者快速定位是否還有任務依賴於某個版本的資料,圖片主要是展示一個開發流程中後設資料的整合。

6. 鏈路保障體系

在日常開發過程中,對於任務健康以及任務出現異常後的判斷和檢測,都是透過異常檢測診斷工具去做支援。主要體現四個方面:

對於基礎資訊採集,透過採集工具,把 Flink 內建 Metric 、Yarn 的 Metric 以及 Kafka 資訊進行採集,提供基礎資料,包括作業資訊,Kafka 一些 Topic 資訊,作業最新指標情況。

對於異常的判斷,透過記憶體以及 Topic 增長情況,包括 CPU 使用情況,以及任務有無出現反壓,任務有無傾斜做出異常的判斷。

對於異常原因的診斷-內部原因,內部原因主要會看 CheckPoint 的失敗情況,Kafka LAG 具體是什麼運算元造成的反壓,Restart 的次數,attempt 的次數。

對於異常原因的診斷-外部原因,外部原因主要是看 Job Manager 以及 Task Manager 所在節點自身的情況,包括 CPU 使用率、IO 利用率、記憶體情況等,然後做出綜合判斷,幫助使用者去快速定位具體問題的原因。

在鏈路保障體系中,全鏈路的感知能力是非常重要的。曹操出行主要透過流量監控和延遲監控來實現全鏈路的感知能力:

流量監控層面:透過 Kafka Cueernt Offset 以及 Hologres 內建的 Offset 資訊做定時的採集,從而推算出 Kafka 以及 Hologres 表的生產速率。

Latency 監控層面:主要採集 Kafka Offset 以及 Flink Source 的 Offset 情況,結合 Kafka Massage Timestamp 去推算出每個任務自身延遲情況,再結合整個資料血緣進行一個串聯,可以得出端到任務自身整體的延遲時間。

透過任務上下游生產速率比,以及任務自身延遲情況,在整個生產鏈路中可以快速定位出具體異常和問題發生的節點,以便及時處理和最佳化,提高系統的效能和穩定性。

7.資料訂正能力建設

在傳統的 Streaming 鏈路中,資料訂正方案一直是個複雜工程,主要涉及以下兩個方面的挑戰:

如何知曉訂正的資料為正確資料?驗證其具有一定困難。

在整個驗證過程中,如何保證對下游的透明?如果丟狀態去做重啟的訂正,肯定會對下游造成很大的影響。

因此我們主要思路是基於 Hologres 去做實現。首先對於原始任務進行程式碼修正後,並維持原有狀態去做重啟。第二步將對 Hologres 表做 Schema 的複製,然後新建一個訂正的臨時表。第三步會將任務進行複製,並將 Sink 調整到訂正臨時表,去做無狀態從頭消費的重啟。這樣可以把訂正的結果資料訂正進 Hologres 訂正表中。等待消費結束後停止訂正任務,然後透過修正指令碼去對比原表以及訂正表中關鍵資訊,去做資料的訂正。由於資料的訂正,它處於資料終態,對於下游來說,不會造成大起大落。並且在整個鏈路中,因為正確資料可以透過整個資料鏈路做回撤的傳導,因此整個下游就可以自動完成資料的訂正。

05

曹操出行業務成果分析

1. 架構清晰簡單

對比原有 Lamada 架構,Hologres + Flink 整體架構更加清晰,使用資料元件大大減少

整體技術複雜難度降低,原先為了解決資料一致性問題,資料需要在不同的異構儲存和異構鏈路中來回傳輸和計算,整個技術複雜度較高

2. 開發效率提高

整個開發模式變得簡單易用,大大縮短人力週期

資料實時模型分層非常清晰,整體下游複用性以及使用門檻大幅度降低

3. 運維體驗提升

由於資料儲存在 Hologres 之上,因此資料探查更加便捷,資料訂正難易程度大幅度減少。

4. 成本減少

元件維護成本減少

資料的離線儲存和實時儲存,從雙份儲存降低到一份儲存,以及降低了資料在異構儲存之間的同步與計算成本

解決在 Flink 中各類計算場景中大狀態的資源成本,減少了計算開銷並提升了處理效能。

06

未來展望

未來展望主要分為以下四個層面:

當前 Flink 叢集還是一個自建的叢集,對於這些叢集我們業務最關心的是使用過程中,其業務的穩定性和可靠性。特別是在高峰場景,資源不足時,怎麼去做快速的縮擴容。在高峰期過去後怎麼去做到無縫縮容,降低業務風險,包括減少業務的資料中斷時間。

在任務級別的動態感知和智慧調控上。很多時候研發根據自己的經驗去設定 Flink 的資源引數,往往有很多資源其實是多設或者是額外設定的。透過動態感知能力的引入,能夠有效提升整體的資源使用情況,包括未來也可能會引入智慧演算法,包括自適應的機制去達到節約成本的目的。

FlinkCDC 來統一 ODS 入倉的方案。我們在離線使用 DataX 的入倉方案,後來實時使用了 Flink CDC 的入倉方案,其實本質上資料可以提供一個統一的解決思路,來解決資料的一致性和靈活性的訴求。包括在 CDC 方案中,也會有一些定製上的需求。比如說在 CDC 過程中資料加解密以及 RDS 資料歸檔一系列訴求。使用 Flink CDC 的過程中也會分階段的做一些調整,包括一些高頻迭代的訴求也會在後續的規劃中更優先的解決。

關於曹操出行的資料服務規劃。目前有很多資料服務場景,包括了線上應用場景,以及分析型的服務場景,業務會比較關注資料服務的高可用以及服務的可擴充套件性,那怎麼樣透過同一份資料來做到不同服務的擴充套件。這部分我們後續會考慮基於 Hologres 主從隔離的能力和結合資料儲存計算隔離的一些特點優勢,構建一主多從的架構,來支援和滿足這些資料應用服務。

來自 “ Apache Flink ”, 原文作者:曹操出行林震;原文連結:https://mp.weixin.qq.com/s/TVakAyrqmJMLP3R3cbhVwQ,如有侵權,請聯絡管理員刪除。

相關文章