有两个独立的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的news1和news2,传统的同步方式满足不了
利用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->rpop('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路径下的文件是否有更新