数据同步之DataX
目前业务中需要进行数据同步, 考虑使用datax数据同步方式替换掉现有的同步方式
业务场景:
即将业务中每天生成的日志表中的数据部分字段同步到自己的库中,进行后台数据的查询
起因:
之前“大神”写的逻辑中使用每三分钟更新一次的策略进行数据同步,在redis中进行计数和打标记的方式进行数据的增量同步,但是最近发现经常数据会发生丢失的问题,于是进行问题的修复
解决:
了解到运营对于这些数据的查询实时性并没有这么高,今天查询昨天的数据这种场景比较多,于是打算使用datax凌晨同步昨天的数据到本地即可,节省资源,减少调用业务的数据库频次
DataX: https://github.com/alibaba/DataX
基于java的同步开源项目,基本使用起来较为容易,简单配置即可,完成之后 3万多的数据 只需要不到10秒中就完成了数据同步工作
数据库-mysql相关的reader和writer相关配置参考:
- https://github.com/alibaba/DataX/blob/master/mysqlwriter/doc/mysqlwriter.md
- https://github.com/alibaba/DataX/blob/master/mysqlreader/doc/mysqlreader.md
当然他还支持很多的数据库
安装)
1)下载源码包
wget http://datax-opensource.oss-cn-hangzhou.aliyuncs.com/datax.tar.gz
基于java, 保证已经安装了Java,推荐8版本,安装方式,可见本博客,
cd /usr/local/src/ wget https://repo.huaweicloud.com/java/jdk/8u201-b09/jdk-8u201-linux-x64.tar.gz tar -zxvf jdk-8u201-linux-x64.tar.gz mv jdk1.8.0_201 /usr/local/ vim /etc/profile export JAVA_HOME=/usr/local/jdk1.8.0_201 export PATH=${JAVA_HOME}/bin:${PATH} source /etc/profile java -version 查看版本
2)解压datax
tar -zxvf datax.tar.gz 执行一个demo python datax/bin/datax.py datax/job/job.json 注意:这里使用的是python2 版本
2)示例
1.MySQL同步到MySQL
{ "job": { "setting": { "speed": { "byte":10485760 }, "errorLimit": { "record": 0, "percentage": 0.02 } }, "content": [ { "reader": { "name": "mysqlreader", "parameter": { "username": "root", "password": "123456", "connection": [ { "querySql": [ "select player_id,UNIX_TIMESTAMP(create_time) AS create_time from t_player_log__20210422" ], "jdbcUrl": [ "jdbc:mysql://127.0.0.1:3306/demo" ] } ] } }, "writer": { "name": "mysqlwriter", "parameter": { "writeMode": "insert", "username": "root", "password":"123456", "column": [ "player_id", "create_time" ], "session": [ "set names utf8mb4" ], "connection": [ { "encoding": "UTF-8", "jdbcUrl": "jdbc:mysql://127.0.0.1:3306/test", "table": [ "tt_player_log" ] } ] } } } ] } }
还支持传入参数的方式动态的配置(python bin/datax.py 支持的参数:-p),例如:
{ "job": { "setting": { "speed": { "byte":10485760 }, "errorLimit": { "record": 0, "percentage": 0.02 } }, "content": [ { "reader": { "name": "mysqlreader", "parameter": { "username": "${username}", "password": "${password}", "connection": [ { "querySql": [ "select player_id,UNIX_TIMESTAMP(create_time) AS create_time from t_player_log__${dateNum}" ], "jdbcUrl": [ "jdbc:mysql://${ip}:${port}/${db}" ] } ] } }, "writer": { "name": "mysqlwriter", "parameter": { "writeMode": "insert", "username": "root", "password":"123456", "column": [ "player_id", "create_time" ], "session": [ "set names utf8mb4" ], "connection": [ { "encoding": "UTF-8", "jdbcUrl": "jdbc:mysql://127.0.0.1:3306/test", "table": [ "${table}" ] } ] } } } ] } }
同步命令:
/bin/python /opt/datax/bin/datax.py /opt/datax/job/game_job.json -p"-Dusername=xxxx -Dpassword=xxx -Dip=xx.xx.xx.xx -Dport=3306 -Ddb=xx -Dtable=xx -DdateNum=20210423"
注意:如果密码中有特殊字符,需要使用单引号将其引起来
相关的job任务会放到job目录下, 新建一个shell脚本放到script下, run_jobs.sh,将相关数据库连接配置到一个数据表中, 添加上定时任务即可
#!/bin/bash #说明: # 执行同步游戏库玩家日志表数据 day_num=`date -d "-1 day" +%Y%m%d` #day_num=`date +%Y%m%d` main(){ mysql -hxx.xx.xx -Pxx -uxx -pxx -N -e "select game_name,app_id,ip,port,username,password,db_name,player_log_table from t xx.tt_game_db where type=2 and status=1" | while read game_name app_id ip port username password db_name player_log_table do echo "当前游戏:$game_name[$app_id] 数据库信息:$username:$password@$ip:$port/$db_name 目标表:$player_log_table" #echo "-Dusername=$username -Dpassword=$password -Dip=$ip -Dport=$port -Ddb=$db_name -Dtable=$player_log_table -DdateNum=$day_num" /bin/python /opt/datax/bin/datax.py /opt/datax/job/game_job.json -p"-Dusername=$username -Dpassword=$password -Dip=$ip -Dport=$port -Ddb= $db_name -Dtable=$player_log_table -DdateNum=$day_num" done } main
2)MongoDB同步到MySQL
{ "job": { "setting": { "speed": { "channel": 2 } }, "content": [ { "reader": { "name": "mongodbreader", "parameter": { "address": ["127.0.0.1:27017"], "userName": "dataxUser1", "userPassword": "xxxxx", "dbName": "log_1", "collectionName": "20210101", "column": [ { "name": "uid", "type": "int" }, { "name": "match_id", "type": "string" } ], "query": { // 添加筛选条件 "func_name":"play", "play_type": { "$in": [2,3] } } } }, "writer": { "name": "mysqlwriter", "parameter": { "writeMode": "insert", "username": "gameUser", "password": "xxxxx", "column": [ "player_index", "table_id" ], "session": [ "set names utf8mb4" ], "connection": [ { "jdbcUrl": "jdbc:mysql://127.0.0.1:3306/game_log", "table": [ "game_record_log" ] } ] } } } ] } }
注意点: 这里的MongoDB的用户名和密码 要开一个这个库的所属人的权限
db.createUser({user:"dataxUser1",pwd:"xxxx",roles:[{role:"dbOwner", db:"log_1"}]})
后面为了通用, 需要将这里配置的MongoDB的信息和MySQL的信息都通过变量的方式传递进来
在script目录下添加shell执行脚本,例如:run_jobs_for_mongo2mysql.sh
#!/bin/bash ## 传入开始和结束时间将MongoDB(10十个库)中每个库指定日期范围内的数据同步到MySQL begin_date=$1 end_date=$2 begin_time=$begin_date mongo_user_prefix="dataxUser" mongo_pwd=xxxx mongo_db_name_prefix="log_" mongo_table_name_prefix="game_" mysql_user="mysqlUser" mysql_pwd="xxx" mysql_host="127.0.0.1" mysql_port=3306 mysql_db_name="game_log" mysql_table_name="game_record_log" main(){ for n in $(seq 1 10) do while [ "$begin_date" != "$end_date" ] do echo $begin_date mongo_user=$mongo_user_prefix$n mongo_db_name=$mongo_db_name_prefix$n mongo_table_name=$mongo_table_name_prefix$begin_date echo "-Dmongo_user=$mongo_user -Dmongo_pwd=$mongo_pwd -Dmongo_db_name=$mongo_db_name -Dmongo_table_name=$mongo_table_name -Dmysql_user=$mysql_user -Dmysql_pwd=$mysql_pwd -Dmysql_host=$mysql_host -Dmysql_port=$mysql_port -Dmysql_db_name=$mysql_db_name -Dmysql_table_name=$mysql_table_name" /bin/python /opt/data/datax/bin/datax.py /opt/data/datax/job/game_mongo2mysql_job.json -p"-Dmongo_user=$mongo_user -Dmongo_pwd=$mongo_pwd -Dmongo_db_name=$mongo_db_name -Dmongo_table_name=$mongo_table_name -Dmysql_user=$mysql_user -Dmysql_pwd='$mysql_pwd' -Dmysql_host=$mysql_host -Dmysql_port=$mysql_port -Dmysql_db_name=$mysql_db_name -Dmysql_table_name=$mysql_table_name" let begin_date=`date -d "-1 days ago ${begin_date}" +%Y%m%d` done begin_date=$begin_time echo $end_date done } main
常见问题:
1.如果数据表中有特殊表情的时候, 可能会出现字符错误的报错信息, 这个时候需要进行设置
"session": [ "set names utf8mb4" ],
更多同步工具:
- canal
- CloudCanal(https://www.clougence.com/)