一、介绍
- 在许多项目都有从mysql-1同步数据到mysql-2、从mysql同步数据到postgres、ES、Redis等异构数据存储的场景中。
- 虽然mysql主从也支持,但是自由度不够高不能将两个库的数据处理后同步到一个库里。
- canal也支持从A表同步部分字段到异构的B表的情况。
工作原理
- MySQL master 将数据变更写入二进制日志( binary log, 其中记录叫做二进制日志事件binary log events,可以通过 show binlog events 进行查看)
- MySQL slave 将 master 的 binary log events 拷贝到它的中继日志(relay log)
- MySQL slave 重放 relay log 中事件,将数据变更反映它自己的数据
canal 工作原理
- canal 模拟 MySQL slave 的交互协议,伪装自己为 MySQL slave ,向 MySQL master 发送dump 协议
MySQL master 收到 dump 请求,开始推送 binary log 给 slave (即 canal ) - canal 解析 binary log 对象(原始为 byte 流)
- 当然Debezimu也是这个原理
二、安装配置详解
基于文件的配置方式官方文档中已有介绍(https://github.com/alibaba/canal/blob/master/client-adapter/README.md),本文主要介绍基于admin-ui上是如何配置的。
本文以1.1.5版本做详解
下载部署文件 canal
-
canal.deployer-1.1.5.tar.gz
用于采集mysql的binlog事件 -
canal.adapter-1.1.5.tar.gz
用户接收canal.deployer采集的事件数据,并将数据写入目标数据库中 -
canal.admin-1.1.5.tar.gz
canal-1.1.4版本发布的新功能,支持在web上配置canal信息,并支持服务的启动、停止、动态更新配置等。
mysql安装
一共需要三个mysql数据库
mysql-canal:存放canal的相关配置
mysql-src: 作为源数据库
mysql-dest: 作为目标数据库
1.安装canal配置需要的mysql-canal数据库
2.创建canal_manager库,导入表结构conf/canal_manager.sql
3.配置mysql-src的my.cnf
[mysqld]
log-bin=mysql-bin # 开启 binlog
binlog-format=ROW # 选择 ROW 模式
server_id=1 # 配置 MySQL replaction 需要定义,不要和 canal 的 slaveId 重复
4.安装mysql-src作为采集的数据库,创建t_user表(主库比从库多一个sex字段)
CREATE TABLE `t_user` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`username` varchar(255) NOT NULL,
`password` varchar(255) NOT NULL,
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`sex` varchar(5) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=utf8mb4;
5.安装mysql-dest作为同步的数据库,创建t_user表
CREATE TABLE `t_user` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`username` varchar(255) NOT NULL,
`password` varchar(255) NOT NULL,
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8mb4;
canal.admin安装
2.配置数据库连接
server:
port: 8089
spring:
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
spring.datasource:
address: 127.0.0.1:3306
database: canal_manager
username: canal
password: canal
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://${spring.datasource.address}/${spring.datasource.database}?useUnicode=true&characterEncoding=UTF-8&useSSL=false
hikari:
maximum-pool-size: 30
minimum-idle: 1
canal:
adminUser: admin
adminPasswd: admin
3.启动服务
./bin/startup.sh
canal.deployer安装
1.新增server(对应服务为canal.deployer)
2.配置server
先载入模板
修改关键配置项
# tcp, kafka, rocketMQ, rabbitMQ
canal.serverMode = rocketmq
# 定义instance配置名。多个逗号分隔instance1,instance2
canal.destinations = instance1
rocketmq.producer.group = canal
rocketmq.enable.message.trace = false
rocketmq.customized.trace.topic =
rocketmq.namespace =
rocketmq.namesrv.addr = 127.0.0.1:9876
rocketmq.retry.times.when.send.failed = 0
rocketmq.vip.channel.enabled = false
rocketmq.tag =
3.新建instance
载入模板
修改关键配置项
# position info
canal.instance.master.address=127.0.0.1:3316
canal.instance.master.journal.name=mysql-bin.000001
canal.instance.master.position=0
canal.instance.master.timestamp=1
canal.instance.master.gtid=
canal.instance.dbUsername=root
canal.instance.dbPassword=root
# mq config
canal.mq.topic=instance1
canal.mq.partition=0
4.配置canal.deployer本地向canal.admin注册信息
conf/canal.properties
# tcp bind ip
canal.ip =
canal.port = 11111 //canal.deployer端口号
canal.metrics.pull.port = 11112
# canal admin config
canal.admin.manager = 127.0.0.1:8089 //canal.admin地址
canal.admin.port = 11110
canal.admin.user = admin
canal.admin.passwd = admin
# admin auto register
canal.admin.register.auto = true
#canal.admin.register.cluster =
#canal.admin.register.name =
4.启动canal.deployer
./bin/startup.sh
canal.adapter安装
1.修改配置conf/application.yml
server:
port: 8081
spring:
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
default-property-inclusion: non_null
canal.conf:
mode: rocketmq #tcp kafka rocketMQ rabbitMQ
flatMessage: true
zookeeperHosts:
syncBatchSize: 1000
retries: 0
timeout:
accessKey:
secretKey:
consumerProperties:
# rocketMQ consumer
rocketmq.namespace:
rocketmq.namesrv.addr: 127.0.0.1:9876
rocketmq.batch.size: 1000
rocketmq.enable.message.trace: false
rocketmq.customized.trace.topic: RMQ_SYS_TRACE_TOPIC
rocketmq.access.channel:
rocketmq.subscribe.filter:
srcDataSources:
defaultDS:
# 源库
url: jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false&zeroDateTimeBehavior=convertToNull&serverTimezone=Asia/Shanghai
username: root
password: root
canalAdapters:
- instance: instance1 # canal instance Name or mq topic name
groups:
- groupId: g1
outerAdapters:
# 目标库
- name: rdb
key: instance1
properties:
jdbc.driverClassName: com.mysql.jdbc.Driver
jdbc.url: jdbc:mysql://127.0.0.1:3316/test?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false&zeroDateTimeBehavior=convertToNull&serverTimezone=Asia/Shanghai
jdbc.username: root
jdbc.password: root
2.配置表关系映射conf/rdb
例: t_user表
新建t_user.yml
dataSourceKey: defaultDS
destination: instance1
groupId: g1
outerAdapterKey: instance1
concurrent: true
dbMapping:
database: test
table: t_user
targetTable: t_user
targetPk:
id: id
# 源表和目标表字段一样时开启mapAll: true
# mapAll: true
targetColumns:
id: id
username: username
password: password
create_time: create_time
commitBatch: 3000 # 批量提交的大小
3.启动canal.adapter
./bin/startup.sh
测试
在源数据库中插入数据,目标库中也自动插入了数据。