一、DataX基础
1、了解
java 解决的是高并发问题,大数据解决的是海量数据存储与分析问题。
可以理解为国内版的Sqoop。
但是比Sqoop要快,Sqoop底层是MR(Map任务),基于磁盘的,DataX基于内存的,所以速度比较快。
DataX 是阿里巴巴集团内被广泛使用的离线数据同步工具/平台,实现包括 MySQL、SQL Server、Oracle、PostgreSQL、HDFS、Hive、HBase、OTS、ODPS 等各种异构数据源之间高效的数据同步功能。
DataX 是一个异构数据源离线同步工具,致力于实现包括关系型数据库(MySQL、Oracle等)、HDFS、Hive、ODPS、HBase、FTP等各种异构数据源之间稳定高效的数据同步功能。
关系型数据库的数据都是结构化的,排列非常整齐
非关系型数据库都是非结构化的,非常的错乱。(异构)
2、下载地址
此前已经开源DataX1.0版本,此次介绍为阿里云开源全新版本DataX3.0,有了更多更强大的功能和更好的使用体验。Github主页地址:https://github.com/alibaba/DataX
DataX是阿里云DataWorks数据集成的开源版本。
假如github访问速度比较慢,或者访问不上,科学上网。
也可以使用FastGitHub软件。
再次访问:
GitHub - alibaba/DataX: DataX是阿里云DataWorks数据集成的开源版本。
3、DataX3.0 框架设计
类似于之前的Flume:
source --> ReadPlugin
channel --> Channel
sink --> WritePlugin
4、支持的数据源有哪些(几乎所有)
5、核心架构
一个Job要想执行,可能会拆分成多个Task任务,这些任务又会分为很多个组,每一个组里面,又根据channel的数量,进行汇总,并行执行,默认一个TaskGroup 有 5个channel
计算题:
假如一个Job,被拆分为100个任务,20 个组,每个组里面并行执行5个任务。
job 100个任务
TaskGroup 假如需要20个并发量
每一个TaskGroup 默认是5个任务
用户提交了一个DataX作业,并且配置了20个并发,目的是将一个100张分表的mysql数据同步到HDFS里面。 DataX的调度决策思路是:
1. DataXJob根据分库分表切分成了100个Task。
2. 根据20个并发,DataX计算共需要分配4个TaskGroup。
3. 4个TaskGroup平分切分好的100个Task,每一个TaskGroup负责以5个并发共计运行25个Task
6、安装
1、上传 /opt/modules
2、解压 tar -zxvf datax.tar.gz -C /opt/installs
3、修改/etc/profile
配置环境变量:
export DATAX_HOME=/opt/installs/datax
export PATH=$PATH:$DATAX_HOME/bin
source /etc/profile
测试一下:
Play一下自带的案例:
编辑这个案例:job.json文件
运行一下:
datax.py job.json
假如你运行报错如下:
报错:
配置信息错误,您提供的配置文件[/opt/installs/datax/plugin/reader/._drdsreader/plugin.json]不存在. 请检查您的配置文件
解决方案如下:
rm -rf /opt/installs/datax/plugin/*/._*
说明运行该脚本的位置不对,找不到对应的json文件。
因为以后要链接mysql数据库,mysql数据库的驱动包少不了:
cp /opt/installs/sqoop/lib/mysql-connector-java-8.0.26.jar /opt/installs/datax/lib/
7、实战
1) MySQLReader 案例
在job 文件夹 创建一个文件 mysql2stream.json ,代码如下
{
"job": {
"setting": {
"speed": {
"channel":1
}
},
"content": [
{
"reader": {
"name": "mysqlreader",
"parameter": {
"username": "root",
"password": "123456",
"connection": [
{
"querySql": [
"select * from emp where empno < 7788;"
],
"jdbcUrl": [
"jdbc:mysql://bigdata01:3306/sqoop"
]
}
]
}
},
"writer": {
"name": "streamwriter",
"parameter": {
"print": true,
"encoding": "UTF-8"
}
}
}
]
}
}
读取mysql的数据,将数据展示在控制台上。此时的stream其实就是控制台
{
"job": {
"setting": {
"speed": {
"channel": 3
},
"errorLimit": {
"record": 0,
"percentage": 0.02
}
},
"content": [
{
"reader": {
"name": "mysqlreader",
"parameter": {
"username": "root",
"password": "123456",
"column": [
"empno",
"ename"
],
"splitPk": "empno",
"connection": [
{
"table": [
"emp"
],
"jdbcUrl": [
"jdbc:mysql://bigdata01:3306/sqoop"
]
}
]
}
},
"writer": {
"name": "streamwriter",
"parameter": {
"print":true
}
}
}
]
}
}
运行:
datax.py mysql2stream.json
2) 含有sql语句的mysqlReader案例
{
"job": {
"setting": {
"speed": {
"channel": 1
}
},
"content": [
{
"reader": {
"name": "mysqlreader",
"parameter": {
"username": "root",
"password": "123456",
"connection": [
{
"querySql": ["select * from emp where comm is not null;"],
"jdbcUrl": ["jdbc:mysql://bigdata01:3306/sqoop"]
}
]
}
},
"writer": {
"name": "streamwriter",
"parameter": {
"print": true,
"encoding": "UTF-8"
}
}
}
]
}
}
特殊说明:
如果你编写的json文件中需要用到字段类型,必须指定DataX内部类型,不要使用Mysql类型和java类型
3) MySQLWriter 展示
{
"job": {
"setting": {
"speed": {
"channel": 1
}
},
"content": [
{
"reader": {
"name": "streamreader",
"parameter": {
"column": [
{"value": "9870", "type": "long" },
{"value": "SHAWN", "type": "string"},
{"value": "BOSS", "type": "string"},
{"value": "1999-01-01", "type": "string"},
{"value": "99999", "type": "long"}
],
"sliceRecordCount": 10
}
},
"writer": {
"name": "mysqlwriter",
"parameter": {
"writeMode": "insert",
"username": "root",
"password": "123456",
"column": ["empno", "ename", "job", "hiredate", "sal"],
"connection": [
{
"jdbcUrl": "jdbc:mysql://bigdata01:3306/sqoop",
"table": ["emp"]
}
]
}
}
}
]
}
}
由于emp表中empno是主键,所以10条数据,只插入了一条。
mysql Writer 的另一个案例:
{
"job": {
"setting": {
"speed": {
"channel": 1
}
},
"content": [
{
"reader": {
"name": "streamreader",
"parameter": {
"column": [
{"value": "9870", "type": "long" },
{"value": "ZhangSan", "type": "string"},
{"value": "BOSS", "type": "string"},
{"value": "1999-01-01", "type": "string"},
{"value": "99999", "type": "long"}
],
"sliceRecordCount": 10
}
},
"writer": {
"name": "mysqlwriter",
"parameter": {
"writeMode": "replace",
"username": "root",
"password": "123456",
"column": ["empno", "ename", "job", "hiredate", "sal"],
"preSql": ["delete from emp"],
"connection": [
{
"jdbcUrl": "jdbc:mysql://bigdata01:3306/sqoop",
"table": ["emp"]
}
]
}
}
}
]
}
}
insert into 插入 不判断,直接插入
replace into 先查看这个主键是否有数据,如果有直接删除并插入,如果没有,直接插入。
4) HDFSReader 案例展示
{
"job": {
"setting": {
"speed": {
"channel": 3
}
},
"content": [
{
"reader": {
"name": "hdfsreader",
"parameter": {
"path": "/home/a.txt",
"defaultFS": "hdfs://bigdata01:9820",
"column": [ "*" ],
"fileType": "text"
}
},
"writer": {
"name": "streamwriter",
"parameter": {
"print": true
}
}
}
]
}
}
5) HDFS只读取部分列值
{
"job": {
"setting": {
"speed": {
"channel": 3
}
},
"content": [
{
"reader": {
"name": "hdfsreader",
"parameter": {
"path": "/home/1.txt",
"defaultFS": "hdfs://bigdata01:9820",
"column": [
{"index": 1, "type": "long"},
{"index": 0, "type": "long"},
{"value": "老闫真帅", "type": "string"}
],
"fileType": "text",
"encoding": "UTF-8",
"filedDelimiter": ","
}
},
"writer": {
"name": "streamwriter",
"parameter": {
"print": true
}
}
}
]
}
}
6) 将数据导入到hdfs上,即 hdfsWriter 案例
{
"job": {
"setting": {
"speed": {
"channel": 3
}
},
"content": [
{
"reader": {
"name": "streamreader",
"parameter": {
"column": [
{"value": "9870", "type": "long" },
{"value": "SHAWN", "type": "string"},
{"value": "BOSS", "type": "string"},
{"value": "1999-01-01", "type": "string"},
{"value": "99999", "type": "long"}
],
"sliceRecordCount": 10
}
},
"writer": {
"name": "hdfswriter",
"parameter": {
"defaultFS": "hdfs://bigdata01:9820",
"path": "/datax/emp",
"fileName": "emp",
"column": [
{"name": "empno", "type": "string"},
{"name": "ename", "type": "string"},
{"name": "job", "type": "string"},
{"name": "hiredate", "type": "string"},
{"name": "sal", "type": "double"}
],
"fileType": "text",
"writeMode": "append",
"fieldDelimiter": "\t"
}
}
}
]
}
}
说明 hdfs上的路径必须提前创建好
hdfs dfs -mkdir -p /datax/emp
7) 将mysql的数据导入到hive中(重要)
第一步:创建mysql的表 base_area
需要使用base_area.sql
第二步:在hive中创建一个ods_01_base_area
create external table if not exists ods_01_base_area (
id int COMMENT 'id标识',
area_code string COMMENT '省份编码',
province_name string COMMENT '省份名称',
iso string COMMENT 'ISO编码'
)row format delimited fields terminated by ','
stored as TextFile
location '/data/nshop/ods/ods_01_base_area/';
从mysql导入到hive中(其实就是导入到hdfs)
编写对应的Job的json文件:
read 方 是mysqlreader
write 方 是 hive (没有找到,找到了hdfswriter)
在 job文件夹,创建一个 mysql2hive01.json
{
"job": {
"setting": {
"speed": {
"channel": 3
},
"errorLimit": {
"record": 0,
"percentage": 0.02
}
},
"content": [
{
"reader": {
"name": "mysqlreader",
"parameter": {
"writeMode": "insert",
"username": "root",
"password": "123456",
"column": [
"id",
"area_code",
"province_name",
"iso"
],
"splitPk": "id",
"connection": [
{
"table": [
"base_area"
],
"jdbcUrl": [
"jdbc:mysql://bigdata01:3306/sqoop"
]
}
]
}
},
"writer": {
"name": "hdfswriter",
"parameter": {
"defaultFS": "hdfs://bigdata01:9820",
"fileType": "text",
"path": "/data/nshop/ods/ods_01_base_area/",
"fileName": "base_area_txt",
"column": [
{
"name": "id",
"type": "int"
},
{
"name": "area_code",
"type": "string"
},
{
"name": "province_name",
"type": "string"
},
{
"name": "iso",
"type": "string"
}
],
"writeMode": "append",
"fieldDelimiter": ","
}
}
}
]
}
}
8、datax如何做增量导入
sqoop增量导入有两种方案:
1、使用where语句 2、使用last-value 和 job任务一起使用,让job记住last-value
datax只有一种方案:使用where语句
举例:
如果json中有变量,需要传递值,在运行的时候,使用-D 传递即可
datax.py job/append.json -p "-Dstart_time=2021-01-01 -Dend_time=2021-01-03"
第二种还是使用where条件,只是这个时候的where条件是在SQL语句中
9、关于datax的调优
在datax中有两种配置文件,一种全局的,一种局部的。
全局的是 conf/core.json
也可以通过 record 和 byte 进行限速,这个值是每秒的条数和字节大小。
这个地方可以调整channel的各项参数,并发度默认是5个。
局部的配置文件,就是自己写的 xxxx.json
参数调优:
1、调整channel的数量,扩大并发度
2、调整jvm堆的大小,调整方案可以使用局部调整
python datax.py --jvm="-Xms3G -Xmx3G" ../job/test.json
一般这个任务比较大,报OOM异常了,或者GC次数特别的情况下,就可以指定堆大小。
指定的时候为什么初识容量大小和最大容量是一样的呢?
因为从初识容量到最大容量,需要不断的尝试,这个也比较耗时,所以一步到位即可。
关于并行度的说明
二、DataX高级部分
1、数据从hive导出到mysql
重要:一般都是将hive中分析的结果,存入到hive的一个表中,web端想展示,必须将hive中的数据导出到mysql或者其他关系型数据库中。
数据准备:
查看hive中是否有数据:
在mysql中创建一个表,用于存放数据。
目标:从par3中导出数据到mysql的user表。
在咱们的datax中没hiveReader,但是有hdfsreader,所以本质上就是hdfs导出到mysql
{
"job": {
"setting": {
"speed": {
"channel": 3
}
},
"content": [
{
"reader": {
"name": "hdfsreader",
"parameter": {
"path": "/user/hive/warehouse/yhdb.db/par3/*",
"defaultFS": "hdfs://bigdata01:9820",
"column": [
{
"index": 0,
"type": "long"
},
{
"index": 1,
"type": "long"
}
],
"fileType": "text",
"encoding": "UTF-8",
"fieldDelimiter": ","
}
},
"writer": {
"name": "mysqlwriter",
"parameter": {
"writeMode": "insert",
"username": "root",
"password": "123456",
"column": [
"id",
"age"
],
"connection": [
{
"jdbcUrl": "jdbc:mysql://bigdata01:3306/sqoop",
"table": [
"user"
]
}
]
}
}
}
]
}
}
结果展示:
2、DataX Web -- 图形化的DataX界面而已
1)介绍
github地址:https://github.com/WeiYe-Jing/datax-web
2) 安装
1、上传
2、解压
tar -zxvf datax-web-2.1.2.tar.gz -C /opt/installs/
3、安装
cd /opt/installs/datax-web-2.1.2/bin
执行安装程序
./install.sh
3)修改配置文件
vi /opt/installs/datax-web-2.1.2/modules/datax-executor/bin/env.properties
修改此处:
PYTHON_PATH=/opt/installs/datax/bin/datax.py
4)启动和关闭
bin路径下,有一个 start-all.sh 启动
stop-all.sh 关闭
不要配置环境变量
/opt/installs/datax-web-2.1.2/bin
运行的时候 ./start-all.sh
5) 浏览
在上一步启动dataxweb之后,通过浏览器可以进行dataxweb的访问,具体地址如下:
http://192.168.52.10:9527/index.html
进入网页之后,要求输入登录的用户名与密码,使用默认的即可:
用户名:admin
密码:123456
6)查看jps
7) 使用
第一步:创建一个项目
第二步:添加数据源
首先添加mysql数据源:
添加hive的数据源:
启动hive的远程连接:
hiveserver2
通过beeline测试连接:
[root@hadoop10 ~]# beeline
Beeline version 3.1.2 by Apache Hive
beeline> !connect jdbc:hive2://hadoop10:10000
Connecting to jdbc:hive2://hadoop10:10000
Enter username for jdbc:hive2://hadoop10:10000:
Enter password for jdbc:hive2://hadoop10:10000:
Connected to: Apache Hive (version 3.1.2)
Driver: Hive JDBC (version 3.1.2)
Transaction isolation: TRANSACTION_REPEATABLE_READ
0: jdbc:hive2://hadoop10:10000> show databases;
INFO : Compiling command(queryId=root_20230625195657_077b4fad-4d99-4574-ba7e-4fbe524ae63a): show databases
INFO : Concurrency mode is disabled, not creating a lock manager
INFO : Semantic Analysis Completed (retrial = false)
INFO : Returning Hive schema: Schema(fieldSchemas:[FieldSchema(name:database_name, type:string, comment:from deserializer)], properties:null)
INFO : Completed compiling command(queryId=root_20230625195657_077b4fad-4d99-4574-ba7e-4fbe524ae63a); Time taken: 1.446 seconds
INFO : Concurrency mode is disabled, not creating a lock manager
INFO : Executing command(queryId=root_20230625195657_077b4fad-4d99-4574-ba7e-4fbe524ae63a): show databases
INFO : Starting task [Stage-0:DDL] in serial mode
INFO : Completed executing command(queryId=root_20230625195657_077b4fad-4d99-4574-ba7e-4fbe524ae63a); Time taken: 0.052 seconds
INFO : OK
INFO : Concurrency mode is disabled, not creating a lock manager
+----------------+
| database_name |
+----------------+
| default |
| test_hive |
| workspaces |
| yhdb |
+----------------+
4 rows selected (2.199 seconds)
连接正常再进行配置:
添加datx模板
名词解释:
- 执行器:目前只有datax可选
- 路由策略:用于集群化部署后,任务的分配,默认随机即可。
- 阻塞处理:在调度出现积压时(同时启动大量的数据处理任务)使用的策略:
- 单机串行:调度请求进入单机执行器后,调度请求进入FIFO队列并以串行方式运行;
- 丢弃后续调度:调度请求进入单机执行器后,发现执行器存在运行的调度任务,本次请求将会被丢弃并标记为失败;
- 覆盖之前调度:调度请求进入单机执行器后,发现执行器存在运行的调度任务,将会终止运行中的调度任务并清空队列,然后运行本地调度任务;
`建议使用单机串行与丢弃后续调度`
- 任务类型:目前只有DataX选项可以选择
- Cron:调度定时执行器,通过该配置可以完成定时、定周期启动
编写任务(以hive数据导出到mysql为例)
配置hdfsreader
配置mysqlwriter:
配置字段映射:
查看json:
记得点击【下一步】,否则任务不创建。
查看任务并执行:
查看运行结果和日志:
编辑任务: