異源資料同步 → 如何獲取 DataX 已同步資料量?

青石路發表於2024-11-04

開心一刻

今天,表妹問我:哥,我男朋友過兩天要生日了,你們男生一般喜歡什麼,幫忙推薦個禮物唄
我:預算多少
表妹:預算300
我:20塊買條黑絲,剩下280給自己買支口紅,你男朋友生日那天你都給自己用上
表妹:秒啊,哥
我:必須的嘛,你要知道男人最懂男人!

開心一刻

前情回顧

關於異源資料同步工具 DataX,我已經寫了好幾篇文章

異構資料來源同步之資料同步 → datax 改造,有點意思
異構資料來源同步之資料同步 → datax 再改造,開始觸及原始碼
異構資料來源同步之資料同步 → DataX 使用細節
異構資料來源資料同步 → 從原始碼分析 DataX 敏感資訊的加解密
異源資料同步 → DataX 為什麼要支援 kafka?

推薦大家去看看,可以對 DataX 有個基本的瞭解,掌握其基本使用;示例程式碼:qsl-datax

需求背景

假設我們基於 XXL-JOB 實現排程,qsl-datax-hook 作為 XXL-JOB 執行器的同時也充當 DataX 的拉起方,三者呼叫關係如下

datax同步資料量

離線同步的資料量往往會很大,少則上萬,多則上億,所以同步過程一般會持續很長時間,如何確認同步仍在進行中呢?我們可以看日誌,也可以查目標表的記錄數,但都不夠直觀,好的實現方式應該是有同步任務檢視頁面,透過該頁面可以檢視到正在同步中的任務,以及這些任務已同步的資料量,所以問題就來到

如何獲取 DataX 已同步資料量?

已同步資料量

換做是你們,你們會如何實現?或者說有什麼思路?我提供下我的方案,是不是也是你們所想

DataX 的 Writer 往目標源寫資料的時候,一次寫多少資料我們就記錄多少,然後累加並持久化,是不是就可以實時檢視當前的已同步資料量呢?

具體如何實現了,我們可以基於 DataX 的日誌來實現;我們在講 異構資料來源同步之資料同步 → datax 再改造,開始觸及原始碼 的時候,對日誌進行了調整,qsl-datax-hook 能夠獲取 DataX 程序的日誌輸出,所以我們只需要在 DataX 往目標源寫入資料完成後往日誌中寫入一條記錄(寫入了多少數量),qsl-datax-hook 就能夠獲取該記錄,從而得到寫入資料量,然後進行累加操作;我們以 mysqlwriter 為例,來看看透過程式碼到底如何實現

  1. writer 往日誌中寫 同步資料量

    從哪裡找切入點,我就不繞彎子了

    writer寫日誌起點

    跟進 startWriteWithConnection,有如下程式碼

    doBatchInsert

    可以看到是批次寫入的,繼續跟進 doBatchInsert

    doBatchInsert關鍵點

    分兩種情況

    1. 正常情況,批次插入並 commit 成功

    2. 異常情況,先回滾批次插入,然後透過 doOneInsert

      doOneInsert

      逐條插入

    所以在哪裡寫 同步資料量 的日誌是不是清楚了,有兩個地方需要寫

    1. doBatchInsert 批次插入 commit 之後寫日誌

      批次插入記錄同步資料量
    2. doOneInsert 單條插入後寫日誌

      單挑插入記錄同步資料量

    DataX 就算改造好了,是不是很簡單?

  2. qsl-datax-hook 讀取 DataX 日誌中的 同步資料量 並持久化

    com.qsl.hook.DataXManager#exec 適配改造下即可

    hook適配改造

    做持久化的時候一定要採用

    update table_name set sync_rows = sync_rows + syncRows;
    

    的方式,利用資料庫的鎖來避免併發問題,而採用 set 具體的值

    update table_name set sync_rows = totalSyncRows;
    

    會有併發覆蓋問題,比如第一次將總量更新成 50000,而第二次可能將總量更新成 48000

至此,需求就算基本完成了;其他型別的 DataX writer 可以採用類似的方式來實現,具體就不演示了,你們自行去實現

總結

如果目標源支援事務,那麼 已同步資料量 可以實現的很準確,如果目標源不支援事務,那麼 已同步資料量 實現的就不會很準確,或者說實現難度非常高;文中講到的日誌方式,只是實現方式之一,還有其他的實現方式,例如

  1. 定時讀取目標源的資料量

  2. 改造DataX,直接持久化 已同步資料量

    update table_name set sync_rows = sync_rows + syncRows;
    

各種方式都有其優勢,也存在其弊端,需要結合業務選擇合適的方式

相關文章