開心一刻
今天,表妹問我:哥,我男朋友過兩天要生日了,你們男生一般喜歡什麼,幫忙推薦個禮物唄
我:預算多少
表妹:預算300
我:20塊買條黑絲,剩下280給自己買支口紅,你男朋友生日那天你都給自己用上
表妹:秒啊,哥
我:必須的嘛,你要知道男人最懂男人!
前情回顧
關於異源資料同步工具 DataX,我已經寫了好幾篇文章
異構資料來源同步之資料同步 → datax 改造,有點意思
異構資料來源同步之資料同步 → datax 再改造,開始觸及原始碼
異構資料來源同步之資料同步 → DataX 使用細節
異構資料來源資料同步 → 從原始碼分析 DataX 敏感資訊的加解密
異源資料同步 → DataX 為什麼要支援 kafka?
推薦大家去看看,可以對 DataX 有個基本的瞭解,掌握其基本使用;示例程式碼:qsl-datax
需求背景
假設我們基於 XXL-JOB
實現排程,qsl-datax-hook
作為 XXL-JOB 執行器的同時也充當 DataX
的拉起方,三者呼叫關係如下
離線同步的資料量往往會很大,少則上萬,多則上億,所以同步過程一般會持續很長時間,如何確認同步仍在進行中呢?我們可以看日誌,也可以查目標表的記錄數,但都不夠直觀,好的實現方式應該是有同步任務檢視頁面,透過該頁面可以檢視到正在同步中的任務,以及這些任務已同步的資料量,所以問題就來到
如何獲取 DataX 已同步資料量?
已同步資料量
換做是你們,你們會如何實現?或者說有什麼思路?我提供下我的方案,是不是也是你們所想
DataX 的 Writer 往目標源寫資料的時候,一次寫多少資料我們就記錄多少,然後累加並持久化,是不是就可以實時檢視當前的已同步資料量呢?
具體如何實現了,我們可以基於 DataX 的日誌來實現;我們在講 異構資料來源同步之資料同步 → datax 再改造,開始觸及原始碼 的時候,對日誌進行了調整,qsl-datax-hook
能夠獲取 DataX 程序的日誌輸出,所以我們只需要在 DataX 往目標源寫入資料完成後往日誌中寫入一條記錄(寫入了多少數量),qsl-datax-hook 就能夠獲取該記錄,從而得到寫入資料量,然後進行累加操作;我們以 mysqlwriter
為例,來看看透過程式碼到底如何實現
-
writer 往日誌中寫
同步資料量
從哪裡找切入點,我就不繞彎子了
跟進
startWriteWithConnection
,有如下程式碼可以看到是批次寫入的,繼續跟進
doBatchInsert
分兩種情況
-
正常情況,批次插入並 commit 成功
-
異常情況,先回滾批次插入,然後透過
doOneInsert
逐條插入
所以在哪裡寫
同步資料量
的日誌是不是清楚了,有兩個地方需要寫-
doBatchInsert
批次插入 commit 之後寫日誌 -
doOneInsert
單條插入後寫日誌
DataX 就算改造好了,是不是很簡單?
-
-
qsl-datax-hook 讀取 DataX 日誌中的
同步資料量
並持久化com.qsl.hook.DataXManager#exec
適配改造下即可做持久化的時候一定要採用
update table_name set sync_rows = sync_rows + syncRows;
的方式,利用資料庫的鎖來避免併發問題,而採用 set 具體的值
update table_name set sync_rows = totalSyncRows;
會有併發覆蓋問題,比如第一次將總量更新成 50000,而第二次可能將總量更新成 48000
至此,需求就算基本完成了;其他型別的 DataX writer 可以採用類似的方式來實現,具體就不演示了,你們自行去實現
總結
如果目標源支援事務,那麼 已同步資料量
可以實現的很準確,如果目標源不支援事務,那麼 已同步資料量
實現的就不會很準確,或者說實現難度非常高;文中講到的日誌方式,只是實現方式之一,還有其他的實現方式,例如
定時讀取目標源的資料量
改造DataX,直接持久化
已同步資料量
update table_name set sync_rows = sync_rows + syncRows;
各種方式都有其優勢,也存在其弊端,需要結合業務選擇合適的方式