DataX 之旅

DataX 概述

DataX 是阿里巴巴开源的一个异构数据源离线同步工具,实现关系型数据库(MySQL、Oracle等)、HDFS、Hive、ODPS、HBase、FTP等异构数据源之间的数据同步功能

源码地址 :

https://github.com/alibaba/DataX

支持的数据源

类型数据源Reader(读)Writer(写)
RDBMS 关系型数据库MySQL
Oracle
OceanBase
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 架构原理

DataX设计理念

为了解决异构数据源同步问题,DataX 将复杂的网状的同步链路变成了星型数据链路,DataX 作为中间传输载体负责连接各种数据源

当需要接入一个新的数据源的时候,只需要将此数据源对接到 DataX ,就与已有的数据源做到无缝数据同步

在这里插入图片描述

框架设计

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

在这里插入图片描述

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

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

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

运行流程

DataX 作业生命周期的时序图 :

在这里插入图片描述

Job:单个数据同步的作业,称为一个 Job ,一个 Job 启动一个进程

Task:根据不同数据源的切分策略,一个 Job 会切分为多个 Task,Task 是 DataX 作业的最小单元,每个 Task 负责一部分数据的同步工作

TaskGroup :Scheduler 调度模块会对 Task 进行分组,每个 Task 组称为一个 Task Group 。每个 TaskGroup 负责以一定的并发度运行其所分得的 Task,单个 Task Group 的并发度为 5

Reader → Channel → Writer:每个 Task 启动后,都会固定启动 Reader → Channel → Writer的线程来完成同步工作

调度决策思路

例子 :

用户提交了一个 DataX 作业,并且配置了总的并发度为 20,目的是对一个有 100 张分表的 mysql 数据源进行同步

DataX 的调度决策思路是:

  • DataX Job 根据分库分表切分策略,将同步工作分成 100 个Task
  • 根据配置的总的并发度20,以及每个 Task Group 的并发度 5,DataX计算共需要分配 4 个TaskGroup
  • 4 个 TaskGroup 平分 100 个Task,每一个 TaskGroup 负责运行 25 个Task

DataX与Sqoop对比

功能DataXSqoop
运行模式单进程多线程MR
分布式不支持,可以通过调度系统规避支持
流控有流控功能需要定制
统计信息已有一些统计,上报需定制没有,分布式的数据收集不方便
数据校验在 core 部分有校验功能没有,分布式的数据收集不方便
监控需要定制需要定制

Data 安装

https://blog.csdn.net/qq_44226094/article/details/123261720?spm=1001.2014.3001.5501

DataX 使用

DataX任务提交命令

用户只需根据自己同步数据的数据源目的地选择相应的 Reader 和 Writer,并将 Reader 和Writer 的信息配置在一个 json 文件中

提交数据同步任务

python bin/datax.py 路径/job.json

DataX配置文件格式

查看 DataX 配置文件模板

python bin/datax.py -r mysqlreader -w hdfswriter

在这里插入图片描述

json 最外层是一个 job

job 包含两部分 :

  • setting : 对整个 job 进行配置
  • content : 配置数据源和目的地
{
    "job": {
        "content": [	数据源和目的地
            {
                "reader": {	配置
                    "name": "mysqlreader",名称, 不可随意
                    "parameter": {	配置参数
						// ...
                    }
                },
                "writer": {	writer配置
                    "name": "hdfswriter",	名称, 不可随意
                    "parameter": {	配置参数
						// ...
                    }
                }
            }
        ],
        "setting": {	job 配置参数, 包括限速配置
            "speed": {
                "channel": ""
            }
        }
    }
}

Reader 和 Writer 的具体参数可参考官方文档 :

https://github.com/alibaba/DataX/blob/master/README.md

https://gitee.com/mirrors/DataX/blob/master/README.md

同步 MySQL 数据到 HDFS 案例

需求 : 同步 gmall 数据库中 base_province 表数据到 HDFS 的 /base_province 目录

需求分析: 要实现该功能,需选用 MySQLReader 和 HDFSWriter

MySQLReader 具有两种模式 :

  • TableMode : table,column,where 等属性声明需要同步的数据
  • QuerySQLMode : SQL查询语句声明需要同步的数据

MySQLReader 之 TableMode

创建配置文件 base_province.json

vim base_province.json

配置文件内容 :

{
    "job": {
        "content": [
            {
                "reader": {
                    "name": "mysqlreader",
                    "parameter": {
                        "column": [
                            "id",
                            "name",
                            "region_id",
                            "area_code",
                            "iso_code",
                            "iso_3166_2"
                        ],
                        "where": "id>=3",
                        "connection": [
                            {
                                "jdbcUrl": [
                                    "jdbc:mysql://cpucode102:3306/gmall"
                                ],
                                "table": [
                                    "base_province"
                                ]
                            }
                        ],
                        "password": "xxxxxx",
                        "splitPk": "",
                        "username": "root"
                    }
                },
                "writer": {
                    "name": "hdfswriter",
                    "parameter": {
                        "column": [
                            {
                                "name": "id",
                                "type": "bigint"
                            },
                            {
                                "name": "name",
                                "type": "string"
                            },
                            {
                                "name": "region_id",
                                "type": "string"
                            },
                            {
                                "name": "area_code",
                                "type": "string"
                            },
                            {
                                "name": "iso_code",
                                "type": "string"
                            },
                            {
                                "name": "iso_3166_2",
                                "type": "string"
                            }
                        ],
                        "compress": "gzip",
                        "defaultFS": "hdfs://cpucode101:8020",
                        "fieldDelimiter": "\t",
                        "fileName": "base_province",
                        "fileType": "text",
                        "path": "/base_province",
                        "writeMode": "append"
                    }
                }
            }
        ],
        "setting": {
            "speed": {
                "channel": 1
            }
        }
    }
}

在这里插入图片描述

配置文件说明

Reader 参数说明

"reader": {
    "name": "mysqlreader", 名称, 固定写法
    "parameter": {
        "column": [
            "id",
            "name",
            "region_id",
            "area_code",
            "iso_code",
            "iso_3166_2"
        ],		同步的列 ,["*"] : 所有列
        "where": "id>=3",	过滤条件
        "connection": [
            {
                "jdbcUrl": [
                    "jdbc:mysql://hadoop102:3306/gmall"
                ], 数据库JDBC URL
                "table": [
                    "base_province"  同步的表名
                ]
            }
        ],
        "password": "xxxxxx", 数据库密码
        "splitPk": "",	分片字段,如指定该字段,会启动多个Task同步数据;若未指定(不提供 splitPk或 splitPk值为空),就是单个Task。只在TableMode下有效,Mysql切为5倍的并发数
        "username": "root"	数据库用户名
    }
}

Writer 参数说明

"writer": {
    "name": "hdfswriter",	固定写法
    "parameter": {
        "column": [
            {
                "name": "id",
                "type": "bigint"
            },
            {
                "name": "name",
                "type": "string"
            },
			//...
        ],
        "compress": "gzip",	HDFS 压缩类型, text支持 : gzip, bzip2。 orc 支持 : NONE, SNAPPY
        "defaultFS": "hdfs://cpucode101:8020",	HDFS namenode节点地址
        "fieldDelimiter": "\t", 字段分隔符
        "fileName": "base_province", HDFS 文件名前缀
        "fileType": "text",		HDFS文件类型, 支持 : text , orc
        "path": "/base_province", HDFS 目标路径
        "writeMode": "append"	数据写入模式, append 追加; nonConflict: 写入目录有同名(前缀相同)文件, 报错
    }
}

HFDS Writer 未提供 nullFormat 参数 , 所以用户并不能自定义 null 值写到 HFDS 文件中的存储格式

默认情况下,HFDS Writer 会将 null 值存储为空字符串(’’),而 Hive 默认的 null 值存储格式为 \N

所以后期 DataX 同步的文件导入 Hive 表就会出现问题

俩种解决方案 :

修改 DataX HDFS Writer 的源码,增加自定义 null 值存储格式的逻辑

在这里插入图片描述

在这里插入图片描述

在 Hive 中建表时指定 null 值存储格式为空字符串(’’)

DROP TABLE IF EXISTS base_province;
CREATE EXTERNAL TABLE base_province
(
    `id`         STRING COMMENT '编号',
    `name`       STRING COMMENT '省份名称',
    `region_id`  STRING COMMENT '地区ID',
    `area_code`  STRING COMMENT '地区编码',
    `iso_code`   STRING COMMENT '旧版ISO-3166-2编码,供可视化使用',
    `iso_3166_2` STRING COMMENT '新版IOS-3166-2编码,供可视化使用'
) COMMENT '省份表'
    ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t'
    NULL DEFINED AS ''
    LOCATION '/base_province/';

Setting 参数说明

{
	"setting":{
		"speend":{	传输速度配置
			"channel": 1	并发数,最终的并发数不一定是该值
		},
		"errorLimit": {	容错比例配置
			"record": 1,	错误条数上限, 超出就任务失败
			"percentage": 0.02	错误比例上限, 超出就任务失败
		}
	}
}

提交任务

在HDFS创建 /base_province 目录

DataX 向 HDFS 同步数据时,需确保目标路径已存在

hadoop fs -mkdir /base_province

在这里插入图片描述

在这里插入图片描述

执行如下命令

python bin/datax.py job/base_province.json

在这里插入图片描述

结果 :

在这里插入图片描述

在这里插入图片描述

查看HDFS文件

hadoop fs -cat /base_province/* | zcat

在这里插入图片描述

MySQLReader之 QuerySQLMode

修改配置文件 base_province_sql.json

vim base_province_sql.json
{
    "job": {
        "content": [
            {
                "reader": {
                    "name": "mysqlreader",
                    "parameter": {
                        "connection": [
                            {
                                "jdbcUrl": [
                                    "jdbc:mysql://cpucode102:3306/gmall"
                                ],
                                "querySql": [
                                    "select id,name,region_id,area_code,iso_code,iso_3166_2 from base_province where id>=3"
                                ]
                            }
                        ],
                        "password": "xxxxxx",
                        "username": "root"
                    }
                },
                "writer": {
                    "name": "hdfswriter",
                    "parameter": {
                        "column": [
                            {
                                "name": "id",
                                "type": "bigint"
                            },
                            {
                                "name": "name",
                                "type": "string"
                            },
                            {
                                "name": "region_id",
                                "type": "string"
                            },
                            {
                                "name": "area_code",
                                "type": "string"
                            },
                            {
                                "name": "iso_code",
                                "type": "string"
                            },
                            {
                                "name": "iso_3166_2",
                                "type": "string"
                            }
                        ],
                        "compress": "gzip",
                        "defaultFS": "hdfs://cpucode101:8020",
                        "fieldDelimiter": "\t",
                        "fileName": "base_province",
                        "fileType": "text",
                        "path": "/base_province",
                        "writeMode": "append"
                    }
                }
            }
        ],
        "setting": {
            "speed": {
                "channel": 1
            }
        }
    }
}

在这里插入图片描述

配置文件说明

Reader参数说明

"reader": {
    "name": "mysqlreader",	名字, 固定写法
    "parameter": {
        "connection": [
            {
                "jdbcUrl": [
                    "jdbc:mysql://cpucode101:3306/gmall"	数据库JDBC URL
                ],
                "querySql": [
                    "select id,name,region_id,area_code,iso_code,iso_3166_2 from base_province where id>=3"	查询语句
                ]
            }
        ],
        "password": "xxxxxx",	数据库密码
        "username": "root"	数据库用户名
    }
}
提交任务

清空历史数据

hadoop fs -rm -r -f /base_province/*

在这里插入图片描述

在这里插入图片描述

进入 DataX 根目录

python bin/datax.py job/base_province_sql.json

在这里插入图片描述

查看HDFS文件

hadoop fs -cat /base_province/* | zcat

在这里插入图片描述

DataX传参

离线数据同步任务需要每日定时重复执行,故 HDFS 上的目标路径通常会包含一层日期,以对每日同步的数据进行区分 ( 每日同步数据的目标路径不同),所以 DataX 配置文件中 HDFS Writer 的 path 参数的值是动态

DataX 传参的用法 :

在 JSON 配置文件中使用 ${param} 引用参数,在提交任务时使用 -p"-Dparam=value" 传入参数值

修改配置文件 base_province_param.json

vim base_province_param.json
{
    "job": {
        "content": [
            {
                "reader": {
                    "name": "mysqlreader",
                    "parameter": {
                        "connection": [
                            {
                                "jdbcUrl": [
                                    "jdbc:mysql://cpucode102:3306/gmall"
                                ],
                                "querySql": [
                                    "select id,name,region_id,area_code,iso_code,iso_3166_2 from base_province where id>=3"
                                ]
                            }
                        ],
                        "password": "xxxxxx",
                        "username": "root"
                    }
                },
                "writer": {
                    "name": "hdfswriter",
                    "parameter": {
                        "column": [
                            {
                                "name": "id",
                                "type": "bigint"
                            },
                            {
                                "name": "name",
                                "type": "string"
                            },
                            {
                                "name": "region_id",
                                "type": "string"
                            },
                            {
                                "name": "area_code",
                                "type": "string"
                            },
                            {
                                "name": "iso_code",
                                "type": "string"
                            },
                            {
                                "name": "iso_3166_2",
                                "type": "string"
                            }
                        ],
                        "compress": "gzip",
                        "defaultFS": "hdfs://cpucode101:8020",
                        "fieldDelimiter": "\t",
                        "fileName": "base_province",
                        "fileType": "text",
                        "path": "/base_province/${dt}",
                        "writeMode": "append"
                    }
                }
            }
        ],
        "setting": {
            "speed": {
                "channel": 1
            }
        }
    }
}

在这里插入图片描述

提交任务

创建目标路径

hadoop fs -mkdir /base_province/2020-06-14

在这里插入图片描述

在这里插入图片描述

执行如下命令

python bin/datax.py -p"-Ddt=2020-06-14" job/base_province.json

在这里插入图片描述

查看结果

hadoop fs -ls /base_province

在这里插入图片描述

同步 HDFS 数据到 MySQL 案例

案例要求:同步 HDFS 上的 /base_province 目录下的数据到 MySQL gmall 数据库下的 test_province

需求分析:要实现该功能,需选用 HDFSReader 和 MySQLWriter

编写配置文件

创建配置文件 base_province_mysql.json

vim base_province_mysql.json

配置文件内容 :

{
    "job": {
        "content": [
            {
                "reader": {
                    "name": "hdfsreader",
                    "parameter": {
                        "defaultFS": "hdfs://cpucode101:8020",
                        "path": "/base_province",
                        "column": [
                            "*"
                        ],
                        "fileType": "text",
                        "compress": "gzip",
                        "encoding": "UTF-8",
                        "nullFormat": "\\N",
                        "fieldDelimiter": "\t",
                    }
                },
                "writer": {
                    "name": "mysqlwriter",
                    "parameter": {
                        "username": "root",
                        "password": "xxxxxx",
                        "connection": [
                            {
                                "table": [
                                    "test_province"
                                ],
                                "jdbcUrl": "jdbc:mysql://cpucode102:3306/gmall?useUnicode=true&characterEncoding=utf-8"
                            }
                        ],
                        "column": [
                            "id",
                            "name",
                            "region_id",
                            "area_code",
                            "iso_code",
                            "iso_3166_2"
                        ],
                        "writeMode": "replace"
                    }
                }
            }
        ],
        "setting": {
            "speed": {
                "channel": 1
            }
        }
    }
}

在这里插入图片描述

配置文件说明

Reader 参数说明

"reader": {
    "name": "hdfsreader",	名称,固定写法
    "parameter": {
        "defaultFS": "hdfs://cpucode101:8020",	namenode地址
        "path": "/base_province",	文件路径
        "column": [
            "*"
        ],	同步的列, 可索引选择列,: {"index": 0, "type": "long"}, {"index": 1, "type": "boolean"}标识前俩列, ["*"]标识所有列
        "fileType": "text",	文件类型, 支持 : textfile(text), orcfile(orc), sequence file(seq), csv文件(csv)
        "compress": "gzip",	压缩类型, 支持: gzip, bz2, zip, lzo, lzo_diflate, snappy
        "encoding": "UTF-8",	文件编码
        "nullFormat": "\\N",	null值存储格式
        "fieldDelimiter": "\t",	字段分隔符
    }
}

Writer 参数说明

"writer": {
    "name": "mysqlwriter",	名称, 固定写法
    "parameter": {
        "username": "root",	数据库用户名
        "password": "xxxxxx",	数据库密码
        "connection": [
            {
                "table": [
                    "test_province"
                ],	目标表
                "jdbcUrl": "jdbc:mysql://cpucode102:3306/gmall?useUnicode=true&characterEncoding=utf-8"	JDBC URL
            }	
        ],
        "column": [
            "id",
            "name",
            "region_id",
            "area_code",
            "iso_code",
            "iso_3166_2"
        ],	目标列
        "writeMode": "replace"	写入方式: 写入目标表 insert into(insert) 或 replace into(replace)ON DUPLICATE KEY UPDATE(update)
    }
}

提交任务

在MySQL中创建 gmall.test_province

DROP TABLE IF EXISTS `test_province`;

CREATE TABLE `test_province`  (
  `id` bigint(20) NOT NULL,
  `name` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `region_id` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `area_code` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `iso_code` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `iso_3166_2` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

在这里插入图片描述

执行如下命令

python bin/datax.py job/base_province_mysql.json 

在这里插入图片描述

查看结果

在这里插入图片描述

DataX 优化

速度控制

DataX3.0 三种流控模式 :

  • 通道(并发)
  • 记录流
  • 字节流

可以随意控制你的作业速度,让作业在数据库可以承受的范围内达到最佳的同步速度

参数说明
job.setting.speed.channel总并发数
job.setting.speed.record总 record 限速
job.setting.speed.byte总 byte 限速
core.transport.channel.speed.record单个 channel 的 record 限速,默认值为 10000(10000 条 / s)
core.transport.channel.speed.byte单个 channel 的 byte 限速,默认值1024 * 1024(1M / s)
  • 配置总 record 限速,则必须配置单个 channel 的 record 限速
  • 配置总 byte 限速,则必须配置单个 channe 的 byte 限速
  • 配置了总 record 限速和总byte限速,channel并发数参数就会失效。因为配置了总record限速和总byte限速之后,实际channel并发数是通过计算得到的:

计算公式为 :

min(总 byte 限速 / 单个 channle 的 byte 限速,总 record 限速 / 单个 channel 的 record 限速 )

配置例子:

{
    "core": {
        "transport": {
            "channel": {
                "speed": {
                    "byte": 1048576 // 单个 channel byte 限速 1M/s
                }
            }
        }
    },
    "job": {
        "setting": {
            "speed": {
                "byte" : 5242880 // 总 byte 限速 5M/s
            }
        },
        ...
    }
}

内存调整

当提升 DataX Job 内 Channel 并发数时,内存的占用会显著增加,因为 DataX 作为数据交换通道,在内存中会缓存较多的数据。

如 : Channel 中会有一个 Buffer,作为临时的数据交换的缓冲区,而在部分 Reader 和 Writer 的中,也会存在一些 Buffer,为了防止 OOM 等错误,需调大JVM 的堆内存

建议将内存设置为4G 或 8G,需根据实际情况来调整

调整 JVM xms xmx参数的两种方式:

  • 更改 datax.py 脚本
  • 启动时,加上对应的参数
python datax/bin/datax.py --jvm="-Xms8G -Xmx8G" 路径/job.json
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值