canal作用:
canal是阿里巴巴旗下的一款开源项目,纯Java开发。基于数据库增量日志解析,提供增量数据订阅&消费,目前主要支持了MySQL(也支持mariaDB)。
canal 就是一个同步增量数据的一个工具。
canal背景:
阿里巴巴B2B公司因为存在杭州和美国双机房部署,存在跨机房同步的业务需求。不过早期的数据库同步业务,主要是基于trigger(触发器)的方式获取增量变更,不过从2010年开始,阿里系公司开始逐步的尝试基于数据库的日志解析,获取增量变更进行同步,由此衍生出了增量订阅&消费的业务,从此开启了一段新纪元。
canal工作原理:
- canal 模拟 MySQL slave 的交互协议,伪装自己为 MySQL slave ,向 MySQL master 发送 dump 协
- MySQL master 收到 dump 请求,开始推送 binary log 给 slave (即 canal )
- canal 解析 binary log 对象(原始为 byte 流)
canal安装配置
canal下载地址:https://github.com/alibaba/canal/releases,选择适当的版本(本例使用1.1.6),下载developer 包;
数据库安装参考: /2023/06/30/mysql-5-7-windows-binary%e4%b8%8b%e8%bd%bd%e9%85%8d%e7%bd%ae/
创建 mysql nacos账号,配置到canal example install 上; dbUsername为 mysql的账号及密码;
文件: d:\software\canal-developer-1.1.6\conf\example\instance.properties
canal.instance.master.address=127.0.0.1:3306
...
canal.instance.dbUsername=canal # 数据库用户 -- CanalConnector canalConnector 连接属性用户密码
canal.instance.dbPassword=canal # 数据库密码
canal.instance.connectionCharset = UTF-8
canal.instance.detaulDatabaseName=testcanal
# table regex
#canal.instance.filter.regex=.*\\..*
canal.instance.filter.regex=mysql-dbname.table-name (数据库名.表名)
# table black regex
canal.instance.filter.black.regex=mysql\\.slave_.*
文件:d:\software\canal-developer-1.1.6\conf\example\canal.propertes
canal.port = 11111
canal.metrics.pull.port = 11112
# canal instance user/passwd
# canal.user = canal
# canal.passwd = E3619321C1A937C46A0D8BD1DAC39F93B27D4458
# canal admin config
#canal.admin.manager = 127.0.0.1:8089
canal.admin.port = 11110
canal.admin.user = admin
canal.admin.passwd = 4ACFE3202A5FF5CF467898FC58AAB1D615029441
canal.destinations = example
canal.instance.tsdb.dbUsername = canal #实例化连接对象的用户密码;
canal.instance.tsdb.dbPassword = canal
mysql创建用户、授权
mysql> create user canal@'%' IDENTIFIED by 'canal';
Query OK, 0 rows affected (0.03 sec)
mysql> GRANT SELECT, REPLICATION SLAVE, REPLICATION CLIENT,SUPER ON *.* TO 'canal'@'%';
Query OK, 0 rows affected (0.00 sec)
mysql> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.01 sec)
修改mysql的日志模式等:
# 打开binlog
log-bin=mysql-bin
# 选择ROW(行)模式
binlog-format=ROW
# 配置MySQL replaction需要定义,不要和canal的slaveId重复
server_id=1
binlog-ignore-db=information_schema
binlog-ignore-db=mysql
binlog-ignore-db=performance_schema
binlog-ignore-db=sys
# binlog-do-db=sys=table-name (这里DO-DB给值 不对)
重启 mysql:
window: net stop/start mysql
linux: systemctl stop/start mysql; [systemctl status mysql 显示不在活动状态\ <> /]
mysql 查看用户权限 ,设置用户权限
SELECT * FROM mysql.user;
# 调整权限
mysql> GRANT SELECT, REPLICATION SLAVE, REPLICATION CLIENT,SUPER ON *.* TO 'canal'@'%';
Query OK, 0 rows affected (0.00 sec)
mysql> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.01 sec)
获取当前 mysql 日志状态( mysql 目前做为 canal 的 master)
mysql> show master status;
+----------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+----------------+----------+--------------+------------------+-------------------+
| log-bin.000002 | 14746 | | | |
+----------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
配置canal的instance.properties的日志坐标:
# position info
canal.instance.master.address=127.0.0.1:3306
canal.instance.master.journal.name=log-bin.000002
canal.instance.master.position=14746
启动canal:
d:\software\canal-developer-1.1.6\>startup.bat
如果 在 /canal***/logs/canal/canal.log 有看到 “the canal server is running now…” 表示启动成功;
运行相关问题整理:
- 提示你需要先运行example 实例,可能是将在cmd窗口用 管理员打开;
- Received error packet: errno = 1236, sqlstate = HY000 errmsg = log event entry;
原因:
由于手动清除mysql 的binlog日志导致canal无法找打mysql的全局事务id无法找到binlog日志,进而报错。
解决办法:手动删除canal实例,重新新建实例
3. canal 删除实例
如果canal启动时候从日志看到报这个错误:can't find start position for example。有如下解决方法:
●单机
删除meta.dat文件,重启canal,问题解决。
●集群
进入canal对应的zookeeper集群下,删除节点/otter/canal/destinations/实例/1001/cursor,
重启canal即可恢复(不懂命令可以到zookeeper官网或者百度查找操作命令)。
4. canal 服务有连接上,但一直侦听不到INSERT;
这可能是 my.ini 的 binlog-do-db 的表名值不对;
5. 遇到 connect by peer 的错误,有可能是当前 canal 运行的日志文件或 position 与 canal server 的不一致;停止 canal server ,删除日志,删除 meta.bat, 修改 instance下 instance.properties 日志及 position ,重启;
执行 insert 操作 (有可能还是看不到日志,有可能是被 其他服务实例吃了)