开发者社区> 问答> 正文

canal-server1.0.22基于mariadb10.1.14测试HA功能的BUG

测试描述:canalserver1.0.22基于mariadb10.1.14的HA功能不好用,部署两台canaserver当其中一台server挂掉后,zookeeper已经切换到新的canalserver,但新的canalserver获取的binlogname不正确导致读取mariadb的binlog错误。 mariadb中binlog名字:

(canal@127.0.0.1) [canal_test]> show binary logs; +------------------+-----------+ | Log_name | File_size | +------------------+-----------+ | mysql-bin.000001 | 25487 | | mysql-bin.000002 | 358 | | mysql-bin.000003 | 1518 | | mysql-bin.000004 | 29137967 | +------------------+-----------+ canalserver获取的binlogname:【binlog[mysql-bin.000004$^Nk<U+0081>:29138083]】中后半段有乱码

解决方法: 修改canalserver1.0.22源码com.alibaba.otter.canal.protocol.CanalEntry中对获取到的binlogname进行过滤,添加如下代码: 【public String filterLogFileName(String logfileName) { System.out.println("开始过滤logfileName:"+logfileName); Pattern p = Pattern.compile("(mysql-bin.[0-9])."); Matcher m = p.matcher(logfileName); while(m.find()){ if(m.groupCount() >= 1) { System.out.println("过滤logfileName为:"+m.group(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); } } 】

重新打包测试验证HA功能可以自动切换,但是存在canalserver切换时client消费端重复消费的问题。 但是在mysql5.6中测试未出现此问题

现在有测试mariadb10.1.14的验证版本吗,看源码好像是从protocolbuffer读取的时候binglogname就存在问题了,对binlog协议格式不是很了解,这个是protocolbuffer定义的协议格式问题吗?

实际代码分析:出现在【com.alibaba.otter.canal.parse.inbound.mysql.dbsync】中,int netlen = getUint24(PACKET_LEN_OFFSET);代码获取的包长度不一致造成的,maraidb和mysql获取的长度为:47和43,mariadb多获取4字节导致后续处理logfilename读取多4个字节;您好问下作者什么情况导致netlen获取的不一致?

原提问者GitHub用户linwenxue

展开
收起
绿子直子 2023-05-09 15:50:06 81 0
1 条回答
写回答
取消 提交回答
  • 最后4位可能是checksum,你试着找一下mariadb关闭一下mariadb的binlog checksum机制看看. ps. 之前有支持过mysql5.6的checksum,可能mariadb协议上有点不一样,没完全兼容,先帮忙验证一下是否为checksum问题

    if (FormatDescriptionLogEvent.versionProduct(versionSplit) >= FormatDescriptionLogEvent.checksumVersionProduct) {

    之前canal代码是限制了>=5.6.1版本号才会开启checksum检查,这是以前mysql5.6的机制,mariadb估计有不一样的行为

    原回答者GitHub用户agapple

    2023-05-10 11:07:32
    赞同 展开评论 打赏
问答排行榜
最热
最新

相关电子书

更多
移动互联网测试到质量的转变 立即下载
给ITer的技术实战进阶课-阿里CIO学院独家教材(四) 立即下载
F2etest — 多浏览器兼容性测试整体解决方案 立即下载

相关镜像