DATAX执行过程
要想进行调优,一般先要了解执行过程,执行过程如下:
架构图来自官方文档
核心模块介绍:
DataX
完成单个数据同步的作业,我们称之为Job
,DataX
接受到一个Job
之后,将启动一个进程来完成整个作业同步过程。DataX Job
模块是单个作业的中枢管理节点,承担了数据清理、子任务切分(将单一作业计算转化为多个子Task
)、TaskGroup
管理等功能。DataXJob
启动后,会根据不同的源端切分策略,将Job
切分成多个小的Task
(子任务),以便于并发执行。Task
便是DataX
作业的最小单元,每一个Task
都会负责一部分数据的同步工作。- 切分多个
Task
之后,DataX Job
会调用Scheduler
模块,根据配置的并发数据量,将拆分成的Task
重新组合,组装成TaskGroup(任务组)
。每一个TaskGroup
负责以一定的并发运行完毕分配好的所有Task
,默认单个任务组的并发数量为5。 - 每一个
Task
都由TaskGroup
负责启动,Task
启动后,会固定启动Reader—>Channel—>Writer
的线程来完成任务同步工作 DataX
作业运行起来之后,Job
监控并等待多个TaskGroup
模块任务完成,等待所有TaskGroup
任务完成后Job
成功退出。否则,异常退出,进程退出值非0
DataX调度流程:
举例来说,用户提交了一个DataX
作业,并且配置了20
个并发,目的是将一个100
张分表的mysql
数据同步到odps
里面。 DataX的调度决策思路是:
DataXJob
根据分库分表切分成了100个Task
。- 根据
20
个并发,DataX
计算共需要分配4个TaskGroup
。 - 4个
TaskGroup
平分切分好的100
个Task,每一个TaskGroup
负责以5
个并发共计运行25个Task
。
简单总结过程如下:
一个DataX Job
会切分成多个Task
,每个Task
会按TaskGroup
进行分组,一个Task
内部会有一组Reader->Channel->Writer
。Channel
是连接Reader
和Writer
的数据交换通道,所有的数据都会经由Channel
进行传输
优化
根据过程,我们可以进行如下优化
优化1:提升每个channel的速度
在DataX内部对每个Channel会有严格的速度控制,分两种,一种是控制每秒同步的记录数,另外一种是每秒同步的字节数,默认的速度限制是1MB/s
,可以根据具体硬件情况设置这个byte速度或者record速度,一般设置byte速度,比如:我们可以把单个Channel的速度上限配置为5MB
优化2:提升DataX Job内Channel并发数
并发数=taskGroup的数量每一个TaskGroup并发执行的Task数 (默认单个任务组的并发数量为5)
。
提升job
内Channel
并发有三种配置方式:
- 配置全局
Byte
限速以及单Channel Byte
限速,Channel个数 = 全局Byte限速 / 单Channel Byte限速 - 配置全局
Record
限速以及单Channel Record
限速,Channel个数 = 全局Record限速 / 单Channel Record限速 - 直接配置Channel个数.
配置含义:
job.setting.speed.channel : channel并发数
job.setting.speed.record : 全局配置channel的record限速(总record限速)
job.setting.speed.byte:全局配置channel的byte限速(总byte限速)
core.transport.channel.speed.record:单个channel的record限速,默认值为10000(10000条/s)
core.transport.channel.speed.byte:单个channel的byte限速,默认值1024*1024(1M/s)
注意事项:
(1)若配置了总record
限速,则必须配置单个channel
的record
限速
(2)若配置了总byte
限速,则必须配置单个channel
的byte
限速
(3)若配置了总record限速和总byte限速,channel并发数参数就会失效。因为配置了总record限速和总byte限速之后,实际channel并发数是通过计算得到的:
举例
方式一
举例如下:core.transport.channel.speed.byte=1048576,job.setting.speed.byte=5242880,所以Channel个数 = 全局Byte限速 / 单Channel Byte限速=5242880/1048576=5个,配置如下:
{
"core": {
"transport": {
"channel": {
"speed": {
"byte": 1048576
}
}
}
},
"job": {
"setting": {
"speed": {
"byte" : 5242880
}
},
...
}
}
方式二
举例如下:core.transport.channel.speed.record=100
,job.setting.speed.record=500
,所以配置全局Record限速以及单Channel Record限速,Channel个数 = 全局Record限速 / 单Channel Record限速=500/100=5
{
"core": {
"transport": {
"channel": {
"speed": {
"record": 100
}
}
}
},
"job": {
"setting": {
"speed": {
"record" : 500
}
},
...
}
}
方式三
举例如下:直接配置job.setting.speed.channel=5,所以job内Channel并发=5个
{
"job": {
"setting": {
"speed": {
"channel" : 5
}
},
...
}
}
内存调整
当提升DataX Job
内Channel
并发数时,内存的占用会显著增加,因为DataX作为数据交换通道,在内存中会缓存较多的数据。例如Channel中会有一个Buffer,作为临时的数据交换的缓冲区,而在部分Reader和Writer的中,也会存在一些Buffer,为了防止OOM等错误,需调大JVM的堆内存。
- 当一个
Job
内Channel
数变多后,内存的占用会显著增加,因为DataX
作为数据交换通道,在内存中会缓存较多的数据。 - 例如
Channel
中会有一个Buffer
,作为临时的数据交换的缓冲区,而在部分Reader和Write
r的中,也会存在一些Buffer
,为了防止jvm报内存溢出等错误,调大jvm的堆参数。 - 通常我们建议将内存设置为4G或者8G,这个也可以根据实际情况来调整
- 调整
JVM xms xmx
参数的两种方式:一种是直接更改datax.py
;另一种是在启动的时候,加上对应的参数,如下:
python datax/bin/datax.py --jvm="-Xms8G -Xmx8G" XXX.json
Channel个数并不是越多越好, 原因如下:
Channel
个数的增加,带来的是更多的CPU
消耗以及内存消耗。- 如果Channel并发配置过高导致JVM内存不够用,会出现的情况是发生频繁的Full GC,导出速度会骤降,适得其反。这个可以通过观察日志发现
注意:
MysqlReader进行数据抽取时,如果指定splitPk
,表示用户希望使用splitPk
代表的字段进行数据分片,DataX因此会启动并发任务进行数据同步,这样可以大大提供数据同步的效能,splitPk不填写,包括不提供splitPk或者splitPk值为空,DataX视作使用单通道同步该表数据,第三个测试不配置splitPk测试不出来效果。