# 使用canal同步mysql数据
# 场景:
有两个独立的MySql数据库A和B
数据库A中有个表名为news,该表三个字段:
字段 | type |
---|---|
id | INT |
title | VARCHAR |
data | LONGTEXT |
数据库B中有两个表,news1 和 news 2, 如下
news 1
字段 | type |
---|---|
id | INT |
title | VARCHAR |
news 2
字段 | type |
---|---|
news_id | INT |
data | LONGTEXT |
如果要同步数据库A的news到数据库B的new1和new2,传统的同步方式满足不了
# 实现思路
利用canal获取数据库A中news的变化数据(增,删,改)
利用canal_mysql_nosql_sync将变化的数据存入到redis队列 (https://github.com/liukelin/canal_mysql_nosql_sync)
起一个守护脚本一直消费该redis,将变化的数据写入到数据库B
整个过程如下:
数据库A -> canal_server -> canal_client / canal_mysql_nosql_sync -> redis -> 脚本处理 -> 数据库B
# 实施步骤
# 一.配置canal
**1.**确定服务器上有java环境,如果没有需安装下java
# java -version
java version "1.8.0_121"
**2.**获取canal包
访问https://github.com/alibaba/canal/releases,下载相应的版本
本次以1.0.24为例
wget https://github.com/alibaba/canal/releases/download/canal-1.0.24/canal.deployer-1.0.24.tar.gz
**3.**解压并配置
详细的配置参数可参考https://github.com/alibaba/canal/wiki/AdminGuide
将安装包解压后,默认有如下文件夹
# ls
bin conf lib logs
canal的主配置文件为/conf/canal.properties,这里可以配置监听的端口等
canal.id= 2
canal.ip=
canal.port= 11111
canal.zkServers=
编辑example的配置文件
vim ./conf/example/instance.properties
配置好数据库的相关信息
canal.instance.master.address = 127.0.0.1:3306
# username/password
canal.instance.dbUsername = root
canal.instance.dbPassword = root123456
canal.instance.defaultDatabaseName = news
canal.instance.connectionCharset = UTF-8
配置下正则表达式,用于指定要同步的表
# table regex
canal.instance.filter.regex = .*
# table black regex
canal.instance.filter.black.regex = platform_news\\..*
这里注意下
canal.instance.filter.regex的白名单配置是无效的,不用配置
如果要指定库和表,可以把不同步的库和表写到canal.instance.filter.black.regex配置中,黑名单的配置有效.
比如我不要同步test这个数据库,则可以这样写
canal.instance.filter.black.regex = test\\..*
配置完成后,启动服务
sh bin/startup.sh
启动完成后,会看到有个端口号为11111的进程
# 二.部署canal_mysql_nosql_sync
**1.**获取canal_mysql_nosql_sync
git clone https://github.com/liukelin/canal_mysql_nosql_sync
**2.**配置
cd canal_mysql_nosql_sync/canal-client/conf
vim canal.properties
配置好对应参数即可,注意下canal.binlog.dir路径
**3.**启动
sh ./canal_mysql_nosql_sync/canal-client/start_canal_client.sh
正常启动后,去项目A的表中改个数据,可立即看到变化
# 三.通过脚本获取redis数据,并写入到数据库B中
1. 连接redis,获取redis中变化的数据,任意语言都可以,只要能使用redis和mysql即可。
以PHP为例:
$predis = new \Predis\Client('tcp://172.16.93.239:2889');
$predis->connect();
$msg = $predis->lpop('canal_binlog_data');
$predis->disconnect();
获取的数据结构如下:
eventType :操作类型(UPDATE/INSERT/DELETE)
db: 涉及库
table: 涉及表
before:变更前数据
after: 变更后数据
time: 操作时间
**2.**提取出变化的数据,根据eventType,将数据更新到数据库B中
# 故障排除
启动canal时,提示Could not find first log file name in binary log index file
需删除example下的meta.dat文件,再重新启动
redis中没数据
1.确保数据库是ROW模式
2.数据库的用户需要有slave权限
3.看下canal的logs/example/meta.log文件是否有更新
4.看下canal_client中canal.binlog.dir路径下的文件是否有更新