版本
canal.deployer-1.1.4
简介
canal是阿里巴巴开源的一款用于MySQL数据库增量日志解析组件,提供增量数据订阅和消费功能。canal读音[kəˈnæl]
canal 工作原理
- canal 模拟 MySQL slave 的交互协议,伪装自己为 MySQL slave ,向 MySQL master 发送dump 协议
- MySQL master 收到 dump 请求,开始推送 binary log 给 slave (即 canal )
- canal 解析 binary log 对象(原始为 byte 流)
canal部署
MySql设置
由于canal是通过mysql的binlog来处理数据库增量,因此需要开启相关配置信息
- 修改MySql配置文件my.cnf(测试环境位于/etc/my.cnf)开启MySql的binlog功能,并配置binlog模式为row。添加配置文件如下:
[mysqld]
log-bin=mysql-bin #添加这一行就ok
binlog-format=ROW #选择row模式
server_id=1 #配置mysql replaction需要定义,不能和canal的slaveId重复
- MySql中配置canal数据库管理员用户,并分配相应的权限(repication权限)
CREATE USER canal IDENTIFIED BY 'canal';
GRANT SELECT, REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'canal'@'%';
FLUSH PRIVILEGES;
- 测试环境账号密码:账号:canal 密码:Cannal!123456
- 检查数据库配置!检查数据库配置!检查数据库配置!确认无误后重启数据库
canal
- 创建canal文件夹,解压到文件夹中
- 修改配置文件,配置文件位于conf/example/instance.properties,配置信息如下
## mysql serverId与mysql配置的server_id不能相同
canal.instance.mysql.slaveId = 1234
#position info,需要改成自己的数据库信息
canal.instance.master.address = 10.20.128.19:3306
canal.instance.master.journal.name =
canal.instance.master.position =
canal.instance.master.timestamp =
#canal.instance.standby.address =
#canal.instance.standby.journal.name =
#canal.instance.standby.position =
#canal.instance.standby.timestamp =
#username/password,需要改成自己的数据库信息,mysql新添加的用户账号和密码
canal.instance.dbUsername = canal
canal.instance.dbPassword = Cannal!123456
## 需要监听数据库
canal.instance.defaultDatabaseName =
canal.instance.connectionCharset = UTF-8
#table regex 用于过滤数据源下的数据库和表
canal.instance.filter.regex = .\*\\\\..\*
- 启动canal,执行bin/startup.sh
- 查看日志,位于logs/canal/canal.log,出现以下内容表示启动成功
2020-07-09 17:04:09.522 [main] INFO com.alibaba.otter.canal.deployer.CanalLauncher - ## set default uncaught exception handler
2020-07-09 17:04:09.609 [main] INFO com.alibaba.otter.canal.deployer.CanalLauncher - ## load canal configurations
2020-07-09 17:04:09.640 [main] INFO com.alibaba.otter.canal.deployer.CanalStarter - ## start the canal server.
2020-07-09 17:04:09.723 [main] INFO com.alibaba.otter.canal.deployer.CanalController - ## start the canal server[10.20.128.19(10.20.128.19):11111]
2020-07-09 17:04:11.444 [main] INFO com.alibaba.otter.canal.deployer.CanalStarter - ## the canal server is running now ......
canal多数据源监听
有时候需要让canal需要监听多个数据源的数据库表增量,需要进一步对canal进行配置
- 在conf目录下创建文件夹hotel
- 将example中的instance.properties复制到hotel目录下并修改为目标数据源、数据库和表
- 修改conf/canal.properties,在canal.destinations后面添加hotel表示目标配置文件在conf/hotel目录中
canal.destinations = hotel,example
- 重新启动canal
- 启动成功后再logs目录下会添加一个hotel目录,里面用于保存hotel配置所属的日志
drwxr-xr-x. 2 root root 23 7月 9 17:19 hotel
canal-admin搭建
- 下载canal-admin,根据canal版本号下载
wget https://github.com/alibaba/canal/releases/download/canal-1.1.4/canal.admin-1.1.4.tar.gz
- 创建文件夹canal-admin,并解压到目录下,解压后的目录如下
drwxr-xr-x. 2 root root 76 7月 10 09:00 bin
drwxr-xr-x. 3 root root 156 7月 10 09:00 conf
drwxr-xr-x. 2 root root 4096 7月 10 09:00 lib
drwxrwxrwx. 2 root root 6 9月 2 2019 logs
- 修改配置文件conf/application.yml
server:
port: 8826 # canal-admin启动端口
spring:
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
spring.datasource:
address: 127.0.0.1:3306 # canal-admin配置数据源地址
database: canal_manager # canal-admin配置数据库
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 # canal-admin登陆用户和密码
adminPasswd: admin
- 初始化数据库,初始化脚本位于conf/canal_manager.sql,初始化的库为application.yml配置中
- 启动canal-admin,执行bin/startup.sh
- 访问 http://服务器:8090,出现以下界面表示启动成功
canal整合kafka
- 修改canal配置conf/canal.properties,对于mq的配置主要在MQ 配置块中
# tcp, kafka, RocketMQ
canal.serverMode = kafka
##################################################
######### MQ #############
##################################################
# kafka地址,集群用逗号分隔
canal.mq.servers = 10.20.128.25:9092
canal.mq.retries = 0
# flagMessage模式下可以调大该值, 但不要超过MQ消息体大小上限
canal.mq.batchSize = 16384
canal.mq.maxRequestSize = 1048576
# flatMessage模式下请将该值改大, 建议50-200
canal.mq.lingerMs = 100
canal.mq.bufferMemory = 33554432
canal.mq.canalBatchSize = 50
canal.mq.canalGetTimeout = 100
canal.mq.flatMessage = true
canal.mq.compressionType = none
canal.mq.acks = all
#canal.mq.properties. =
canal.mq.producerGroup = test
# Set this value to "cloud", if you want open message trace feature in aliyun.
canal.mq.accessChannel = local
# aliyun mq namespace
#canal.mq.namespace =
- 修改conf/hotel/instance.properties
# mq config
canal.mq.topic=hotel_index
# dynamic topic route by schema or table regex
#canal.mq.dynamicTopic=mytest1.user,mytest2\\..*,.*\\..*
canal.mq.partition=0
# hash partition config
#canal.mq.partitionsNum=3
#canal.mq.partitionHash=test.table:id^name,.*\\..*
这里主要配置mq的topic和分区,其中dynamicTopic可以发送到匹配的topic上
- 重启canal服务,并打开kafka消费控制台查看是否接收到canal同步的数据,如果看到kafka控制台接收到消费一个json串,表示已经搭建成功
遇到的坑
1.用户权限不足
Caused by: java.io.IOException: ErrorPacket [errorNumber=1227, fieldCount=-1, message=Access denied; you need (at least one of) the SUPER, REPLICATION CLIENT privilege(s) for this operation, sqlState=42000, sqlStateMarker=#]
with command: show master status
- 问题原因:canal在使用新增的用户来执行show master status 时由于权限不足导致无法获取到binlog
- 解决方案:权限不足的情况根据报错信息来确定需要哪种权限
如果提示 Access denied; you need (at least one of) the SUPER, REPLICATION CLIENT privilege(s) for this operation ,则没有对应 REPLICATION CLIENT 权限
如果提示 Access denied; you need (at least one of) the REPLICATION SLAVE privilege(s) for this operation ,则没有对应 REPLICATION SLAVE 权限
2.写入kafka报错
java.lang.RuntimeException: java.util.concurrent.ExecutionException: org.apache.kafka.common.errors.TimeoutException: Expiring 1 record(s) for hotel_index-0: 30042 ms has passed since batch creation plus linger time
at com.alibaba.otter.canal.kafka.CanalKafkaProducer.produce(CanalKafkaProducer.java:215) ~[canal.server-1.1.4.jar:na]
at com.alibaba.otter.canal.kafka.CanalKafkaProducer.send(CanalKafkaProducer.java:179) ~[canal.server-1.1.4.jar:na]
at com.alibaba.otter.canal.kafka.CanalKafkaProducer.send(CanalKafkaProducer.java:120) ~[canal.server-1.1.4.jar:na]
at com.alibaba.otter.canal.server.CanalMQStarter.worker(CanalMQStarter.java:183) [canal.server-1.1.4.jar:na]
at com.alibaba.otter.canal.server.CanalMQStarter.access$500(CanalMQStarter.java:23) [canal.server-1.1.4.jar:na]
at com.alibaba.otter.canal.server.CanalMQStarter$CanalMQRunnable.run(CanalMQStarter.java:225) [canal.server-1.1.4.jar:na]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_231]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_231]
at java.lang.Thread.run(Thread.java:748) [na:1.8.0_231]
- 问题原因:可能是没读取到hotel配置
- 解决方案:将canal.properties中canal.destinations = hotel,example 的hotel放到前面就好,即使重新放在后面也能够消费。无解。。。
3.云服务器上的数据库配置Canal
大部分云服务器上的Mysql其实与binlog相关配置都已经打开了,只需要配置一个新的用户即可,在上线的时候因为云服务器不能手动配置所以耽误了一些时间。