摘要:本文整理自易車資料平臺負責人王林紅,在 Flink Forward Asia 2022 資料整合專場的分享。本篇內容主要分為四個部分:
Flink 在易車有豐富的應用場景,主要包含實時數倉建設和資料整合。對於實時數倉建設,主要是數倉實時指標的開發,將離線指標逐步向實時指標過度;同時承接了公司各種實時大屏需求,並多次支援了公司內部的 818 購車節活動。在實時監控方面,首先是日誌監控,主要用來監控埋點情況,另外對於伺服器日誌,我們也進行統一收集和監控,監控服務響應和異常日誌等,同時結合機器學習演算法,做日誌的聚類;在前端層面,監控前端介面超時、白屏等異常情況。最後也應用在一些業務實時監控、風控等場景。在資料整合方面,使用 Flink 完成關係型資料庫的實時接入,將 MySQL、SQL Server 等的資料實時接入到 Kafka 中;同時將 Kafka 的資料實時同步到 HDFS/Hive 中,實現資料的實時入倉、入湖;對於資料傳輸通道,我們使用 Flink 將 Kafka 的資料同步到下游儲存引擎中,比如 TiDB、MySQL、ClickHouse、HDFS、Doris 等儲存中,也實現一些異構資料來源資料的實時同步。
易車的資料整合主要分為兩條線,一條離線資料整合,另一條是實時資料整合。本次主要介紹的是實時資料整合的演進過程,對於實時資料整合,最開始也是處在離線階段,隨著業務的發展,對資料的時效性越來越高,開始使用 Canal 同步 MySQL 的資料,然後使用 Spark 做微批計算,再之後引入 Flink,還是使用 Canal 同步接入 MySQL 資料,使用 Flink 進行資料的實時計算,再之後引入了 Flink CDC,基於 Flink CDC 做全增量一體化實時計算。在使用 Canal+Flink 的早期階段,整體流程如下,對於 MySQL 的資料,使用 Canal 透過解析 Binlog 的方式將資料同步到 Kafka 中,對於 SQL Server 的資料,透過 CDC 的方式同步到 Kafka 中,然後透過 Flink 進行加工計算,同步到下游系統如 HDFS 或 Kafka 中,在這個階段,基本可以滿足業務需求,也可以快速完成資料接入及後續開發。但是也存在一些痛點問題,主要是,整個資料鏈路比較長,依賴的元件多,運維成本也比較高,另外 Canal 不支援全量資料的同步,全量和增量是割裂的兩個階段,並且對於不同資料來源的接入,需要考慮不同的實時接入方案,維護也比較困難。基於以上痛點問題,和我們的歷史經驗總結和評估,我們對資料整合工具提出了新的訴求。- 希望可以分散式地去支撐大資料場景,工具能夠線性擴充套件,可以方便的對接更多資料來源。
- 希望基於一個開源框架來開發,這個框架需要和 Hadoop 的整個生態有比較好地整合。並且我們的終極目標,是用一套統一的技術架構來覆蓋離線和實時的所有資料整合場景。
基於以上訴求,我們把方案鎖定在 Flink 技術棧中,決定基於 Flink CDC 自研實現流批一體的資料整合服務。為什麼選擇 Flink CDC?- Flink CDC 引入了無鎖演算法,讀取階段全程無鎖,降低了因加鎖而帶來的對線上資料庫的影響風險,同時降低了對資料庫的壓力。支援併發讀取,在全量資料同步階段,可以更快地完成海量資料同步,可以透過水平擴充套件節點數或增加並行度的方式來加快資料處理速度、加速海量資料的處理。支援斷點續傳,全量階段支援 Checkpoint,即使任務因某種原因退出了,也可透過儲存的 Checkpoint 對任務進行恢復實現資料的斷點續傳。比如同步資料需要 1 天時間,但是同步任務執行 12 小時後失敗了,不需要重跑整個資料同步任務,只需要從發生錯誤的位置重跑即可。
- 支援豐富的資料來源,目前支援 MySQL、SQL Server、Oracle、TiDB、MongoDB 等,也方便的實現異構資料來源的資料同步和資料融合。
- 端到端的一致性,支援 Exactly-Once 語義,保證全鏈路資料的準確性。
- 無縫對接 Flink 生態,複用 Flink 眾多 Sink 能力。
Flink CDC 支援了豐富的資料來源,源頭支援 MySQL、Mongo、TiDB、Oracle、SQL Server 等,目標端支援 kakfa、Hudi、TiDB、Hive、Doris、ClickHouse 等。同時 Flink CDC 作為新一代的資料整合框架,不僅可以替代傳統的 DataX 和 Canal 做實時資料同步,將資料庫的全量和增量資料一體化的同步到訊息佇列或下游系統中;也可以用於實時資料整合,將資料庫資料實時入湖入倉;同時還支援強大的資料加工能力,可以透過 SQL API 或 DataStrean API 對資料庫資料進行實時關聯、打寬、聚合等。在 2.0 版本中,Flink CDC 對於 MySQL CDC 支援了無鎖讀取、併發讀取、全程斷點續傳等高階功能,實現 MySQL 資料的增量快照讀取,在最新的 2.2 版本中,將增量快照讀取演算法抽象成了公共框架,也方便其他 Connector 的接入,其他 Connector 只需要接入這個框架就可以提供無鎖演算法,併發讀取和斷點續傳的能力,十分方便其他聯結器的擴充套件。所以我們基於 Flink CDC 構建了 DTS 資料傳輸平臺,在源端,目前已經整合支援了 MySQL、SQL Server、TiDB、Mongo、kafka 等資料來源,在目標端,也整合了 Hudi、kafka、Doris、ClickHouse、HDFS、Hive 等資料來源,方便業務進行資料實時入湖入倉,和異構資料來源的傳輸、同步。但是,在 DTS 平臺建設過程中,我們也遇到了一些問題,比如元資訊的欄位對映,如何方便安全的將源庫的欄位型別對映成 Flink 的欄位型別;在任務執行過程中,如何動態的增加新的同步表,包括如果業務源庫欄位變更了,下游系統如何處理?另外隨著任務的增多,如何更好的對資料來源資訊進行維護,如一個業務庫遷移,如何優雅的對任務中的資料來源資訊進行變更?首先說元資訊自動對映的問題,Flink CDC 支援豐富的資料來源,這些資料來源都需透過手工的方式對映成 Flink 的 DDL。手工對映表結構是比較繁瑣的,尤其是資料來源頭多、對映關係比較複雜,每種資料來源都有自己的對映關係,當表和欄位數非常多的時候,手工對映也非常容易出錯,對使用者不友好,開發效率也不高。為了解決上述問題,我們開發了統一資料來源服務,我們將平臺中使用到的資料來源統一註冊到資料來源系統中,實現資料來源的統一維護管理,同時實現表結構變更通知,影響分析等。使用者在實時計算平臺建立表和建立同步任務時,選擇對應的資料來源,自動獲取表的 Schema,透過模版化的方式建立表和資料同步任務,同時使用資料來源 ID 對使用者遮蔽連線串和賬號密碼資訊,提升賬號安全性。另外資料來源資訊與任務資訊關聯,資料來源變更或遷移,只需要修改資料來源資訊,降低修改成本。最後離線層的資料接入也依賴於統一資料來源,離線和實時使用同一套後設資料,便於流和批模型的統一。上圖是資料來源改造前後的一個對比圖,前面是原生的 MySQL 的流表,需要連線串、賬號、密碼資訊,統一資料來源之後,在連結串中只需要關注資料來源 ID。同時我們對 Connector 進行了改造,任務在執行時,會將具體的資料來源 ID 替換為真實的連結串、賬號和密碼,對於 Kafka 流表也一樣,在表建立時,只需要資料來源 ID,任務執行時,會替換為 Kafka 的 Server 地址,對於 groupID,在任務中,透過 set 的方式進行設定。這種方式也方便我們進行後續 Kafka 叢集的主備切換。對於其他的資料來源,比如 Hbase、HDFS 等也做了類似的改造。上圖是我們自動建表的頁面,選擇對應的資料來源,需要對映的源表,透過資料來源服務自動獲取源表的 Schema,自動做欄位型別對映,透過模版化的方式,一鍵生成 Flink 的建表語句。上圖是資料同步的配置介面,使用者主要選擇對應的源和目標資料來源、資料表,自動做欄位對映,如果目標表不存在,會自動建立目標表。得益於 MySQL CDC 動態加表功能,也可以在已有任務中,直接增加需要同步的表,新增的表會自動先同步該表的全量資料,然後再無縫切換到同步增量資料。遇到新增監控表時不用新起作業。同時也支援透過正則的方式配置分庫分表的同步,另外對於源表欄位變更,型別變更等,也做了一些適配。接下來介紹下平臺的整體架構,我們對 DTS 平臺、排程平臺、實時平臺進行了深度的整合和整合,任務排程層整合到統一排程平臺中,實現任務的統一管理,主要包含任務的運維管理、許可權管理、資源管控、監控告警、和變數管理等。- 對於任務開發,提供 WebIDE 給使用者進行任務的開發除錯,同時提供語法智慧校驗、檢測功能,便於使用者發現程式碼語法問題。
- 對於任務運維,提供任務診斷、評分、健康檢查、日誌收集、作業快照(Checkpoint、Savapoint)、自動拉起、批次重啟等功能,同時支援任務的容災恢復。
- 對於任務治理,主要包含全鏈路的任務血緣和表血緣,方便的瞭解任務和表的血緣關係和對任務進行影響分析,還有資料層面質量監控,包括斷流、資料量異常波動、資料比對等。
實時計算平臺上主要支援 SQL 任務、Jar 包任務和 DTS 任務。對於 SQL 任務和 Jar 包任務,提供版本管理、資源管理:資源管理主要是將表、UDF、Connector 等資源統一管理,並透過模版化的方式和配置化的方式完成 Source、Sink 表的建立,降低使用者開發成本;對於 TDS 任務,提供資料來源管理、任務配置和資料校驗等一些模組和服務。透過服務平臺化,打造一站式的任務開發管理平臺,在平臺上完成任務從開發到測試、釋出、監控的全流程處理操作,降低使用者使用平臺的門檻。對於核心的 DTS 資料傳輸架構如上,整個架構主要是基於 Flink 1.14 的 DataStream API 和 Flink CDC 2.2 構建,覆蓋流批的場景,實現各種同步需求。整個架構主要包含 Source 端、資料傳輸層、Sink 端, Source 和 Sink 端抽象出 SourceFactory 和 SinkFactory,方便實現對接各種型別資料來源,在資料傳輸層,提供統一的基礎服務框架,支援型別轉換、自定義監控指標、資料校驗等功能,如型別轉換,DTS 中也支援了對 Canal 資料格式的適配。目前 DTS 支援了公司內大部分資料傳輸管道,涵蓋資料庫,如 MySQL、SQL Server 和 TiDB 等;訊息佇列,如 Kafka、RocketMQ 等;以及大資料生態系統的各種元件,例如 HDFS、Hive、ClickHouse、Doris 等,覆蓋了易車大部分實時流場景和少數離線場景。這套資料整合架構如今在易車內部已穩定執行近一年時間,服務於眾多產品線,整套架構對資料整合,有很大的收益。- 統一了技術棧,透過 Flink 可以完成資料異構資料來源的實時整合,同時支援流批一體。
- 透過平臺化的操作,降低了資料接入、任務運維等的複雜度,也無需額外部署 Canal 等元件,降低運維成本,鏈路穩定性也得到了提升。
- Flink CDC 全增量一體化的框架,解決了在資料整合方面全量、增量隔裂的痛點問題,實現了全增量一體化的資料整合。
Flink CDC 的一個主要應用場景就是資料實時入湖,對於資料湖我們主要使用的 Hudi,Hudi 的主要特點如下:- Hudi 的表檔案可以儲存在 HDFS 上,相容 Hadoop 生態圈,可以使用 Hive、Spark、Presto 等引擎查詢 Hudi 表。
- Hudi 表的組織模式也很靈活,可以根據不同場景選擇不同的表模式。
- Hudi 已經整合了 Flink,便於我們計算引擎的統一。最後 Hudi 也有相對比較活躍的社群。
使用 Hudi 後,在沒有引入 Flink CDC 之前,我們的資料入湖架構如下:首先使用 Canal 透過解析 Binlog 的方式將增量資料同步到 Kafka 中,然後透過 DataX,將 MySQL 的全量資料同步到 HDFS 上,然後使用 bulk_insert 的方式初始化資料到 Hudi 中,完成全量資料的初始化,最後,使用 Flink 消費 Kafka 的資料,將資料寫入到 Hudi 中,同時透過主鍵解決資料衝突問題。大家可以看到,這個架構整體的鏈路比較長,操作頻繁、維護成本比較高,涉及的元件比較多,對於完成資料接入工作量比較大,並且穩定性不好保證,如果一旦有資料問題,資料恢復、重導也是一件比較痛苦的事情。在使用 Flink CDC 之後,結合 DTS 平臺,架構如上。在 DTS 平臺中,很方便的可以實現 MySQL 資料一鍵入湖,並且得益於 Flink CDC 全增量一體化框架,不用考慮全增量問題,同時也支援動態增加表功能,操作非常簡單。隨著接入表的增多,對於同一個資料來源下的資料同步任務,建立了過多資料庫連線,導致 Binlog 重複讀取,會對資料來源庫造成巨大的壓力。另外有些 Task 同步的資料量很小,也會造成一定的資源浪費。為了解決這個問題,我們使用 API 的方式讀取資料,透過側輸出流的方式對 DataStream 進行分流,實現合併 Source 的功能。對於讀取的同一資料來源,同一任務只會建立一個資料庫連線,Binlog 也只會讀取一次,降低了對資料庫的壓力,方便的實現了單任務多表的資料實時入湖。在資料實時同步寫入 Hudi 時,Flink Hudi 的寫入 Pipeline 運算元如下。第一個運算元負責將快照資料+增量資料載入到 Flink 狀態。接著經過一個 Bucket Assigner,它主要負責將已經轉好的 HudiRecord 分配到特定的 File Group 中,接著分好 File Group 的 Record 會流入 Writer 運算元執行真正的檔案寫入。再之後會接一個 Compaction 的運算元,主要用來解決 MOR 表讀放大的問題。- 當資料量比較大的時候,Flink State 的膨脹會比較厲害,相應地會影響 Task 的寫入速度以及 Checkpoint 的成功率。
- 對於 Compaction 運算元,當在執行 Compaction 階段時,會和資料讀寫運算元進行資源的搶佔,也會導致任務的背壓、Checkpoint 超時等。
為了解決這個問題,我們把 Compaction 進行單獨拆分,拆分為一個獨立的排程任務,同時為了合併的合理性,對相關的合併計劃也做了一些最佳化。除此之外,我們還做了一些其他的最佳化和 bug 修復。- 第一,在 Hudi 同步 Hive 分割槽時,會對 Hive 外表和 Hudi 表當前表結構、分割槽做比較,會獲取 Hive 的所有分割槽,而我們在 Hive 層面對分割槽訪問做了限制,超過分割槽數量限制,禁止訪問,所以觸發了該問題,我們透過修改原始碼,如果是分割槽表,對訪問 Hive 的分割槽做了過濾,只訪問最近一段時間的分割槽。
- 第二,在業務 MySQL 升級時,出現了混合模式的 Binlog,導致任務失敗,也是修改了原始碼,忽略了一些 DML 的 Binlog 操作,具體 patch 可以參考 3319;
- 第三,解決了一些 Flink CDC 分片的 bug,如 Flink CDC 分片欄位是 String 時,比較邏輯沒有忽略大小寫,導致抽取全量資料到記憶體,導致任務失敗。Flink CDC 分片欄位是 bigint 時,ID 差值較大,觸發了 Flink CDC 的分片最佳化邏輯,但在最佳化邏輯後載入了大量資料到記憶體中,所以最佳化引數,降低資料分佈因子等。
除此之外,還有一些其他最佳化實踐,大部分可以查閱資料或在社群的幫助下解決,在這裡再次感謝社群。
- 第一,全量階段的非同步切片邏輯最佳化,目前資料全量讀取階段讀取流程為首先透過主鍵對錶進行 Snapshot Chunk 劃分,再將 Snapshot Chunk 分發給多個 SourceReader。在所有 Snapshot Chunk 讀取完成後,下發一個 Binlog chunk 進行增量部分的 Binlog 讀取。Snapshot Chunk 劃分及讀取是順序的,影響整個讀取階段的效能,導致大表全量接入階段週期長。所以最佳化 Snapshot Chunk 劃分切片的邏輯,增加非同步讀取策略,提升全量讀取階段效能
- 第二,目前我們的資料整合工具只覆蓋了少量的離線場景,後續準備覆蓋更多的離線資料整合場景。
- 第三,目前我們的實時資料整合的質量相對還比較薄弱,需要進一步加強和打磨。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70027827/viewspace-2946805/,如需轉載,請註明出處,否則將追究法律責任。