1.Datax是什么
DataX 是阿里巴巴集团内被广泛使用的离线数据同步工具/平台,实现包括 MySQL、Oracle、SqlServer、Postgre、HDFS、Hive、ADS、HBase、TableStore(OTS)、MaxCompute(ODPS)、DRDS 等各种异构数据源之间高效的数据同步功能。
2.设计理念
为了解决异构数据源同步问题,DataX将复杂的网状的同步链路变成了星型数据链路,DataX作为中间传输载体负责连接各种数据源。当需要接入一个新的数据源的时候,只需要将此数据源对接到DataX,便能跟已有的数据源做到无缝数据同步。
3.架构设计
DataX本身作为离线数据同步框架,采用Framework + plugin架构构建。将数据源读取和写入抽象成为Reader/Writer插件,纳入到整个同步框架中。
- Reader:Reader为数据采集模块,负责采集数据源的数据,将数据发送给Framework。
- Writer: Writer为数据写入模块,负责不断向Framework取数据,并将数据写入到目的端。
- Framework:Framework用于连接reader和writer,作为两者的数据传输通道,并处理缓冲,流控,并发,数据转换等核心技术问题。
4.支持的数据源
5.作业执行架构
- 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
6.安装部署
环境依赖:
1.jdk安装和环境变量配置
2.python安装和环境变量配置
6.1.下载
在github上下载最新tar包:https://github.com/alibaba/DataX
6.2.解压tar包
tar -zxvf datax.tar.gz
6.3.进入bin目录,执行datax.py脚本
cd datax/bin
执行自检脚本
python datax.py …/job/job.json
运行没有错误说明安装成功
7.数据同步初体验(mysql -> mysql)
以从TEST环境testhybird库同步t_settlement_logistics表到dev环境为例
7.1获取配置模板
这里我们是从mysql数据库同步到mysql数据库,所以read和writer分别是mysqlreader和mysqlwriter
python bin/datax.py -r mysqlreader -w mysqlwriter
7.2编写配置文件
将上面生成的配置模板复制出来,参数可以参考各个插件目录下的docs文档,最终配置如下(logistics.json):
{
“job”: {
“content”: [
{
“reader”: {
“name”: “mysqlreader”,
“parameter”: {
“column”: [’’],
“connection”: [
{
“jdbcUrl”: [“jdbc:mysql://127.0.0.1:3306/testhybird”],
“table”: [“t_settlement_logistics”]
}
],
“password”: “username”,
“username”: “password”,
“where”: “”
}
},
“writer”: {
“name”: “mysqlwriter”,
“parameter”: {
“column”: [""],
“connection”: [
{
“jdbcUrl”: “jdbc:mysql://ip:port/testhybird”,
“table”: [“t_settlement_logistics”]
}
],
“password”: “password”,
“preSql”: [“TRUNCATE t_settlement_logistics”],
“session”: [],
“username”: “username”,
“writeMode”: “insert”
}
}
}
],
“setting”: {
“speed”: {
“channel”: “1”
}
}
}
}
7.3运行
chmod +x logistics.json
python datax.py …/job/logistics.json
7.4运行结果
8.异构数据源支持
插件化的设计使得datax理论上支持任何形式的数据源,目前已经支持的插件满足大部分使用场景,不同数据库的不同表都可以指定table和column来进行同步,联表查询数据源可以使用querySql来自定义sql
9.在线/离线同步
工具支持在线和离线同步,但官方定义为离线同步工具,具体原因可以参照约束限制
10.用户体验
界面:datax没有用户界面,运行依靠编写json文件来执行脚本。可以使用另一个开源项目datax-web
失败重试:内部支持失败重试机制,满足大部分场景需求
DB性能影响:对DB的网卡流量和DB负载有一定的影响,取决于机器性能、通道数、单条记录大小等因素,同步效率越高,DB负载越大
11.约束限制
11.1主备同步数据恢复问题
主备同步问题指Mysql使用主从灾备,备库从主库不间断通过binlog恢复数据。由于主备数据同步存在一定的时间差,特别在于某些特定情况,例如网络延迟等问题,导致备库同步恢复的数据与主库有较大差别,导致从备库同步的数据不是一份当前时间的完整镜像。针对这个问题,我们提供了preSql功能,该功能待补充。
11.2一致性约束
Mysql在数据存储划分中属于RDBMS系统,对外可以提供强一致性数据查询接口。例如当一次同步任务启动运行过程中,当该库存在其他数据写入方写入数据时,MysqlReader完全不会获取到写入更新数据,这是由于数据库本身的快照特性决定的。关于数据库快照特性,请参看MVCC Wikipedia上述是在MysqlReader单线程模型下数据同步一致性的特性,由于MysqlReader可以根据用户配置信息使用了并发数据抽取,因此不能严格保证数据一致性:当MysqlReader根据splitPk进行数据切分后,会先后启动多个并发任务完成数据同步。由于多个并发任务相互之间不属于同一个读事务,同时多个并发任务存在时间间隔。因此这份数据并不是完整的、一致的数据快照信息。针对多线程的一致性快照需求,在技术上目前无法实现,只能从工程角度解决,工程化的方式存在取舍,我们提供几个解决思路给用户,用户可以自行选择:
- 使用单线程同步,即不再进行数据切片。缺点是速度比较慢,但是能够很好保证一致性。
- 关闭其他数据写入方,保证当前数据为静态数据,例如,锁表、关闭备库同步等等。缺点是可能影响在线业务。
11.3数据库编码问题
Mysql本身的编码设置非常灵活,包括指定编码到库、表、字段级别,甚至可以均不同编码。优先级从高到低为字段、表、库、实例。我们不推荐数据库用户设置如此混乱的编码,最好在库级别就统一到UTF-8。MysqlReader底层使用JDBC进行数据抽取,JDBC天然适配各类编码,并在底层进行了编码转换。因此MysqlReader不需用户指定编码,可以自动获取编码并转码。对于Mysql底层写入编码和其设定的编码不一致的混乱情况,MysqlReader对此无法识别,对此也无法提供解决方案,对于这类情况,导出有可能为乱码。
11.4增量数据同步
MysqlReader使用JDBC SELECT语句完成数据抽取工作,因此可以使用SELECT…WHERE…进行增量数据抽取,方式有多种:数据库在线应用写入数据库时,填充modify字段为更改时间戳,包括新增、更新、删除(逻辑删)。对于这类应用,MysqlReader只需要WHERE条件跟上一同步阶段时间戳即可。对于新增流水型数据,MysqlReader可以WHERE条件后跟上一阶段最大自增ID即可。对于业务上无字段区分新增、修改数据情况,MysqlReader也无法进行增量数据同步,只能同步全量数据。
11.5Sql安全性
MysqlReader提供querySql语句交给用户自己实现SELECT抽取语句,MysqlReader本身对querySql不做任何安全性校验。这块交由DataX用户方自己保证。
12.FAQ
Q: MysqlWriter 执行 postSql 语句报错,那么数据导入到目标数据库了吗?
A: DataX 导入过程存在三块逻辑,pre 操作、导入操作、post 操作,其中任意一环报错,DataX 作业报错。由于 DataX 不能保证在同一个事务完成上述几个操作,因此有可能数据已经落入到目标端。
Q: 按照上述说法,那么有部分脏数据导入数据库,如果影响到线上数据库怎么办?
A: 目前有两种解法,第一种配置 pre 语句,该 sql 可以清理当天导入数据, DataX 每次导入时候可以把上次清理干净并导入完整数据。第二种,向临时表导入数据,完成后再 rename 到线上表。