CDC YAML 在阿里雲的最佳實踐

ApacheFlink發表於2024-12-06

摘要:本文投稿自阿里雲開源大資料平臺資料通道團隊,主要介紹了 Flink CDC YAML 在實時計算Flink版的最佳實踐。內容分為以下五個部分:

  1. CDC YAML 簡介
  2. CDC YAML 核心能力
  3. CDC YAML 應用場景阿里雲 
  4. Flink CDC 企業級功能
  5. 十分鐘在阿里雲免費實現一個 CDC YAML 作業

CDC YAML 簡介

CDC YAML 是 Flink CDC [1] 提供的簡單易用的資料整合 API,用於幫助使用者快速構建功能強大的資料同步鏈路,實時地同步業務資料庫中的資料變更和表結構變更實時同步到資料倉儲,資料湖以及其他下游系統。CDC YAML 上手門檻較低,即使沒有研發背景和Flink基礎,使用者也可以較快地完成資料的同步和ETL加工,快速完成資料的實時入湖入倉,加速資料分析效率。

圖片
阿里雲實時計算 Flink 版基於 Flink CDC 提供了資料攝入 CDC YAML 開發[2],透過開發 YAML 作業的方式有效地實現將資料從源端同步到目標端的資料攝入工作,幫助使用者在雲上高效完成資料入湖入倉。
圖片
CDC YAML 核心能力CDC YAML 主要用於同步資料庫變更到其他系統,同步前支援對資料進行簡單處理和清洗,幫助使用者完成秒級的資料同步工作,構建入湖入倉作業,主要的核心能力有以下幾個方面:
圖片
端到端 Data Pipeline:支援秒級同步資料變更和結構變更到其他系統,使用者可以快速構建自己的資料湖和資料倉儲,為資料分析提供基礎。細粒度 Schema Evolution:出於資料安全的考慮,部分高危操作(如刪除表,清空資料等)使用者不希望同步到目標端。CDC YAML 提供細粒度 Schema 變更的能力,幫助使用者限制可同步的資料變更型別。全增量一體化 CDC 讀取:CDC YAML提供了全量和增量的一體化讀取能力,全量資料讀取完成後自動切換增量讀取,無需使用者操作。豐富的 Transform 支援 :支援對資料欄位進行處理後同步到下游,如新增額外計算列,新增後設資料、只同步某些列、重新指定主鍵或分割槽鍵等場景。CDC YAML 內建了豐富的函式,使用者也可以自行開發UDF,相容 Flink 的 UDF。支援對資料來源資料進行過濾,跳過不需要的資料,完成對無用資料和髒資料的清洗工作。靈活的 Route 策略控制:支援自定義資料來源的表同步到目標端表的對映關係,支援一對一、一對多和多對一的多種對映關係,幫助使用者靈活指定目標端表名,支援分庫分表合併的場景。完善的 作業 Metric 支援:為了便於判斷作業執行的階段和狀態,CDC YAML 提供了豐富的指標。如全量階段未處理/已處理的表數量,全量階段未處理/已處理的分片數量、最新一條資料的時間戳等。阿里雲實時計算 Flink 結合使用者需求,YAML 作業支援了更多的上下游,支援同步到常見的資料湖和資料倉儲,已經支援的上下游如下。聯結器支援型別SourceSinkMySQL√×訊息佇列Kafka√√實時數倉Hologres×√Upsert Kafka×√Print×√StarRocks×√流式資料湖倉Paimon×√YAML 作業 與 SQL / DataStream 作業對比Flink 提供了兩種級別的作業開發方式:SQL 和 DataStream,下面會比較一下相比於 SQL 和 DataStream來說 CDC YAML 開發有什麼優勢。CDC YAML 作業相比 SQL 主要有以下一些優勢:資料攝入YAMLSQL自動識別 Schema,支援整庫同步需要人工寫 Create Table 和 Insert 語句支援細粒度 Schema 變更不支援 Schema 變更支援原始 Changelog 同步破壞原始 Changelog 結構支援讀寫多個表讀寫單個表CDC YAML 作業相比 DataStream 作業的優勢如下:資料攝入YAMLDataStream為各級別使用者設計,不只是專家需要熟悉Java和分散式系統隱藏底層細節,便於開發需要熟悉Flink框架YAML格式容易理解和學習需要了解Maven等工具管理相關依賴已有作業方便複用難以複用已有程式碼CDC YAML 應用場景CDC YAML 能夠支援使用者資料同步多種應用場景,下面簡單介紹一些常見的使用場景,以及應該如何使用 CDC YAML 解決這些問題。整庫同步,構建資料湖倉整庫同步是資料同步最常見的一種使用場景,將存在資料庫的資料同步到資料湖或資料倉儲中,為後續的資料分析提供基礎。如下的資料攝入YAML作業可以完成同步整個app_db資料庫到Paimon的工作,快速完成資料入湖的同步工作。source: type: mysql name: MySQL Source hostname: ${secret_values.mysql-hostname} port: 3306 username: flink password: ${secret_values.mysql-password} tables: app_db.. server-id: 18601-18604​sink: type: paimon name: Paimon Sink catalog.properties.metastore: filesystem catalog.properties.warehouse: oss://test-bucket/warehouse catalog.properties.fs.oss.endpoint: oss-cn-beijing-internal.aliyuncs.com catalog.properties.fs.oss.accessKeyId: ${secret_values.test_ak} catalog.properties.fs.oss.accessKeySecret: ${secret_values.test_sk}在整庫同步中,有時需要重新定義同步到目標端的表名,防止發生衝突。或者需要做一些簡單的資料處理和資料過濾工作,這時需要結合 transform 模組和 route 模組完成,transform 模組負責資料處理工作,route 模組負責資料分發工作。例如在如下的整庫同步作業中,為 app_db.customers 表新增額外的計算列 upper 和資料庫名這個後設資料列db,同時在目標端為三張表名新增版本字尾。source: type: mysql name: MySQL Source hostname: ${secret_values.mysql-hostname} port: 3306 username: flink password: ${secret_values.mysql-password} tables: app_db.. server-id: 18601-18604​transform: - source-table: app_db.customers   projection: *, UPPER(name) AS upper, schema_name AS db​route: - source-table: app_db.customers   sink-table: app_db.customers_v1 - source-table: app_db.products   sink-table: app_db.products_v0 - source-table: app_db.orders   sink-table: app_db.orders_v0​sink: type: paimon name: Paimon Sink catalog.properties.metastore: filesystem catalog.properties.warehouse: oss://test-bucket/warehouse catalog.properties.fs.oss.endpoint: oss-cn-beijing-internal.aliyuncs.com catalog.properties.fs.oss.accessKeyId: ${secret_values.test_ak} catalog.properties.fs.oss.accessKeySecret: ${secret_values.test_sk}CDC YAML提供了豐富的內建函式,還支援使用者自定義函式來完成複雜的資料處理。CDC YAML 對Flink SQL 的自定義函式進行了相容,大部分的 Flink 自定義函式可以在資料攝入YAML中直接使用。分庫分表合併在高併發和大資料量場景下,使用者可能選擇將一個表拆分為多個庫的多張表儲存資料,對於分庫分表在分析資料前,希望將資料合併為資料湖倉中的一張表。假設app_db資料庫中只有customers_v0,customers_v1和customers_v2三張表,如下 CDC YAML 作業可以將這三張分表合併為一張表customers,完成分庫分表的資料同步。source: type: mysql name: MySQL Source hostname: ${secret_values.mysql-hostname} port: 3306 username: flink password: ${secret_values.mysql-password} tables: app_db.customers. server-id: 18601-18604​route: - source-table: app_db.customers.   sink-table: app_db.customers​sink: type: paimon name: Paimon Sink catalog.properties.metastore: filesystem catalog.properties.warehouse: oss://test-bucket/warehouse catalog.properties.fs.oss.endpoint: oss-cn-beijing-internal.aliyuncs.com catalog.properties.fs.oss.accessKeyId: ${secret_values.test_ak} catalog.properties.fs.oss.accessKeySecret: ${secret_values.test_sk}原始 Binlog 資料同步 Kafka,對接已有系統使用者除了整庫整表同步,有些場景下需要獲取到詳細的 Changelog 變更歷史,而不是變更後的資料。將 Binlog 同步到 Kafka,結合分散式訊息佇列 Kafka 可以提高資料消費速度,解決消費同一個 Binlog 導致的資料瓶頸。後續能夠使用 Kafka 裡的 Binlog 歷史, 進行資料回放和資料審計工作,或者消費 Kafka 實時監控資料變更歷史,從而觸發通知和報警。由於 Flink SQL 作業裡傳遞的資料結構是 RowData,會將一條 Update 操作拆分為 Update before 和 Update after 兩條訊息傳送,破壞了 Changelog 原有的結構,無法完成原始 Binlog 資料同步。CDC YAML 使用了 SchemaChangeEvent 和 DataChangeEvent 傳遞資料,可以完整保留 Changelog,幫助使用者完成同步原始 Binlog 資料到 Kafka 的工作。如下作業可以將資料庫 app_db 的變更歷史同步到 Kafka,app_db 資料庫下的表 customers、products 和 shipments 的變更會各自寫入對應的 topic 中。source: type: mysql name: MySQL Source hostname: ${secret_values.mysql-hostname} port: 3306 username: flink password: ${secret_values.mysql-password} tables: app_db..* server-id: 18601-18604 metadata-column.include-list: op_ts​sink: type: Kafka name: Kafka Sink properties.bootstrap.servers: ${secret_values.bootstraps-server} properties.enable.idempotence: false儲存時支援使用 debezium-json(預設) 或 canal-json 格式,使用 debezium 或 canal 的歷史同步作業可以平滑切換為使用 Flink CDC YAML 進行同步,下游的消費者無需修改邏輯。以一條Update訊息為例,debezium-json 和 canal-json 資料格式分別如下。{  "before": {    "id": 4,    "name": "John",    "address": "New York",    "phone_number": "2222",    "age": 12 },  "after": {    "id": 4,    "name": "John",    "address": "New York",    "phone_number": "1234",    "age": 12 },  "op": "u",  "source": {    "db": null,    "table": "customers",    "ts_ms": 1728528674000 }}{  "old": [   {      "id": 4,      "name": "John",      "address": "New York",      "phone_number": "2222",      "age": 12   } ],  "data": [   {      "id": 4,      "name": "John",      "address": "New York",      "phone_number": "1234",      "age": 12   } ],  "type": "UPDATE",  "database": null,  "table": "customers",  "pkNames": [    "id" ],  "ts": 1728528674000}細粒度 Schema 變更CDC YAML 作業支援同步資料來源的 Schema 變更到目標端,例如建立表、新增列、重新命名列、更改列型別、刪除列和刪除表等。但是下游目標端可能無法支援全部型別的變更,或者出於資料安全和許可權的考慮,不希望將全部的變更同步到下游。比如希望保留全部歷史資料,不希望執行刪除和清空等操作。為了滿足更多的使用者場景,資料攝入YAML提供了多種變更策略:LENIENT(預設):按照固定的模式,將部分型別的變更轉換後同步或跳過同步,確保 Schema Evolution 的向後相容性。EXCEPTION:不允許變更行為,發生變更時作業丟擲異常。IGNORE:跳過全部變更。EVOLVE:同步所有變更,同步失敗作業丟擲異常。TRY_EVOLVE:嘗試同步變更,目標端不支援變更時不報錯。如果不同的變更策略無法滿足需求,資料攝入YAML還提供了更細粒度的調控配置,在 Sink 模組中設定 include.schema.changes 和 exclude.schema.changes 選項可以控制需要同步的和需要過濾的變更型別。如下作業使用 EVOLVE 模式,可以正常同步全部變更,但是會跳過同步刪除表,刪除列和清空表的操作。source: type: mysql name: MySQL Source hostname: localhost port: 3306 username: username password: password tables: holo_test.\.* server-id: 8601-8604​sink: type: hologres name: Hologres Sink endpoint: ****.hologres.aliyuncs.com:80 dbname: cdcyaml_test username: ${secret_values.holo-username} password: ${secret_values.holo-password} sink.type-normalize-strategy: BROADEN exclude.schema.changes: [drop, truncate.table]  pipeline: name: MySQL to Hologres yaml job schema.change.behavior: EVOLVE寬容模式同步Schema 變更同步相比於資料同步可能耗時更多,因為在多併發情況下需要等全部資料都寫出後,才可以安全地進行 Schema 變更,而且下游的目標端可能無法支援重現全部的 Schema 變更。為了作業能夠更寬容地處理這些變更,在 Hologres 目標端支援了寬容模式同步。Hologres 不支援變更列的型別,在寬容模式下,CDC YAML 將多個 MySQL 資料型別對映到更寬的 Hologres 型別,跳過不必要的型別變更事件,從而讓作業正常執行,可以透過配置項sink.type-normalize-strategy進行更改。例如,如下作業使用 ONLY_BIGINT_OR_TEXT 讓 MySQL 型別只對應到 Hologres 的 int8 和 text 兩種型別。如果 MySQL 某個列型別從 INT 改為 BIGINT ,Hologres 將這兩種 MySQL 型別都對應到 int8 型別,作業不會因為無法處理型別轉換而報錯。source: type: mysql name: MySQL Source hostname: localhost port: 3306 username: username password: password tables: holo_test.\.* server-id: 8601-8604​sink: type: hologres name: Hologres Sink endpoint: ****.hologres.aliyuncs.com:80 dbname: cdcyaml_test username: ${secret_values.holo-username} password: ${secret_values.holo-password} sink.type-normalize-strategy: ONLY_BIGINT_OR_TEXT新增同步表在一些業務場景企業開發了新業務模組(如會員系統、積分系統),需要新增資料庫表,並將其資料同步到現有的資料倉儲、資料湖或實時計算平臺中。或者由於業務調整變化,作業啟動時未同步的表需要同步到資料湖倉。對於在執行中的作業,這些新表就是新增表。新增表存在兩種不同的場景,CDC YAML 對不同新增表場景需要使用不同的處理方式,不需要新增作業。如果新增加的表是空表,由於資料都是新插入的資料,因此不需要同步歷史資料,可以在 mysql source 模組上設定 scan.binlog.newly-added-table.enabled=true。在這種場景下,被 CDC YAML 作業匹配的新建立的表會自動同步到目標端。如果新增加的表是作業啟動前存在的表,客戶希望表裡的歷史資料需要同步,可以在 mysql source 模組上設定 scan.newly-added-table.enabled=true,然後從 savepoint 重啟作業。指定同步位點重跑資料執行中的 CDC YAML 作業可能因為一些預期外的錯誤而退出,比如 Binlog 過期清理,無法解析的 Binlog 內容,解析程式碼的 Bug 等,這些錯誤會導致作業無法從原有位置恢復。CDC YAML 支援使用指定位點啟動作業,透過修正部分資料 + 指定位點的方式,可以幫助作業繼續執行。阿里雲 Flink CDC 企業級功能阿里雲實時計算 Flink 版在支援開源Flink CDC的所有功能外,還結合企業級客戶的需求和場景,提供了以下企業級特性,幫助雲上企業更好地完成資料實時化改造。MySQL CDC 企業級效能最佳化MySQL CDC 消費 Binlog 是單並行度執行的,消費效能存在瓶頸,阿里雲實時計算 Flink 版資料攝入 YAML 對MySQL CDC 消費效能進行了大幅最佳化:Debezium Bump引數最佳化:Debezium 讀取資料時,一些引數可以適當調整以獲取更好的效能。該方式對比開源 Flink CDC 可以提高11%的效能。過濾無關表資料:MySQL CDC 消費整個例項的 Binlog,跳過不匹配的表的資料可以加速解析。該方式提升的效能取決於無關表資料的佔比。並行解析 Binlog:Binlog 解析位元組流時,可以從單併發最佳化為多併發加速解析速度。該方式對比開源 Flink CDC 可以提高14%的效能。並行序列化:透過火焰圖發現 CPU 在完成從 Event 到 SourceRecord 和從 SourceRecord 到 JSON 的序列化過程中耗時較多,最佳化為並行序列化並保序可以提高效能。該方式對比開源 Flink CDC 可以提高42%的效能。結合以上 4 種最佳化方式,實時計算 Flink 版資料攝入 YAML 相比於社群 Flink CDC 來說,如果 Binlog 只有單個表的資料,普適的效能會提升 80%左右;如果 Binlog 包含多個表的資料且 YAML 作業只需要同步部分表,則可以獲得 10 倍左右的效能提升。OSS 持久化 binlog 消費支援MySQL 的資料庫例項只有一份 Binlog,如果資料更新太快很可能導致消費速度趕不上生產速度,從而 Binlog 日誌被清理,無法從消費失敗的位置指定位點重啟作業。阿里雲 RDS MySQL 例項支援將 Binlog 同步到 OSS,MySQL CDC 可以使用這部分離線的日誌啟動作業。使用者使用 RDS MySQL 作為上游時,可以指定對應 OSS 配置,當指定的時間戳或者 Binlog 位點對應的檔案儲存在 OSS 時,會自動拉取 OSS 日誌檔案到 Flink 叢集本地進行讀取,當指定的時間戳或者 Binlog 位點對應的檔案儲存在資料庫本地時,會自動切換使用資料庫連線讀取,徹底解決 Binlog 日誌過期導致的作業重跑或資料不一致問題。更豐富的監控指標為了便於判斷作業執行的階段和狀態,商業版提供更豐富的監控指標。當前作業處於全量或增量階段全量階段未處理/已處理的表數量全量階段未處理/已處理的分片數量最新一條資料的時間戳讀取資料的延遲全量階段的訊息條數/全量階段每個表的訊息條數訊息總條數/每個表的訊息條數十分鐘在阿里雲免費實現一個 CDC YAML 作業接下來我們使用阿里雲免費試用 [3] 來快速測試一下 CDC YAML 作業的功能,完成一個簡單的 MySQL 到 Paimon 的整庫同步作業。資源準備開始測試前需要準備好一個 RDS MySQL 例項,一個實時計算 Flink 版環境,一個 OSS 物件儲存。OSS 物件儲存OSS 物件儲存用作資料湖儲存,並且用在實時計算 Flink 版的 checkpoint 儲存。在免費試用搜尋oss,點選立即試用物件儲存 OSS。
圖片
試用成功後,在 OSS 控制檯建立一個杭州地區的Bucket。建立成功後,在新建的 Bucket 的檔案列表中新建目錄 warehouse,用於儲存資料湖資料。
圖片
RDS MySQL 例項RDS MySQL 作為測試的 MySQL 資料來源。在免費試用搜尋RDS MySQL,點選立即試用雲資料庫 RDS MySQL。
圖片
試用成功後,在 RDS 控制檯建立一個杭州地區的RDS MySQL叢集。在例項列表點選進入剛建立的例項,在賬號管理建立一個高許可權賬號。
圖片
賬號建立完成後,在資料庫管理建立一個資料庫用於測試。
圖片
點選登入資料庫,使用使用者名稱和密碼登入,然後在資料庫下建立一些表並插入測試資料。此處建立了products 和 users 兩張表,每個表各生成 5 條測試資料。
圖片
在白名單與安全組點選全部開放,打通網路連線。此處因為測試目的使用了全部開放,在生產環境請合理配置白名單。實時計算 Flink 版在免費試用搜尋 flink,點選立即試用實時計算 Flink 版。
圖片
完成RAM授權並領取資源抵扣包後,在杭州地區與RDS相同的可用區建立實時計算 Flink 版例項。建立 AccessKeyPaimon 訪問 OSS 時需要使用 AccessKey,參照建立AccessKey文件[4]建立 AccessKey。CDC YAML 整庫同步 Paimon當所需資源和測試資料都準備好後,接下來讓我們在實時計算 Flink 版本上快速開發整庫同步作業。為了資料安全,可以將需要使用的資訊在變數管理用密文儲存。
圖片
儲存好變數後,在資料攝入中建立一個整庫同步作業並部署上線。
圖片
部署成功後,在作業運維點選啟動按鈕啟動作業。
圖片
作業啟動後,可以在監控告警的資料攝入看到 CDC YAML 同步狀態。如下監控可以看出測試作業已經進入了增量階段,一共同步了2張表,2個分片,每個表全量分別同步了5條資料。
圖片

圖片
為了檢視測試資料,可以使用資料開發 ETL 的除錯功能。首先在後設資料管理建立對應的Paimon Catalog。
圖片
建立一個 Session 叢集用於執行檢視資料結果的 SQL,注意選擇資料攝入支援的引擎版本。
圖片
在資料開發 ETL 中,建立一個 select SQL 作業檢視資料,點選除錯在 Session 叢集執行,可以在控制檯檢視資料結果。
圖片
至此一個完整的業務案例就已經實現了,接下來可以自由地在 RDS MySQL 資料庫側操作相應的資料修改,重新執行 select 命令檢視資料時,變能夠觀察到透過YAML作業實時同步到Paimon中的資料了。相關連結[1] https://nightlies.apache.org/flink/flink-cdc-docs-stable/[2] https://help.aliyun.com/zh/flink/user-guide/develop-a-yaml-dr...[3] https://free.aliyun.com/[4] https://help.aliyun.com/zh/ram/user-guide/create-an-accesskey...

相關文章