DataX 是阿里巴巴集团内被广泛使用的离线数据同步工具/平台,实现包括 MySQL、Oracle、SqlServer、Postgre、HDFS、Hive、ADS、HBase、TableStore(OTS)、MaxCompute(ODPS)、DRDS 等各种异构数据源之间高效的数据同步功能。Datax将不同数据源的同步抽象为从源头数据源读取数据的Reader插件,以及向目标端写入数据的Writer插件,理论上DataX框架可以支持任意数据源类型的数据同步工作。同时DataX插件体系作为一套生态系统, 每接入一套新数据源该新加入的数据源即可实现和现有的数据源互通。
为了解决异构数据源同步问题,DataX将复杂的网状的同步链路变成了星型数据链路,DataX作为中间传输载体负责连接各种数据源。当需要接入一个新的数据源的时候,只需要将此数据源对接到DataX,便能跟已有的数据源做到无缝数据同步。
Reader
:Reader为数据采集模块,负责采集数据源的数据,将数据发送给Framework。Writer
: Writer为数据写入模块,负责不断向Framework取数据,并将数据写入到目的端。Framework
:Framework用于连接reader和writer,作为两者的数据传输通道,并处理缓冲,流控,并发,数据转换等核心技术问题。DataX目前已经有了比较全面的插件体系,主流的RDBMS数据库、NOSQL、大数据计算系统都已经接入,目前支持数据如下图,详情请点击:DataX数据源参考指南
类型 | 数据源 | Reader(读) | Writer(写) | 文档 |
---|---|---|---|---|
RDBMS 关系型数据库 | MySQL | √ | √ | 读 、写 |
Oracle | √ | √ | 读 、写 | |
SQLServer | √ | √ | 读 、写 | |
PostgreSQL | √ | √ | 读 、写 | |
DRDS | √ | √ | 读 、写 | |
通用RDBMS(支持所有关系型数据库) | √ | √ | 读 、写 | |
阿里云数仓数据存储 | ODPS | √ | √ | 读 、写 |
ADS | √ | 写 | ||
OSS | √ | √ | 读 、写 | |
OCS | √ | √ | 读 、写 | |
NoSQL数据存储 | OTS | √ | √ | 读 、写 |
Hbase0.94 | √ | √ | 读 、写 | |
Hbase1.1 | √ | √ | 读 、写 | |
Phoenix4.x | √ | √ | 读 、写 | |
Phoenix5.x | √ | √ | 读 、写 | |
MongoDB | √ | √ | 读 、写 | |
Hive | √ | √ | 读 、写 | |
Cassandra | √ | √ | 读 、写 | |
无结构化数据存储 | TxtFile | √ | √ | 读 、写 |
FTP | √ | √ | 读 、写 | |
HDFS | √ | √ | 读 、写 | |
Elasticsearch | √ | 写 | ||
时间序列数据库 | OpenTSDB | √ | 读 | |
TSDB | √ | √ | 读 、写 |
DataX 3.0 开源版本支持单机多线程模式完成同步作业运行,本小节按一个DataX作业生命周期的时序图,从整体架构设计非常简要说明DataX各个模块相互关系。
举例来说,用户提交了一个DataX作业,并且配置了20个并发,目的是将一个100张分表的mysql数据同步到odps里面。 DataX的调度决策思路是:
方法一、直接下载DataX工具包:DataX下载地址
下载后解压至本地某个目录,进入bin目录,即可运行同步作业:
$ cd {YOUR_DATAX_HOME}/bin
$ python datax.py {YOUR_JOB.json}
方法二、下载DataX源码,自己编译:DataX源码
bin目录下是pytho脚本文件,主要用来执行job文件(默认需要依赖Python2的环境,也可以修改为Python3)
conf目录存放一些配置文件
job目录下存放了一个job测试文件(我们通过datax-web生成的临时job文件不会放在这里,而是在data-web里边自己配置存放目录)
lib是依赖的一些jar包
log目录存放job文件的执行日志
plugin目录存放的是对不同数据源读取(Reader)和写入(Writer)的插件支持
如果没有在plugin目录下发现自己需要的Reader或者Writer则需要自己手动安装(比如ES的Reader和Writer)。
job文件是一个JSON格式的文件,每一个job文件都代表一个同步任务,执行job文件需要使用bin目录datax.py脚本。执行命令如下命令执行job任务:
python datax.py job文件
如果出现控制台乱码在控制台输入:CHCP 65001,再次执行就不会乱码
一个Json格式的Job文件模板如下(Mysql为例):
{
"job": {
"setting": {
"speed": {
"channel": 3,
"byte": 1048576
},
"errorLimit": {
"record": 0,
"percentage": 0.02
}
},
"content": [
{
"reader": {
"name": "mysqlreader",
"parameter": {
"username": "yRjwDFuoPKlqya9h9H2Amg==",
"password": "6YrK4y3NaUxccEgnoAz8yA==",
"column": [
"`id`",
"`course_id`",
"`chapter_id`",
"`title`",
"`video_source_id`",
"`video_original_name`",
"`sort`",
"`play_count`",
"`is_free`",
"`duration`",
"`status`",
"`size`",
"`version`",
"`gmt_create`",
"`gmt_modified`"
],
"where": "gmt_modified >= ${lastTime} and gmt_modified < ${currentTime}",
"splitPk": "",
"connection": [
{
"table": [
"edu_video"
],
"jdbcUrl": [
"jdbc:mysql://127.0.0.1:3306/education_edu?serverTimezone=Asia/Shanghai&useLegacyDatetimeCode=false&useSSL=false&nullNamePatternMatchesAll=true&useUnicode=true"
]
}
]
}
},
"writer": {
"name": "mysqlwriter",
"parameter": {
"username": "yRjwDFuoPKlqya9h9H2Amg==",
"password": "6YrK4y3NaUxccEgnoAz8yA==",
"writeMode": "update",
"column": [
"`id`",
"`course_id`",
"`chapter_id`",
"`title`",
"`video_source_id`",
"`video_original_name`",
"`sort`",
"`play_count`",
"`is_free`",
"`duration`",
"`status`",
"`size`",
"`version`",
"`gmt_create`",
"`gmt_modified`"
],
"connection": [
{
"table": [
"edu_video"
],
"jdbcUrl": "jdbc:mysql://127.0.0.1:3306/datax_web?serverTimezone=Asia/Shanghai&useLegacyDatetimeCode=false&useSSL=false&nullNamePatternMatchesAll=true&useUnicode=true"
}
]
}
}
}
]
}
}
主要包括三部分
setting
reader
writer
如要查看不同数据源的reader和writer的写法可以参照官网或者执行以下命令
# 查看mysql的reader和writer的写法
python datax.py -r mysqlreader -w mysqlwriter
DataX Web是在DataX之上开发的分布式数据同步工具,提供简单易用的操作界面,降低用户使用DataX的学习成本,缩短任务配置时间,避免配置过程中出错。用户可通过页面选择数据源即可创建数据同步任务,RDBMS数据源可批量创建数据同步任务,支持实时查看数据同步进度及日志并提供终止同步功能,集成并二次开发xxl-job可根据时间、自增主键增量同步数据。
任务"执行器"支持集群部署,支持执行器多节点路由策略选择,支持超时控制、失败重试、失败告警、任务依赖,执行器CPU.内存.负载的监控等等。后续还将提供更多的数据源支持、数据转换UDF、表结构同步、数据同步血缘等更为复杂的业务场景。
在mysql数据库创建项目运行所必需要的数据库文件,sql脚本在bin/db目录下
# 端口号
server:
port: 8080
spring:
#数据源,目前仅仅支持Mysql
datasource:
username: root
password: 'root'
url: jdbc:mysql://127.0.0.1:3306/datax_web?serverTimezone=Asia/Shanghai&useLegacyDatetimeCode=false&useSSL=false&nullNamePatternMatchesAll=true&useUnicode=true&characterEncoding=UTF-8
driver-class-name: com.mysql.jdbc.Driver
# 数据库连接池配置
hikari:
## 最小空闲连接数量
minimum-idle: 5
## 空闲连接存活最大时间,默认600000(10分钟)
idle-timeout: 180000
## 连接池最大连接数,默认是10
maximum-pool-size: 10
## 数据库连接超时时间,默认30秒,即30000
connection-timeout: 30000
connection-test-query: SELECT 1
##此属性控制池中连接的最长生命周期,值0表示无限生命周期,默认1800000即30分钟
max-lifetime: 1800000
# datax-web email 不需要可以不用配置
mail:
host: smtp.qq.com
port: 25
username: [email protected]
password: opfmjdcwbnlhefee
properties:
mail:
smtp:
auth: true
starttls:
enable: true
required: true
socketFactory:
class: javax.net.ssl.SSLSocketFactory
management:
health:
mail:
enabled: false
server:
servlet:
context-path: /actuator
mybatis-plus:
# mapper.xml文件扫描
mapper-locations: classpath*:/mybatis-mapper/*Mapper.xml
# 实体扫描,多个package用逗号或者分号分隔
#typeAliasesPackage: com.yibo.essyncclient.*.entity
global-config:
# 数据库相关配置
db-config:
# 主键类型 AUTO:"数据库ID自增", INPUT:"用户输入ID", ID_WORKER:"全局唯一ID (数字类型唯一ID)", UUID:"全局唯一ID UUID";
id-type: AUTO
# 字段策略 IGNORED:"忽略判断",NOT_NULL:"非 NULL 判断"),NOT_EMPTY:"非空判断"
field-strategy: NOT_NULL
# 驼峰下划线转换
column-underline: true
# 逻辑删除
logic-delete-value: 0
logic-not-delete-value: 1
# 数据库类型
db-type: mysql
banner: false
# mybatis原生配置
configuration:
map-underscore-to-camel-case: true
cache-enabled: false
call-setters-on-nulls: true
jdbc-type-for-null: 'null'
type-handlers-package: com.wugui.datax.admin.core.handler
# 配置mybatis-plus打印sql日志
logging:
level:
com.wugui.datax.admin.mapper: error
path: ./data/applogs/admin
#datax-job, access token
datax:
job:
accessToken:
#i18n (default empty as chinese, "en" as english)
i18n:
## triggerpool max size
triggerpool:
fast:
max: 200
slow:
max: 100
### log retention days
logretentiondays: 30
datasource:
aes:
key: AD42F6697B035B75
主要修改数据源的配置
# web port
server:
#port: ${server.port}
port: 8081
# 日志路径
logging:
config: classpath:logback.xml
path: ./data/applogs/executor/jobhandler
datax:
job:
admin:
### datax admin address list, http://address01,http://address02",data-admin的地址
addresses: http://127.0.0.1:8080
executor:
appname: datax-executor # 创建执行器时的AppName需要和这里保持一致
ip:
port: 9999 # 执行器端口号
### job log path job文件的执行日志
logpath: ./data/applogs/executor/jobhandler
### job log retention days
logretentiondays: 30
### job, access token
accessToken:
executor:
# datax json临时文件保存路径
jsonpath: F:\javaProject\datax-web-v-2.1.2\temp\executor
#jsonpath: ${json.path}
# Datax执行文件datax.py的地址
pypath: F:\javaProject\datax\bin\datax.py
#pypath: ${python.path}
datax.job配置
上述准备工作做好后,运行datax_admin下 的DataXAdminApplication和运行datax_executor下 的DataXExecutorApplication
admin启动成功后日志会输出三个地址,两个接口文档地址,一个前端页面地址
注意:windows下如果控制台报错需要hadoop啥的则需要先安装hadoop的环境变量,下载地址:https://github.com/srccodes/hadoop-common-2.2.0-bin,下载成功后解压配置环境变量
如果不配置hadoop环境变量,不能生成.json格式的job任务文件
1、AppName: (与datax-executor中application.yml的datax.job.executor.appname保持一致)
每个执行器集群的唯一标示AppName, 执行器会周期性以AppName为对象进行自动注册。可通过该配置自动发现注册成功的执行器, 供任务调度时使用;
2、名称: 执行器的名称, 因为AppName限制字母数字等组成,可读性不强, 名称为了提高执行器的可读性;
3、排序: 执行器的排序, 系统中需要执行器的地方,如任务新增, 将会按照该排序读取可用的执行器列表;
4、注册方式:调度中心获取执行器地址的方式;
自动注册:执行器自动进行执行器注册,调度中心通过底层注册表可以动态发现执行器机器地址;
手动录入:人工手动录入执行器的地址信息,多地址逗号分隔,供调度中心使用;
5、机器地址:"注册方式"为"手动录入"时有效,支持人工维护执行器的地址信息;
数据源就是数据库的一些连接信息
我们稍后创建的同步任务都是依据任务模板创建的,模板主要配置任务的执行器,路由策略、定时任务等,同一个模板下的任务属于同一个项目。
切分字段splitPk
描述:MysqlReader进行数据抽取时,如果指定splitPk,表示用户希望使用splitPk代表的字段进行数据分片,DataX因此会启动并发任务进行数据同步,这样可以大大提供数据同步的效能。
推荐splitPk用户使用表主键,因为表主键通常情况下比较均匀,因此切分出来的分片也不容易出现数据热点。
目前splitPk仅支持整形数据切分,不支持浮点、字符串、日期等其他类型
。如果用户指定其他非支持类型,MysqlReader将报错!
如果splitPk不填写,包括不提供splitPk或者splitPk值为空,DataX视作使用单通道同步该表数据。
**注意:**在选择字段映射时,源端表字段的选择顺序要和目的端表字段的选择顺序一致
注意:批量构建任务时,源端表和目的端表的数量要一致,需要同步的表勾选的顺序也要一致。
按下图中5个步骤进行配置
1.-D是DataX参数的标识符,必配
2.-D后面的lastTime和currentTime是DataX json中where条件的时间字段标识符,必须和json中的变量名称保持一致
3.='%s'是项目用来去替换时间的占位符,比配并且格式要完全一致
4.注意-DlastTime='%s'和-DcurrentTime='%s'中间有一个空格,空格必须保留并且是一个空格
一个时间增量的Json例子如下
{
"job": {
"setting": {
"speed": {
"channel": 3,
"byte": 1048576
},
"errorLimit": {
"record": 0,
"percentage": 0.02
}
},
"content": [
{
"reader": {
"name": "mysqlreader",
"parameter": {
"username": "yRjwDFuoPKlqya9h9H2Amg==",
"password": "6YrK4y3NaUxccEgnoAz8yA==",
"splitPk": "",
"connection": [
{
"jdbcUrl": [
"jdbc:mysql://127.0.0.1:3306/education_edu?serverTimezone=Asia/Shanghai&useLegacyDatetimeCode=false&useSSL=false&nullNamePatternMatchesAll=true&useUnicode=true"
],
"querySql": [
"select * from edu_teacher_copy1 where gmt_modified >= ${lastTime} and gmt_modified < ${currentTime}"
]
}
]
}
},
"writer": {
"name": "mysqlwriter",
"parameter": {
"username": "yRjwDFuoPKlqya9h9H2Amg==",
"password": "6YrK4y3NaUxccEgnoAz8yA==",
"column": [
"`id`",
"`name`",
"`intro`",
"`career`",
"`level`",
"`avatar`",
"`sort`",
"`join_date`",
"`is_deleted`",
"`gmt_create`",
"`gmt_modified`"
],
"connection": [
{
"table": [
"edu_teacher_copy1"
],
"jdbcUrl": "jdbc:mysql://127.0.0.1:3306/datax_web?serverTimezone=Asia/Shanghai&useLegacyDatetimeCode=false&useSSL=false&nullNamePatternMatchesAll=true&useUnicode=true"
}
]
}
}
}
]
}
}
select * from edu_teacher_copy1 where gmt_modified >= ${lastTime} and gmt_modified < ${currentTime}"
select * from test_list where operationDate >= FROM_UNIXTIME(${lastTime}) and operationDate < FROM_UNIXTIME(${currentTime})
此处还有两点需要注意:
配置增量需要我们创建任务后,在任务管理编辑任务设置辅助参数
为时间自增,并且手动的给json文件Reader–>parameter加上querySql,也就是reader增量查询的sql,当然,简单一点可以不写querySql而直接在reader的parameter加一个where条件
"where": "gmt_modified >= ${lastTime} and gmt_modified < ${currentTime}",
如果使用querySql的方式需要删除掉Reader的column属性和table属性,因为我们的sql中已经指明了我们需要的字段和表
对于Writer我们需要设置parameter–>“writeMode”: “update”,写入模式修改为update过后,datax会对增量的数据依照主键进行判断如果目标表中已经有这条数据就是更新操作,目标表没有这条数据就是新增。默认情况下写入模式是新增和不是update,我们可以手动改Json文件也可以对源码进行修改。
writeModel控制写入数据到目标表采用 insert into
或者 replace into
或者 ON DUPLICATE KEY UPDATE
语句。
insert into
;ON DUPLICATE KEY UPDATE
语句,其他数据库中用replace into
.关于ID自增增量参照官网
关于更详细文档可以参照官网或者doc目录下的文档