介绍单机版的canal-server搭建,实际项目中需要配合canal-admin搭建集群,将采集到的数据发送到kafka,springboot客户端从kafka消费,这里介绍的canal-spring-boot-starter支持从kafka消费
数据库账号创建
先在被监听的数据库里创建一个给canal用的账号
create user canal identified by 'canal';
grant select, show view, replication slave, replication client on *.* to 'canal'@'%';
flush privileges;
docker-compose.yml
version: '3.1'
services:
canal-server:
restart: always
container_name: canal-server
image: canal/canal-server:latest
ports:
- 11111:11111
volumes:
- ./server-logs:/home/admin/canal-server/logs
# 定义一个叫test的实例
- ./instance/test:/home/admin/canal-server/conf/test
在./instance/test/目录下创建instance.properties文件,内容如下:
canal.instance.master.address=192.168.3.3:3306
canal.instance.dbUsername=canal
canal.instance.dbPassword=canal
canal.instance.connectionCharset=UTF-8
canal.instance.filter.regex=要监听的库名\\..*
canal.instance.parser.parallelThreadSize=1 # CPU核心数
canal.instance.master.address要监听的mysql数据库地址canal.instance.dbUsername=canal该mysql数据库给canal使用的用户名canal.instance.dbPassword=canal该mysql数据库给canal使用的密码canal.instance.filter.regex设置要监听的数据库,如test\\..*表示监听test库所有表的变化canal.instance.parser.parallelThreadSize设置该实例canal占用的CPU核心数,测试使用设为1即可
配置还有很多,比如设置binlog的position等,可从canal官方文档中查阅
springboot配置
canal:
mode: simple
filter: # 过滤表名,可以为空
batch-size: 1
timeout: 1
server: 192.168.3.3:11111
destination: # canal-server中定义的实例名,不可以为空
user-name: canal
password: canal
async: true # 必须是true,设为false在启动时会报MessageHandler bean找不到,具体原因没看
springboot消费
pom.xml中引入canal-spring-boot-starter
<dependency>
<groupId>top.javatool</groupId>
<artifactId>canal-spring-boot-starter</artifactId>
<version>1.2.1-RELEASE</version>
</dependency>
这个包之前在《canal-spring-boot-starter修改》文章中讲过需要自己拉源码修改后才好用
假设有数据库里面有test表,对应的实体类是Test,按照下面这样定义一个消费者,就可以对Test这个表的改动进行监听
@Slf4j
@Component
@CanalTable(value = "表名")
public class TestConsumer implements EntryHandler<Test> {
@Override
public void insert(Test test) {
log.info("新增,{}", test);
}
/**
* @param before 只包含变更的属性
* @param after 包含所有属性
*/
@Override
public void update(Test before, Test after) {
log.info("更新,更新前={},更新后={}", before, after);
}
@Override
public void delete(Test test) {
log.info("删除,{}", test);
}
}
建议采用策略模式去处理不同表不同字段的处理逻辑
统一处理
统一对所有监听的表进行处理,是将表字段和值放到Map里,字段名为Map的key,字段值为Map的value
@Slf4j
@Component
@CanalTable(value = "all")
public class AllConsumer implements EntryHandler<Map<String, String>> {
@Override
public void insert(Map<String, String> map) {
log.info("新增,{}", map);
}
@Override
public void update(Map<String, String> before, Map<String, String> after) {
// CanalModel可以得到当前这次的库名和表名
CanalModel canal = CanalContext.getModel();
log.info("更新,更新前={},更新后={}", before, after);
}
@Override
public void delete(Map<String, String> map) {
log.info("删除,{}", map);
}
}
公众号:飞翔的代码