原文

1.1. 开启 MySQL 的 binlog 日志

  1. 修改 my.cnfmy.ini(windows), 添加配置项:
# binlog 日志存放路径
log-bin=D:\env\mysql-5.7.28-winx64\binlog
# 日志中记录每一行数据被修改的形式
binlog-format=ROW
# 当前机器的服务 ID, 如果为集群时不能重复
server_id=1
  1. 重启 mysql 服务后, 查看配置变量是否生效:
mysql> show variables like '%log_bin%';
+---------------------------------+----------------------+
| Variable_name                   | Value                |
+---------------------------------+----------------------+
| log_bin                         | ON                   |
| log_bin_basename                | D:\env\mysql-5       |
| log_bin_index                   | D:\env\mysql-5.index |
| log_bin_trust_function_creators | OFF                  |
| log_bin_use_v1_row_events       | OFF                  |
| sql_log_bin                     | ON                   |
+---------------------------------+----------------------+
6 rows in set, 1 warning (0.00 sec)
  1. 配置 mysql 数据库的 canal 用户

mysql -uroot -p 登录 mysql, 创建并授权用户 canal;

CREATE USER canal IDENTIFIED BY 'canal';
GRANT SELECT, REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'canal'@'%';
FLUSH PRIVILEGES;

1.2. 配置 rabbitmq Exchanges 和 Queues

  1. 新建 Queue

mysql-canal-rabbitmq 安装部署教程-LMLPHP

  1. 新建 Exchange

mysql-canal-rabbitmq 安装部署教程-LMLPHP

  1. 设置 Queue 里的 Bindings, 填写 Exchange 名称, 以及路由 Routing key;

mysql-canal-rabbitmq 安装部署教程-LMLPHP

1.3. 安装单机 canal

1.3.1. 下载安装

下载 并解压缩;

sudo wget https://github.com/alibaba/canal/releases/download/canal-1.1.4/canal.deployer-1.1.4.tar.gz
sudo tar -zxvf canal.deployer-1.1.4.tar.gz

最新版本 1.1.5的安装

sudo wget https://github.com/alibaba/canal/releases/download/canal-1.1.5-alpha-1/canal.deployer-1.1.5-SNAPSHOT.tar.gz
sudo tar -zxvf canal.deployer-1.1.5-SNAPSHOT.tar.gz

1.3.2. 配置文件

1.3.2.1. 节点配置文件 canal.properties

# tcp bind ip, 当前节点的 IP 地址
canal.ip = 192.168.2.108
# register ip to zookeeper, 注册到 ZK 的 IP 地址, 如下图1.
canal.register.ip = 192.168.2.108

canal.zkServers = zk集群

# tcp, kafka, RocketMQ, 最新版本 1.1.5 可以直接连接 rabbitmq
canal.serverMode = rabbitmq

# destinations, 当前 server 上部署的 instance 列表, 对应各个实例文件夹(../conf/<instance_name>)名称
canal.destinations = example2

# 设置 mq 服务器地址, 此处为 rabbitmq 的服务器地址
# !! 此处下载后默认的配置是有配置IP:端口的
# rabbitmq 此处则不需要配置端口
canal.mq.servers = 192.168.208.100

# 一下几项均为 1.1.5 新版本新增支持 rabbitmq 的配置
canal.mq.vhost=/
canal.mq.exchange=example2-ex # 指定 rabbitmq 上的 exchange 名称, "新建 `Exchange`" 步骤新建的名称
canal.mq.username=admin # 连接 rabbitmq 的用户名
canal.mq.password=**** # 连接 rabbitmq 的密码
canal.mq.aliyunuid=

mysql-canal-rabbitmq 安装部署教程-LMLPHP

1.3.2.2. 实例配置文件 instance.properties

# position info, 数据库的连接信息
canal.instance.master.address=192.168.2.108:3306
# 以下两个配置, 需要在上面配置的 address 的数据库中执行 `SHOW MASTER STATUS` 获取的 `File` 和 `Position` 两个字段值
canal.instance.master.journal.name=mysql-5.7
canal.instance.master.position=674996

# table meta tsdb info, 禁用 tsdb 记录 table meta 的时间序列版本
canal.instance.tsdb.enable=false

# username/password, 实例连接数据的用户名和密码
canal.instance.dbUsername=canal
canal.instance.dbPassword=canal

# table regex, 正则匹配需要监听的数据库表
canal.instance.filter.regex=ysb\\.useropcosttimes_prod

# mq config, 指定 rabbitmq 设置绑定的路由, 详见"配置rabbitmq"步骤里的第三步配置的`Routing key`
canal.mq.topic=example2-routingkey

1.3.3. 启动 canal 服务

Linux 对应的启动脚本 ./bin/startup.sh, Windows 对应的启动脚本 ./bin/startup.bat; 以 Windows 为例:

λ .\startup.bat
start cmd :  java   -Xms128m -Xmx512m -XX:PermSize=128m  -Djava.awt.headless=true -Djava.net.preferIPv4Stack=true -Dapplication.codeset=UTF-8 -Dfile.encoding=UTF-8  -server -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=9099,server=y,suspend=n  -DappName=otter-canal -Dlogback.configurationFile="d:\env\green\canal-1.1.5\bin\\..\conf\logback.xml" -Dcanal.conf="d:\env\green\canal-1.1.5\bin\\..\conf\canal.properties" -classpath "d:\env\green\canal-1.1.5\bin\\..\conf\..\lib\*;d:\env\green\canal-1.1.5\bin\\..\conf" java   -Xms128m -Xmx512m -XX:PermSize=128m  -Djava.awt.headless=true -Djava.net.preferIPv4Stack=true -Dapplication.codeset=UTF-8 -Dfile.encoding=UTF-8  -server -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=9099,server=y,suspend=n  -DappName=otter-canal -Dlogback.configurationFile="d:\env\green\canal-1.1.5\bin\\..\conf\logback.xml" -Dcanal.conf="d:\env\green\canal-1.1.5\bin\\..\conf\canal.properties" -classpath "d:\env\green\canal-1.1.5\bin\\..\conf\..\lib\*;d:\env\green\canal-1.1.5\bin\\..\conf" com.alibaba.otter.canal.deployer.CanalLauncher
Java HotSpot(TM) Server VM warning: ignoring option PermSize=128m; support was removed in 8.0
Listening for transport dt_socket at address: 9099

最后手动修改数据库数据, 或者等待其他的修改, 再查看一下 rabbitmq 上的监控即可知道流程是否走通了.

mysql-canal-rabbitmq 安装部署教程-LMLPHP

1.4. 安装集群 canal

1.4.1. 安装 canal-admin

1.4.1.1. 下载安装

下载并解压缩

sudo wget https://github.com/alibaba/canal/releases/download/canal-1.1.5-alpha-1/canal.admin-1.1.5-SNAPSHOT.tar.gz
sudo tar -zxvf canal.admin-1.1.5-SNAPSHOT.tar.gz

1.4.1.2. 配置文件

server:
  port: 8089
spring:
  jackson:
    date-format: yyyy-MM-dd HH:mm:ss
    time-zone: GMT+8

spring.datasource:
  address: 192.168.2.108:3306
  database: canal_manager
  username: canal
  password: canal
  driver-class-name: com.mysql.jdbc.Driver
  # 数据库连接字符串末尾需添加`serverTimezone=UTC`, 否则启动时会报时区异常;
  url: jdbc:mysql://${spring.datasource.address}/${spring.datasource.database}?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=UTC
  hikari:
    maximum-pool-size: 30
    minimum-idle: 1

canal:
  # 配置 canal-admin 的管理员账号和密码
  adminUser: admin
  adminPasswd: 123456

在管理canal-admin数据的数据库中执行该 sql 脚本, 初始化一些表;

1.4.1.3. 启动 canal-admin 服务

Linux 对应的启动脚本 ./bin/startup.sh, Windows 对应的启动脚本 ./bin/startup.bat; 以 Windows 为例:

λ .\startup.bat
start cmd :  java   -Xms128m -Xmx512m  -Djava.awt.headless=true -Djava.net.preferIPv4Stack=true -Dapplication.codeset=UTF-8 -Dfile.encoding=UTF-8  -DappName=canal-admin -classpath "D:\env\green\canal-1.1.5-admin\bin\\..\conf\..\lib\*;D:\env\green\canal-1.1.5-admin\bin\\..\conf" com.alibaba.otter.canal.admin.CanalAdminApplication
2020-04-13 20:01:39.495 [main] INFO  com.alibaba.otter.canal.admin.CanalAdminApplication - Starting CanalAdminApplication on Memento-PC with PID 50696 (D:\env\green\canal-1.1.5-admin\lib\canal-admin-server-1.1.5-SNAPSHOT.jar started by Memento in D:\env\green\canal-1.1.5-admin\bin)
2020-04-13 20:01:39.527 [main] INFO  com.alibaba.otter.canal.admin.CanalAdminApplication - No active profile set, falling back to default profiles: default
2020-04-13 20:01:39.566 [main] INFO  o.s.b.w.s.c.AnnotationConfigServletWebServerApplicationContext - Refreshing org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@13a5bf6: startup date [Mon Apr 13 20:01:39 CST 2020]; root of context hierarchy
2020-04-13 20:01:41.149 [main] INFO  o.s.boot.web.embedded.tomcat.TomcatWebServer - Tomcat initialized with port(s): 8089 (http)
2020-04-13 20:01:41.166 [main] INFO  org.apache.coyote.http11.Http11NioProtocol - Initializing ProtocolHandler ["http-nio-8089"]
2020-04-13 20:01:41.176 [main] INFO  org.apache.catalina.core.StandardService - Starting service [Tomcat]
2020-04-13 20:01:41.177 [main] INFO  org.apache.catalina.core.StandardEngine - Starting Servlet Engine: Apache Tomcat/8.5.29
...
2020-04-13 20:01:42.996 [main] INFO  org.apache.coyote.http11.Http11NioProtocol - Starting ProtocolHandler ["http-nio-8089"]
2020-04-13 20:01:43.007 [main] INFO  org.apache.tomcat.util.net.NioSelectorPool - Using a shared selector for servlet write/read
2020-04-13 20:01:43.019 [main] INFO  o.s.boot.web.embedded.tomcat.TomcatWebServer - Tomcat started on port(s): 8089 (http) with context path ''
2020-04-13 20:01:43.024 [main] INFO  com.alibaba.otter.canal.admin.CanalAdminApplication - Started CanalAdminApplication in 3.919 seconds (JVM running for 5.241)

1.4.1.4. 注意事项

canal-admin 连接数据库的账号, 必须有建表, 读写数据的权限, 如果还是采用上文中创建的 canal 账号, 需要另外扩展一下权限:

GRANT ALL PRIVILEGES ON *.* TO 'canal'@'%' ;

1.4.2. 添加单机 canal-server 节点

1.4.2.1. 启动 canal-server 节点服务

单机 canal-server 照常启动, 此时, canal-server 默认加载的 ../conf/canal.properties 里的配置信息, 可以从 ../bin/startup.bat[startup.sh] 脚本中获悉, 获取从执行的脚本命令提示里获悉;

1.4.2.2. 新建单机 server

canal-admin 中新建一个单机 server

mysql-canal-rabbitmq 安装部署教程-LMLPHP

server 会自动识别已启动的 canal-server 节点, 但是此时由 admin 接管后, 不会自动加载 ../conf/canal.properties 的配置文件, 点击最右侧的 操作-配置 查看, 该 server 加载的是默认的配置信息

mysql-canal-rabbitmq 安装部署教程-LMLPHP
mysql-canal-rabbitmq 安装部署教程-LMLPHP

需要手动将 1.3.2 中配置好的 ../conf/canal.properties 里的配置信息拷贝到该配置里进行覆盖!

1.4.2.3. 新建实例 instance

手动在 canal-admin 中新建一个 instance, 对应单机 canal-server 配置下的实例 example2; 同样, 需要手动将 ./conf/<实例名称>/instance.properies 配置文件手动拷贝到 admin 中

mysql-canal-rabbitmq 安装部署教程-LMLPHP

mysql-canal-rabbitmq 安装部署教程-LMLPHP

!!注意
在新建或启动 instance 实例时, 先删除实例文件夹下的 meta.dat 文件, 并更新 canal.instance.master.journal.name=..., canal.instance.master.position=... 两个配置项;

1.4.3. 添加集群 canal-server 节点

1.4.3.1. 新建集群

需要指定集群名称, 以及配置集群绑定的 zookeeper 集群地址;
mysql-canal-rabbitmq 安装部署教程-LMLPHP

新建成功后, 在最右侧的 操作-主配置 中配置集群的通用 server 配置信息

mysql-canal-rabbitmq 安装部署教程-LMLPHP

此处也可以将之前配置的 ../conf/canal.properties 配置直接拷贝过来, 稍微修改一下就可以用了

# canal admin config
canal.admin.manager = 192.168.2.108:8089

canal.instance.global.mode = manager

1.4.3.2. 新建 server

指定所属集群, 为 1.4.3.1 中设定的集群名称;
mysql-canal-rabbitmq 安装部署教程-LMLPHP

如果先前已经启动了 canal-server 节点服务, 则新建的 server 会自动识别为 启动 状态, 否则为 断开 状态;

mysql-canal-rabbitmq 安装部署教程-LMLPHP

这里有一点需要十分注意的地方

细心的人可能会发现, 除了 canal.properties 配置文件, 还有一个 canal_local.properties 的配置文件, 后者比前者的内容少了很多, 因为这个文件就是用于搭建 canal 集群时, 本地节点的配置文件, 而前者配置文件里的其他信息都是交由 canal-admin 集中配置管理的;

./bin/startup.bat[startup.sh] 启动脚本里, 默认是加载 canal.properties 配置文件, 即以单机形式启动的服务;

windows 在搭建 canal 集群时, 需要手动修改 startup.bat, 蓝色标注处是加载 %canal_conf% 变量的配置文件路径, 所以需要将红色框内的变量调整为:

@rem set canal_conf=...
set canal_conf=%conf_dir%\canal_local.properties

使启动时加载 canal_local.properties 的配置文件

mysql-canal-rabbitmq 安装部署教程-LMLPHP

1.4.3.3. 新建 instance

此处配置也可以基于单机 server 中的实例 1.4.2.3 配置进行调整使用;

# 2. position info, 指定 mysql 开始同步的 binlog 位置信息
canal.instance.master.address=192.168.0.25:63306
canal.instance.master.journal.name=mysql-bin.001349
canal.instance.master.position=198213313

# 3. username/password, 设置同步 mysql 的数据库用户名和密码
canal.instance.dbUsername=xxxx
canal.instance.dbPassword=xxx

# 4. table regex, 正则匹配需要同步的数据表
canal.instance.filter.regex=xxxx

# 5. mq config, 指定 mysql 上的路由绑定, 见 `1.2.3`
canal.mq.topic=example2-routingkey

保存后即可在 操作 中启动该实例

mysql-canal-rabbitmq 安装部署教程-LMLPHP

1.5. canal 配置说明

1.5.1. canal.properties

  1. canal.ip, 该节点 IP
  2. canal.register.ip, 注册到 zookeeper 上的 IP
  3. canal.zkServers, zk 集群
  4. 是否启用 tsdb, 开启 table meta 的时间序列版本记录功能
    // 5. canal.serverMode, 设置为 rabbitmq, 默认为 tcp
canal.instance.tsdb.enable = true
canal.instance.tsdb.dir = ${canal.file.data.dir:../conf}/${canal.instance.destination:}
canal.instance.tsdb.url = jdbc:h2:${canal.instance.tsdb.dir}/h2;CACHE_SIZE=1000;MODE=MYSQL;
canal.instance.tsdb.dbUsername = canal
canal.instance.tsdb.dbPassword = canal
  1. canal.destinations, 当前集群上部署的 instance 列表
  2. canal.mq.servers, 设置 Rabbitmq 集群地址, !! 此处不可以加上端口

1.5.2. instance.properties

  1. canal.instance.master.address, master 数据库地址
  2. canal.instance.master.journal.name, 在数据库中执行show master statusFile
  3. canal.instance.master.position, 在数据库中执行show master statusPosition
  4. canal.instance.tsdb.enable=false, 禁用 tsdb
  5. canal.instance.dbUsername, 实例数据库用户名
  6. canal.instance.dbPassword, 实例数据库密码
  7. canal.instance.filter.regex, 匹配需要同步的表
  8. canal.mq.topic, canal 注册 mq 的 topic 名称

1.5.3. properties 配置文件

properties 配置分为两部分

  1. canal.properties
canal.destinations # 当前 server 上部署的 instance 列表
canal.conf.dir # conf 目录所在路径
canal.auto.scan # 开启 instance 自动扫描
# 如果配置为 true, canal.conf.dir 目录下的 instance 配置变化会自动触发
# 1. instance 目录新增: 触发 instance 配置载入, lazy 为 true 时则自动启动;
# 2. instance 目录删除: 卸载对应 instance 配置, 如已启动则进行关闭;
# 3. instance.properties 文件变化: reload instance 配置, 如已启动则自动进行重启操作;
canal.auto.scan.interval # instance 自动扫描间隔时间, 单位 s
canal.instance.global.mode # 全局配置加载方式
canal.instance.global.lazy # 全局 lazy 模式
canal.instance.global.manager.address # 全局的 manager 配置方式的链接信息
canal.instance.global.spring.xml # 全局的 spring 配置方式的组件文件
canal.instance.example.mode
canal.instance.example.lazy
canal.instance.example.spring.xml
# instance 级别的配置定义, 如有配置, 会自动覆盖全局配置定义模式

canal.instance.tsdb.enable # 是否开启 table meta 的时间序列版本记录功能
canal.instance.tsdb.dir # 时间序列版本的本地存储路径, 默认为 instance 目录
canal.instance.tsdb.url # 时间序列版本的数据库连接地址, 默认为本地嵌入式数据库
canal.instance.tsdb.dbUsername # 时间序列版本的数据库连接账号
canal.instance.tsdb.dbPassword # 时间序列版本的数据库连接密码
  1. instance.properties
canal.id # 每个 canal server 实例的唯一标识
canal.ip # canal server 绑定的本地 IP 信息, 如果不配置, 默认选择一个本机 IP 进行启动服务
canal.port # canal server 提供 socket 服务的端口
canal.zkServers # canal server 连接 zookeeper 集群的连接地址, 例如: 10.20.144.22:2181,10.20.144.23:2181
canal.zookeeper.flush.period # canal 持久化数据到 zookeeper 上的更新频率, 单位 ms
canal.instance.memory.batch.mode # canal 内存 store 中数据缓存模式
# 1. ITEMSIZE: 根据 buffer.size 进行限制, 只限制记录的数量
# 2. MEMSIZE: 根据 buffer.size * buffer.memunit 的大小, 限制缓存记录的大小;
canal.instance.memory.buffer.size # canal 内存 store 中可缓存 buffer 记录数, 需要为 2 的指数
canal.instance.memory.buffer.memunit # 内存记录的单位大小, 默认为 1KB, 和 buffer.size 组合决定最终的内存使用大小
canal.instance.transactions.size # 最大事务完整解析的长度支持, 超过该长度后, 一个事务可能会被拆分成多次提交到 canal store 中, 无法保证事务的完整可见性
canal.instance.fallbackIntervalInSeconds # canal 发生 mysql 切换时, 在新的 mysql 库上查找 binlog 时需要往前查找的时间, 单位 s
# 说明: mysql 主备库可能存在解析延迟或者时钟不一致, 需要回退一段时间, 保证数据不丢
canal.instance.detecting.enable # 是否开启心跳检查
canal.instance.detecting.sql # 心跳检查 sql, insert into retl.xdual values(1,now()) on duplicate key update x=now()
canal.instance.detecting.interval.time # 心跳检查频率, 单位 s
canal.instance.detecting.retry.threshold # 心跳检查失败重试次数
canal.instance.detecting.heatbeatHaEnable # 心跳检查失败后, 是否开启 mysql 自动切换
# 说明: 比如心跳检查失败超过阈值后, 如果该配置为 true, canal 会自动连到 mysql 备库获取 binlog 数据
canal.instance.network.receiveBufferSize # 网络连接参数, SocketOptions.SO_RCVBUF
canal.instance.network.sendBufferSize # 网络连接参数, SocketOptions.SO_SNDBUF
canal.instance.network.soTimeout # 网络连接参数, SocketOptions.SO_TIMEOUT

1.5.4. canal.mq.dynamicTopic

mysql-canal-rabbitmq 安装部署教程-LMLPHP

1.6. 问题处理

  1. windows 下执行 startup.bat 启动 canal 时, 出现如下异常
Failed to instantiate [ch.qos.logback.classic.LoggerContext]
Reported exception:
ch.qos.logback.core.LogbackException: Unexpected filename extension of file [file:/D:/env/green/canal/conf/]. Should be either .groovy or .xml
        at ch.qos.logback.classic.util.ContextInitializer.configureByResource(ContextInitializer.java:79)
        at ch.qos.logback.classic.util.ContextInitializer.autoConfig(ContextInitializer.java:152)
        at org.slf4j.impl.StaticLoggerBinder.init(StaticLoggerBinder.java:85)
        at org.slf4j.impl.StaticLoggerBinder.<clinit>(StaticLoggerBinder.java:55)
        at org.slf4j.LoggerFactory.bind(LoggerFactory.java:141)
        at org.slf4j.LoggerFactory.performInitialization(LoggerFactory.java:120)
        at org.slf4j.LoggerFactory.getILoggerFactory(LoggerFactory.java:331)
        at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:283)
        at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:304)
        at com.alibaba.otter.canal.deployer.CanalLauncher.<clinit>(CanalLauncher.java:29)

解决方法:
startup.bat 里的一下这行代码注释打开
@rem set logback_configurationFile=%conf_dir%\logback.xml

注, 新版 1.1.5 不存在该问题, 1.1.5这个文件中的这一行是没有注释掉的.

  1. 1.1.5新版本 canal-admin 启动时出现如下异常:
2020-04-10 18:55:40.406 [main] ERROR com.zaxxer.hikari.pool.HikariPool - HikariPool-1 - Exception during pool initialization.
java.sql.SQLException: The server time zone value '�й���׼ʱ��' is unrecognized or represents more than one time zone. You must configure either the server or JDBC driver (via the serverTimezone configuration property) to use a more specifc time zone value if you want to utilize time zone support.

解决方法

spring.datasource.url 配置的 mysql 连接地址后面加上参数 &serverTimezone=UTC

  1. Instance 日志里出现异常 errno = 1236, sqlstate = HY000 errmsg = log event entry exceeded max_allowed_packet;
2020-04-13 13:06:09.507 [destination = example3 , address = /192.168.2.108:3306 , EventParser] ERROR com.alibaba.otter.canal.common.alarm.LogAlarmHandler - destination:example3[java.io.IOException: Received error packet: errno = 1236, sqlstate = HY000 errmsg = log event entry exceeded max_allowed_packet; Increase max_allowed_packet on master; the first event 'mysql-5.7' at 671745, the last event read from 'D:\env\mysql-5.7' at 673181, the last byte read from 'D:\env\mysql-5.7' at 673200.
	at com.alibaba.otter.canal.parse.inbound.mysql.dbsync.DirectLogFetcher.fetch(DirectLogFetcher.java:102)
	at com.alibaba.otter.canal.parse.inbound.mysql.MysqlConnection.dump(MysqlConnection.java:235)
	at com.alibaba.otter.canal.parse.inbound.AbstractEventParser$3.run(AbstractEventParser.java:265)
	at java.lang.Thread.run(Unknown Source)
]

解决方法

删除 canal/conf 下对应实例里的 meta.dat 文件, 让 canal-admin 自动再生成即可;

1.7. 参考资料

03-08 15:45