canal的使用记录(binlog文件名字有乱码导致主备切换报错)

本文探讨了Canal不同版本与MariaDB之间的兼容性问题,特别是在主备切换过程中出现的binlog文件名乱码问题及解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

canal的安装在canal的github wiki上面很详细

具体参见: canal的canal github wiki

虽然wiki上面建议使用1.0.22版本,一看那个版本感觉太老了,还是用了最新的1.0.25 Release版本,其中1.0.22版本的binlog的日志名字和他的position等的元数据会存储为一个meta.dat文件放在你conf的instance目录下,比如官方的example instance,meta.dat就会放到\conf\example\meta.dat下面。

1.0.25版本默认使用了嵌入式h2数据库,其中数据库的存储文件也在con的instance目录下h2.mv.db。

当我使用1.0.22版本的canal,10.2.11的MariaDB,使用集群版本,第一次通过git上面提供的canal client 端能获取到数据库的操作信息,但是第二次就开始报错,弄了半天没搞好。然后将canal版本换为1.0.25,并且清理掉zookeeper的canal数据,发现没反应,canal server启动了,日志也正常,client端就是没获取到值。

1.0.22版本的canal,10.2.11的MariaDB第二次报错:

2018-01-03 00:36:28.369 [destination = lijietest , address = /192.168.80.130:3306 , EventParser] ERROR com.alibaba.otter.canal.common.alarm.LogAlarmHandler - destination:lijietest[java.io.IOException: Received error packet: errno = 1236, sqlstate = HY000 errmsg = Could not find first log file name in binary log index file
    at com.alibaba.otter.canal.parse.inbound.mysql.dbsync.DirectLogFetcher.fetch(DirectLogFetcher.java:95)
    at com.alibaba.otter.canal.parse.inbound.mysql.MysqlConnection.dump(MysqlConnection.java:113)
    at com.alibaba.otter.canal.parse.inbound.AbstractEventParser$3.run(AbstractEventParser.java:210)
    at java.lang.Thread.run(Thread.java:748)

然后使用了5.1.73的mysql,1.0.25的canal的canal,部署顺利,测试的时候当两台机器第一次运行canal server的时候,发现客户端获取不到数据库的操作,当停掉当前work节点后,另外一个standby节点变为work节点,client端就能监听到数据库的操作,并且之后切换没返现问题。

最后又使用了5.1.73的mysql,1.0.22版本的canal做测试,部署顺利,测试也顺利。


用了10.2.11的MariaDB和1.0.26alpha 1的canal,发现主备切换的时候binlog文件名字会乱码,导致从节点dump数据的时候数据库报错:

这里写图片描述

查看本地的binlog文件,文件名字是正常的:

这里写图片描述

查看zookeeper节点里面的cursor数据,binlog名字有乱码,这个乱码导致切换的时候另外一个节点拿着binlog文件和position向数据库发送协议的时候,数据库找不到这个文件从而一直报错。

不知是不是版本兼容问题,这里暂时做个记录。


之前发现canal主备切换的时候 读取到的binlog文件名字会出现乱码,后来参考:canalserver1.0.22基于mariadb10.1.14的HA功能bug
这一篇博客可以解决,思路也很简单就是将获取binlog文件名字的方法做下修改,只取binlog文件名的 mysql-bin.000001,其他的乱码用正则过滤掉,或者substr也行。

将canal工程下的子protocol工程下的CanalEntry类获取binlog文件名字的方法getLogfileName(),修改一下,并且添加一个filterLogFileName方法用来剔除乱码,该类里面有两个getLogfileName方法都修改下(其中一个在静态内部类Builder中,另外一个在静态内部类Header中)

这里写图片描述

/**
* 添加该方法用来剔除乱码
*/
public String filterLogFileName(String logfileName) {
            Pattern p = Pattern.compile("(mysql-bin\\.[0-9]{6}).");
            Matcher m = p.matcher(logfileName);
            while (m.find()) {
                if (m.groupCount() >= 1) {
                    return m.group(1);
                }
            }
            return logfileName;
        }

/**
* 修改该方法,调用上面的添加的方法
*/
public String getLogfileName() {
            java.lang.Object ref = logfileName_;
            if (ref instanceof String) {
                return filterLogFileName((String) ref);
            } else {
                com.google.protobuf.ByteString bs =
                        (com.google.protobuf.ByteString) ref;
                String s = bs.toStringUtf8();
                if (com.google.protobuf.Internal.isValidUtf8(bs)) {
                    logfileName_ = s;
                }
                return filterLogFileName(s);
            }
        }

重新打包,并将新编译好的canal.protocol-1.0.22.jar文件替换原lib目录下的该文件,然后再做测试发现主备切换没问题了。然后也重新编译了canal.protocol-1.0.25.jar 发现25版本的canal也没问题了。

查看zookeeper的cursor节点,发现乱码没了

get /otter/canal/destinations/example/1001/cursor

这里写图片描述

其中binlog中的日志都是有效数据,就是确定数据库已经提交事务的数据,没有提交事务的数据不会落到binlog中。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值