datax原理和源码分析

1.datax介绍


DataX 是阿里云 DataWorks数据集成 的开源版本,在阿里巴巴集团内被广泛使用的离线数据同步工具/平台。DataX 实现了包括 MySQL、Oracle、OceanBase、SqlServer、Postgre、HDFS、Hive、ADS、HBase、TableStore(OTS)、MaxCompute(ODPS)、Hologres、DRDS 等各种异构数据源之间高效的数据同步功能。
在这里插入图片描述

2.datax框架介绍


在这里插入图片描述
DataX本身作为离线数据同步框架,采用Framework + plugin架构构建。将数据源读取和写入抽象成为Reader/Writer插件,纳入到整个同步框架中。

- Reader:Reader为数据采集模块,负责采集数据源的数据,将数据发送给Framework。

- Writer: Writer为数据写入模块,负责不断向Framework取数据,并将数据写入到目的端。

- Framework:Framework用于连接reader和writer,作为两者的数据传输通道,并处理缓冲,流控,并发,数据转换等核心技术问题。


3.datax插件体系

经过几年积累,DataX目前已经有了比较全面的插件体系,主流的RDBMS数据库、NOSQL、大数据计算系统都已经接入。DataX目前支持数据如下:

类型数据源Reader(读)Writer(写)文档
RDBMS 关系型数据库MySQL读、写
RDBMS 关系型数据库Oracle读、写
RDBMS 关系型数据库OceanBase读、写

待补充


4.datax核心架构

DataX 3.0 开源版本支持单机多线程模式完成同步作业运行,本小节按一个DataX作业生命周期的时序图,从整体架构设计非常简要说明DataX各个模块相互关系。

在这里插入图片描述

4.1datax模块介绍

  1. DataX完成单个数据同步的作业,我们称之为Job,DataX接受到一个Job之后,将启动一个进程来完成整个作业同步过程。DataX Job模块是单个作业的中枢管理节点,承担了数据清理、子任务切分(将单一作业计算转化为多个子Task)、TaskGroup管理等功能。
  2. DataXJob启动后,会根据不同的源端切分策略,将Job切分成多个小的Task(子任务),以便于并发执行。Task便是DataX作业的最小单元,每一个Task都会负责一部分数据的同步工作。
  3. 切分多个Task之后,DataX
    Job会调用Scheduler模块,根据配置的并发数据量,将拆分成的Task重新组合,组装成TaskGroup(任务组)。每一个TaskGroup负责以一定的并发运行完毕分配好的所有Task,默认单个任务组的并发数量为5。
  4. 每一个Task都由TaskGroup负责启动,Task启动后,会固定启动Reader—>Channel—>Writer的线程来完成任务同步工作。
  5. DataX作业运行起来之后, Job监控并等待多个TaskGroup模块任务完成,等待所有TaskGroup任务完成后Job成功退出。否则,异常退出,进程退出值非0

5.datax核心源码分析

在这里插入图片描述

5.1JobContainer核心源码分析

JobContainer实现了AbstractContainer的start方法。
方法如下,我们现在主要分析下schedule方法。

在这里插入图片描述

- 生成scheduler实例
在这里插入图片描述

这里的scheduler实现类是StandAloneScheduler。

  • 调用schedule方法
    在这里插入图片描述

在这里插入图片描述

  • 分析startAllTaskGroup方法
    在这里插入图片描述
    ① 首先创建固定数量的线程池
    ② 遍历任务组配置
    ③ 创建TaskGroupContainerRunner对象实例

在这里插入图片描述

点开TaskGroupContainerRunner可以看到,runner实现了Runnable接口,run方法实际调用的是TaskGroupContainer的start方法

在这里插入图片描述

④ 调用TaskGroupContainer.start方法


5.2TaskGroupContainer核心源码分析

这里我们不对每一行代码进行分析,主要分析下start方法。
在这里插入图片描述
前面的逻辑主要是一些初始化参数的配置。

我们重点分析这几行代码

在这里插入图片描述
① 创建并初始化TaskExecutor
TaskExecutor是一个完整的执行器,包括reader和writer以及传输通道channel。

在这里插入图片描述

在这里插入图片描述

② 启动器创建逻辑分析

在这里插入图片描述

在这里插入图片描述

③ 调用doStart方法

在这里插入图片描述

从源码可得知,doStart本质上就是启动了writerTread和readerThread线程。writerTread的Runnable是WriterRunner,readThread的Runnable是ReaderRunner。


5.3.ReaderRunner核心源码分析

ReaderRunner实现了Runnable接口,我们重点关注run方法即可。ReaderRunner的构造方法只有一个参数AbstractTaskPlugin,而AbstractTaskPlugin的实例是通过LoadUtil类加载器创建的,如下图:

在这里插入图片描述

LoadUtil.loadPluginClass底层其实就是通过反射技术获取plugin的实例,有兴趣的同学可以追踪下LoadUtil.getJarLoader的源码,我这里就不多做介绍了,下面我们重点分析run方法。
在开始具体分析之前,我们先看下下面的截图,可以很清晰的发现,核心方法就是startRead,事实上确实如此,基本上所有的reader插件最复杂的部分就是startRead方法的实现。话不多说,我们看下startReader的具体实现是什么样的,下面我以MysqlReader读取插件作为范例,给大家揭开datax读取插件的神秘面纱。

在这里插入图片描述

5.4 MysqlReader核心源码分析

先来一张图:

在这里插入图片描述

Datax给我们提供了一个模板,所有的读取插件都要实现Job、Task两个内部类。而MysqlReader继承Reader并实现了Job和Task两个内部类,如下图:

在这里插入图片描述

本质上,MysqlReader其实是调用了CommonRdbmsReader的方法。它没干啥事,有兴趣的同学可以看下其他的read插件,其实可以发现PostgresReader、OracleReader等关系型数据库都是一样的,都是调用的模板方法。
我们继续往下挖/(ㄒoㄒ)/~~

① Job内部类的实现
实现了init()、preCheck()、split(int adviceNumber)、post()、destory()方法。

  • init方法解读

在这里插入图片描述

commonRdbmsReaderJob.init方法做了什么?我们点进去看下:

在这里插入图片描述

在这里插入图片描述

  • preCheck方法解读

在这里插入图片描述

  • post方法解读
    在这里插入图片描述
  • destroy方法解读
    在这里插入图片描述
  • split方法解读
    在这里插入图片描述

主要是做切分工作,有兴趣的同学可以看下doSplit具体的实现。

② Task内部类的实现
Task内部的实现,主要实现了init和startRead方法,我们只介绍startRead方法。

  • startRead方法解读
    在这里插入图片描述

需要注意的是,每次读取到的数据,都会调用recordSender.sendToWriter方法。Record对象类型是通过core.transport.record.class属性控制的。

在这里插入图片描述

RecordSender的实现类一共有三个,分别是RecordExchanger、BufferedRecordExchanger、BufferedRecordTransformerExchanger。

A.RecordExchanger

在这里插入图片描述

在这里可以做校验或者转换。调用的是TransformerExchanger抽象类的doTransformer方法。然后调用channel.push方法推送至writer,从以上代码可以得出,channel是reader和writer之间数据沟通的桥梁。Channel的实现类只有一个MemoryChannel,底层使用的是ArrayBlockingQueue有界阻塞队列。

在这里插入图片描述

B.BufferedRecordExchanger

在这里插入图片描述

从字面意思上看,BufferedRecordExchanger是一个可以缓存的Record交互类。先判断缓存区是否满了,如果满了会调用flush方法,将所有的数据推送至channel,并清空缓存,重置下标和缓存大小。不管怎么操作,数据最终还是会通过channel流向writer插件

在这里插入图片描述
C.BufferedRecordTransformerExchanger
BufferedRecordTransformerExchanger和BufferedRecordExchanger一样。


5.5.MysqlWriter核心源码分析

先来一张图:

在这里插入图片描述

可以看到,Writer模板和Reader模板比较类似,这里我们着重看下startWrite的实现。

① startWrite方法解读

在这里插入图片描述

在这里插入图片描述

A.调用DBUtil,根据数据库类型、用户、密码、连接URL获取连接。
B.处理session,这里有兴趣可以看到,我们着重介绍下面的方法。
C.startWriteWithConnection方法一个有三个参数,分别是RecordReceiver接收器、taskPluginCollector数据收集器,Connection数据库连接。

在这里插入图片描述

跟踪getFromReader方法:

在这里插入图片描述

其实就是从channel中获取数据,底层就是调用了阻塞队列的take方法。

跟踪doBatchInsert方法:

在这里插入图片描述

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值