开心一刻

今天,表妹问我:哥,我男朋友过两天要生日了,你们男生一般喜欢什么,帮忙推荐个礼物呗
我:预算多少
表妹:预算300
我:20块买条黑丝,剩下280给自己买支口红,你男朋友生日那天你都给自己用上
表妹:秒啊,哥
我:必须的嘛,你要知道男人最懂男人!

异源数据同步 → 如何获取 DataX 已同步数据量?_数据同步

前情回顾

关于异源数据同步工具 DataX,我已经写了好几篇文章

异构数据源同步之数据同步 → datax 改造,有点意思异构数据源同步之数据同步 → datax 再改造,开始触及源码异构数据源同步之数据同步 → DataX 使用细节异构数据源数据同步 → 从源码分析 DataX 敏感信息的加解密异源数据同步 → DataX 为什么要支持 kafka?

推荐大家去看看,可以对 DataX 有个基本的了解,掌握其基本使用;示例代码:qsl-datax

需求背景

假设我们基于 XXL-JOB 实现调度,qsl-datax-hook 作为 XXL-JOB 执行器的同时也充当 DataX 的拉起方,三者调用关系如下

异源数据同步 → 如何获取 DataX 已同步数据量?_异构_02

离线同步的数据量往往会很大,少则上万,多则上亿,所以同步过程一般会持续很长时间,如何确认同步仍在进行中呢?我们可以看日志,也可以查目标表的记录数,但都不够直观,好的实现方式应该是有同步任务查看页面,通过该页面可以查看到正在同步中的任务,以及这些任务已同步的数据量,所以问题就来到

如何获取 DataX 已同步数据量?

已同步数据量

换做是你们,你们会如何实现?或者说有什么思路?我提供下我的方案,是不是也是你们所想

DataX 的 Writer 往目标源写数据的时候,一次写多少数据我们就记录多少,然后累加并持久化,是不是就可以实时查看当前的已同步数据量呢?

具体如何实现了,我们可以基于 DataX 的日志来实现;我们在讲 异构数据源同步之数据同步 → datax 再改造,开始触及源码 的时候,对日志进行了调整,qsl-datax-hook 能够获取 DataX 进程的日志输出,所以我们只需要在 DataX 往目标源写入数据完成后往日志中写入一条记录(写入了多少数量),qsl-datax-hook 就能够获取该记录,从而得到写入数据量,然后进行累加操作;我们以 mysqlwriter 为例,来看看通过代码到底如何实现

  1. writer 往日志中写 同步数据量从哪里找切入点,我就不绕弯子了

跟进 startWriteWithConnection,有如下代码

异源数据同步 → 如何获取 DataX 已同步数据量?_异构_03

可以看到是批量写入的,继续跟进 doBatchInsert

异源数据同步 → 如何获取 DataX 已同步数据量?_数据同步_04

分两种情况

  1. 正常情况,批量插入并 commit 成功

  2. 异常情况,先回滚批量插入,然后通过 doOneInsert

  3. 异源数据同步 → 如何获取 DataX 已同步数据量?_数据源_05

    逐条插入

所以在哪里写 同步数据量 的日志是不是清楚了,有两个地方需要写

  1. doBatchInsert 批量插入 commit 之后写日志

  2. 异源数据同步 → 如何获取 DataX 已同步数据量?_数据源_06

  3. doOneInsert 单条插入后写日志

  4. 异源数据同步 → 如何获取 DataX 已同步数据量?_数据源_07

DataX 就算改造好了,是不是很简单?

  1. 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 可以采用类似的方式来实现,具体就不演示了,你们自行去实现

总结

如果目标源支持事务,那么 已同步数据量 可以实现的很准确,如果目标源不支持事务,那么 已同步数据量 实现的就不会很准确,或者说实现难度非常高;文中讲到的日志方式,只是实现方式之一,还有其他的实现方式,例如

  1. 定时读取目标源的数据量
  2. 改造DataX,直接持久化 已同步数据量

update table_name set sync_rows = sync_rows + syncRows;

各种方式都有其优势,也存在其弊端,需要结合业务选择合适的方式