KING 博主等级

一帆风顺 ⛵️⛵️⛵️

大数据之Canal

钟晓川
2023-06-04 / 142 点赞 / 3009 阅读

什么是Canal

Canal是用 Java开发的基于数据库增量日志解析,提供增量数据订阅 &消费的中间件。目前 。 Canal主要支持了 MySQL的 Binlog解析,解析完成后才利用 Canal Client来处理获得的相关数据。 (数据库同步需要阿里的 Otter中间件,基于 Canal)。

什么是Binlog

MySQL的二进制日志可以说MySQL最重要的日志了,它记录了所有的DDL和DML(除了数据库查询)语句,以事件形式记录,还包含语句所执行的消耗时间,MySQL的二进制是事务安全性的。

一般来说,开启二进制日志大概会有1%的性能损耗,二进制有两个重要的使用场景

一、MySQL Replication在Master端开启Binlog,Master把它的二进制日志传递给Slaves来达到Master-Slave数据一致的目的。

二、自然就是数据恢复了,通过使用MySQL Binlog工具来使恢复数据

二进制日志包括两类文件

二进制日志索引文件(文件名后缀为.index)用于记录所有的二进制文件
二进制日志文件(文件名后缀为.00000*)记录数据库所有的DDL和DML(除了数据库查询语句)语句事件。

Binlog的分类

​ MySQL Binlog的格式有三种,分别是 STATEMENT,MIXED,ROW。在配置文件中可以选择配置 binlog_format= statement|mixed|row。 三种格式的 区别:

​ 1)statement 语句级, binlog会记录每次一执行写操作的语句。相对 row模式节省空间,但是可能产生不一致性,比如 update tt set create_date= 如果用 binlog日志进行恢复,由于执行时间不同可能产生的数据就不同。
​ 优点:节省空间 。
​ 缺点:有可能造成数据不一致。

​ 2 row 行级, binlog会记录每次操作后每行记录的变化。
​ 优点:保持数据的绝对一致性。因为不管sql是什么,引用了什么函数,他只记录执行后的效果。
​ 缺点:占用较大空间。

​ 3)mixed statement的升级版,一定程度上解决了,因为一些情况而造成的 statement模式不一致问题 默认还是 statement 在某些情况下譬如:当函数中包含 UUID() 时;包含AUTO_INCREMENT 字段的表被更新时;执行 INSERT DELAYED 语句时;用 UDF 时;会按照ROW的方式进行处理
​ 优点:节省空间,同时兼顾了一定的一致性。
​ 缺点:还有些极个别情况依旧会造成不一致,另外statement和 mixed对于需要对binlog的监控的情况都不方便。
综合上面对比,
Canal想做监控分析,选择 row格式比较合适 。

MySQL主从复制过程

1)Master主库将改变记录,写到二进制日志 (Binary Log)中
2)Slave从库向 MySQL Master发送 dump协议,将 Master主库的 binary log events拷贝到它的中继日志 (relay log)
3)Slave从库读取并重做中继日志中的事件,将改变的数据同步到自己的数据库。

Canal的工作原理

很简单,就是把自己伪装成 Slave,假装从 Master复制数据 。

MySQL的准备

创建数据库

CREATE DATABASE mydb1;

创建数据库表

CREATE TABLE user_info(
`id` VARCHAR(255),
`name` VARCHAR(255),
`sex` VARCHAR(255)
);

修改 配置 文件 开启 Binlog

[root@server01 conf]$ vim /my_data/mysql05/conf/my.cnf
server-id=1
log-bin=mysql-bin
binlog_format=row
binlog-do-db=mydb1

注意:binlog-do-db根据自己的情况进行修改,指定具体要同步的数据库 ,如果不配置则表示所有数据库均开启 Binlog

重启MySQL使配置生效

docker restart mysql05

赋权限

在MySQL中执行

mysql> set global validate_password_length=4;
mysql> set global validate_password_policy=0;
mysql> GRANT SELECT, REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'canal'@'%' IDENTIFIED BY 'canal';

Canal 的下载和安装

下载并解压 Jar包

https://github.com/alibaba/canal/releases

注意:canal解压后是分散的,我们在指定解压目录的时候需要将 canal指定上

[root@server01 /]$ mkdir /opt/module/canal
[root@server01 /]$ tar -zxvf canal.deployer-1.1.2.tar.gz -C /opt/module/canal

修改 canal.properties的配置

[root@server01 conf]$ pwd
/opt/module/canal/conf
[root@server01 conf]$ vim canal.properties
######### common argument #############
canal.id = 1
canal.ip =
canal.port = 11111
canal.metrics.pull.port = 11112
canal.zkServers =
# flush data to zk
canal.zookeeper.flush.period = 1000
canal.withoutNetty = false
# tcp, kafka, RocketMQ
canal.serverMode = tcp
# flush meta cursor/parse position to file
canal.instance.parser.parallel = false

说明:这个文件是 canal的基本通用配置, canal端口号默认就是 11111 修改 canal的输出 model,默认 tcp,改为输出到 kafka
多实例配置如果创建多个实例 通过前面 canal架构,我们可以知道,一个 canal服务中可以有多个 instance conf/下的每一个 example即是一个实例,每个实例下面都有独立的配置文件。默认只有一个实例 example,如果需要多个实例处理不同的 MySQL数据的话,直接拷贝出多个 example,并对其重新命名,命名和配置文件中指定的名称一致,然后修改canal.properties中的 canal.destinations=实例 1,实例 2,实例 3。

修改 instance.properties

我们这里只读取一个MySQL数据,所以只有一个实例,这个实例的配置文件在conf/example目录下

[root@server01 example]$ pwd
/opt/module/canal/conf/example
[root@server01 example]$ vim instance.properties

1)配置 MySQL服务器地址

## mysql serverId , v1.0.26+ will autoGen
canal.instance.mysql.slaveId=20
# enable gtid use true/false
canal.instance.gtidon=false
# position info
canal.instance.master.address=127.0.0.1:3306

2)配置连接 MySQL的用户名和密码,默认就是我们前面授权的 canal

# username/password
canal.instance.dbUsername=canal
canal.instance.dbPassword=canal
canal.instance.connectionCharset=UTF8 
canal.instance.defaultDatabaseName=test
# enable druid Decrypt database password
canal.instance.enableDruid=false

常见问题

  1. 尝试多次,客户端一直读取不到binlog变更

    https://github.com/alibaba/canal/issues/1429

  2. Canal.deployer 启动报错说CHARACTER SET 'utf8' COLLATE 'utf8_unico', expect null

    删除实体(默认example)里面的文件 h2.mv.db

142