起因
事情是这样的,服务商有一批数据,现在的数据量大致为 2 千万条(单表),每天都会增加数据(增加多少暂不知道),但是呢给我们提供的查询不是一张数据表而是一张视图,我们再根据这个数据对外提供一个查询服务。因为是视图查询的时候就比较慢,我们也没有权限进行表的优化,所以就需要将数据同步到我们本地数据库,在本地进行数据表的优化(加索引等等的),但是数据量是 2 千万多,就需要一个工具来把远端数据同步到本地,然后在 github 上发现了 Datax
,就按照文档
依赖关系
- Linux
- JDK(1.8 以上,推荐 1.8)
- Python(2或3都可以)
jdk 安装
解压重命名
解压重名为 java1.8
并移动到 /usr/local
目录下 /usr/local/java1.8
运行环境配置
vim ~/.bashrc
# 写入一下内容
export JAVA_HOME=/usr/local/java1.8
export JRE_HOME=${JAVA_HOME}/jre
export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib
export PATH=${JAVA_HOME}/bin:$PATH
# 执行 source
source ~/.bashrc
# 查看版本
java -version
java version "1.8.0_181"
Java(TM) SE Runtime Environment (build 1.8.0_181-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.181-b13, mixed mode)
Python 安装
Python 在 Ubuntu 系统上已经默认安装了,可以使用命令 python -V
或 python3 -V
查看当前版本。
可以使用命令 apt install python3
安装 Python3。也可以自己使用编译的方式安装。
datax 安装
可以直接下载工具包,不需要再编译安装,可以直接使用。
验证是否安装成功
输入
python3 /usr/local/datax/bin/datax.py /usr/local/datax/job/job.json
输出
2022-11-21 14:05:28.828 [job-0] INFO JobContainer - PerfTrace not enable!
2022-11-21 14:05:28.829 [job-0] INFO StandAloneJobContainerCommunicator - Total 100000 records, 2600000 bytes | Speed 261.91KB/s, 20000 records/s | Error 0 records, 0 bytes | All Task WaitWriterTime 0.070s | All Task WaitReaderTime 0.068s | Percentage 100.00%
2022-11-21 14:05:28.829 [job-0] INFO JobContainer -
任务启动时刻 : 2022-11-21 14:05:18
任务结束时刻 : 2022-11-21 14:05:28
任务总计耗时 : 10s
任务平均流量 : 253.91KB/s
记录写入速度 : 10000rec/s
读出记录总数 : 100000
读写失败总数 : 0
job.json 文件解析
{
"job": {
"content": [
{
"reader": {
"name": "mysqlreader",# 读端,这个 name 不能 streamreader 会报错的
"parameter": {
"username": "",# 用户
"password": "",# 密码
"connection": [
{
"jdbcUrl": [],# 连接信息,貌似可以连接多个数据库,没有进行测试
"table": []# 数据表
}
],
"column": ["*"],# 需要同步的列 (* 表示所有的列)
"where": " id >= 500000 and id < 500100 "# 描述筛选条件,多个表时不适用
}
},
"writer": {
"name": "mysqlwriter",# 写端
"parameter": {
"username": "",# 账号
"password": "", # 密码
"writeMode": "insert",# 操作类型,可选:【insert | replace | update】
"connection": [
{
"jdbcUrl": "", # 连接信息,这个连接信息最好是这样写,否则会出错
"table": []# 数据表
}
],
"column": ["*"],# 需要同步的列,要和 reader 中的字段一致
"preSql": [],# 同步前操作,是 sql 语句
"postSql": [],# 同后前操作,是 sql 语句
"session": [] # 设置 session,是 sql 语句
}
}
}
],
"setting": {
"speed": {
"channel": 1 # 指定并发数,目前不知道什么作用,有知道的可以告知下
}
}
}
}
job.json 示例
{
"job": {
"content": [
{
"reader": {
"name": "mysqlreader",
"parameter": {
"username": "datax2",
"password": "datax2",
"connection": [
{
"jdbcUrl": [
"jdbc:mysql://192.168.0.174:3306/datax2?useUnicode=true&characterEncoding=utf8"
],
"table": [
"user"
]
}
],
"column": [
"*"
]
}
},
"writer": {
"name": "mysqlwriter",
"parameter": {
"username": "datax",
"password": "datax",
"writeMode": "insert",
"connection": [
{
"jdbcUrl": "jdbc:mysql://192.168.0.174:3306/datax?useUnicode=true&characterEncoding=utf8",
"table": [
"user"
]
}
],
"column": [
"*"
]
}
}
}
],
"setting": {
"speed": {
"channel": 2
}
}
}
}
增量同步建议
对于增量同步数据,建议每张表有单独的 job.json
配置文件,记录上次同步的最大的 ID,在 reader.where
进行判断 id > last_max_sync_id
。
where 示例,适用于单表的情况:
{
"parameter": {
"where": " id > last_max_sync_id "
}
}
针对失败数据的处理方式
Datax 在同步过程中,失败的数据会写入到 /datax/log/
文件中,并认定为 脏数据
,可以从日志 脏数据
中抽离出失败数据的内容组成 sql
语句,或者找出 主键ID
再去查询同步。
失败数据日志内容如下:
2022-11-22 09:52:50.696 [0-0-0-writer] ERROR StdoutPluginCollector - 脏数据:
{
"exception":"Incorrect integer value: 'inno' for column 'id' at row 1",
"record":[
{
"byteSize":8,
"index":0,
"rawData":"inno",
"type":"STRING"
},
{
"byteSize":32,
"index":1,
"rawData":"9ddfaac20670c9sda5s1d5a587fc40f104",
"type":"STRING"
},
{
"byteSize":14,
"index":2,
"rawData":"手持设备调用",
"type":"STRING"
},
{
"byteSize":4,
"index":3,
"rawData":9243,
"type":"LONG"
},
{
"byteSize":3,
"index":4,
"rawData":441,
"type":"LONG"
},
{
"byteSize":5,
"index":5,
"rawData":"admin",
"type":"STRING"
},
{
"byteSize":32,
"index":6,
"rawData":"49b1d2b5ds1d5a1s1d5a7414890ad2",
"type":"STRING"
},
{
"byteSize":1,
"index":7,
"rawData":1,
"type":"LONG"
},
{
"byteSize":61,
"index":8,
"rawData":"[[\"app_id\", \"=\", \"yuan\"], [\"id_name\", \"like\", \"%天华%\"]]",
"type":"STRING"
},
{
"byteSize":127,
"index":9,
"rawData":"SELECT COUNT(*) AS count FROM `device_request_history` WHERE `app_id` = 'yuan' AND `id_name` LIKE '%天华%' LIMIT 1",
"type":"STRING"
},
{
"byteSize":8,
"index":10,
"rawData":1668575331000,
"type":"DATE"
}
],
"type":"writer"
}
关于读取视图数据到本地的方式
视图读取问题
Datax 可以从 reader 中读取视图数据,但是无法读取 writer 中的视图数据结构元信息,为了确保数据能够同步成功,需要先校验数据表结构一致性, Datax 需要判断写入目的表的数据结构是否和读取源数据表的结构一致。
针对视图读取问题处理方案
可以在目的数据库中新建数据表,新建数据表的结构和源数据视图的结构一致,这样 Datax 在校验数据表结构和视图结构一致性时就可以通过。
20000000 条数据实测案例
同步方案
为了方便测试,将 2 千万条数据按照 10 次进行同步(按照自己的实际情况来,可以一次性进行同步)。
方案划分
id > 0 and id <= 2000000
id > 2000000 and id <= 4000000
id > 4000000 and id <= 6000000
id > 6000000 and id <= 8000000
id > 8000000 and id <= 10000000
id > 10000000 and id <= 12000000
id > 12000000 and id <= 14000000
id > 14000000 and id <= 16000000
id > 16000000 and id <= 18000000
id > 18000000 and id <= 20000000
id > 0 and id <= 2000000
这个 id 之间数据有断层。缺少 144 条数据。
2022-11-23 14:58:06.418 [job-0] INFO JobContainer -
任务启动时刻 : 2022-11-23 14:53:34
任务结束时刻 : 2022-11-23 14:58:06
任务总计耗时 : 271s
任务平均流量 : 1.28MB/s
记录写入速度 : 7406rec/s
读出记录总数 : 1999856
读写失败总数 : 0
id > 2000000 and id <= 4000000
2022-11-23 15:03:39.879 [job-0] INFO JobContainer -
任务启动时刻 : 2022-11-23 14:59:08
任务结束时刻 : 2022-11-23 15:03:39
任务总计耗时 : 271s
任务平均流量 : 1.28MB/s
记录写入速度 : 7407rec/s
读出记录总数 : 2000000
读写失败总数 : 0
id > 4000000 and id <= 6000000
这个 id 之间数据有断层。缺少 13 条数据。
2022-11-23 15:09:38.418 [job-0] INFO JobContainer -
任务启动时刻 : 2022-11-23 15:04:56
任务结束时刻 : 2022-11-23 15:09:38
任务总计耗时 : 282s
任务平均流量 : 1.24MB/s
记录写入速度 : 7142rec/s
读出记录总数 : 1999987
读写失败总数 : 0
id > 6000000 and id <= 8000000
2022-11-23 15:17:05.814 [job-0] INFO JobContainer -
任务启动时刻 : 2022-11-23 15:12:14
任务结束时刻 : 2022-11-23 15:17:05
任务总计耗时 : 291s
任务平均流量 : 1.19MB/s
记录写入速度 : 6896rec/s
读出记录总数 : 2000000
读写失败总数 : 0
id > 8000000 and id <= 10000000
2022-11-23 15:22:41.729 [job-0] INFO JobContainer -
任务启动时刻 : 2022-11-23 15:17:30
任务结束时刻 : 2022-11-23 15:22:41
任务总计耗时 : 311s
任务平均流量 : 1.12MB/s
记录写入速度 : 6451rec/s
读出记录总数 : 2000000
读写失败总数 : 0
id > 10000000 and id <= 12000000
这个 id 之间数据有断层。缺少 462 条数据。
2022-11-23 15:29:08.710 [job-0] INFO JobContainer -
任务启动时刻 : 2022-11-23 15:23:56
任务结束时刻 : 2022-11-23 15:29:08
任务总计耗时 : 311s
任务平均流量 : 1.12MB/s
记录写入速度 : 6450rec/s
读出记录总数 : 1999538
读写失败总数 : 0
id > 12000000 and id <= 14000000
2022-11-23 15:34:23.699 [job-0] INFO JobContainer -
任务启动时刻 : 2022-11-23 15:29:42
任务结束时刻 : 2022-11-23 15:34:23
任务总计耗时 : 281s
任务平均流量 : 1.24MB/s
记录写入速度 : 7142rec/s
读出记录总数 : 2000000
读写失败总数 : 0
id > 14000000 and id <= 16000000
2022-11-23 15:39:16.394 [job-0] INFO JobContainer -
任务启动时刻 : 2022-11-23 15:34:54
任务结束时刻 : 2022-11-23 15:39:16
任务总计耗时 : 261s
任务平均流量 : 1.33MB/s
记录写入速度 : 7692rec/s
读出记录总数 : 2000000
读写失败总数 : 0
id > 16000000 and id <= 18000000
2022-11-23 15:45:19.011 [job-0] INFO JobContainer -
任务启动时刻 : 2022-11-23 15:40:07
任务结束时刻 : 2022-11-23 15:45:19
任务总计耗时 : 311s
任务平均流量 : 1.12MB/s
记录写入速度 : 6451rec/s
读出记录总数 : 2000000
读写失败总数 : 0
id > 18000000 and id <= 20000000
2022-11-23 15:51:07.983 [job-0] INFO JobContainer -
任务启动时刻 : 2022-11-23 15:45:56
任务结束时刻 : 2022-11-23 15:51:07
任务总计耗时 : 311s
任务平均流量 : 1.09MB/s
记录写入速度 : 6276rec/s
读出记录总数 : 1945569
读写失败总数 : 0