异源数据同步 → 如何获取 DataX 已同步数据量?
开心一刻
今天,表妹问我:哥,我男朋友过两天要生日了,你们男生一般喜欢什么,帮忙推荐个礼物呗
我:预算多少
表妹:预算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;
各种方式都有其优势,也存在其弊端,需要结合业务选择合适的方式