问题
canal-server 在配合 ZooKeeperLogPositionManager使用时,重启后读取的 binlog 位点是 server 上一次 parse 的位置还是 client ack 的位置? 根据 https://github.com/alibaba/canal/wiki/Introduction#eventparser%E8%AE%BE%E8%AE%A1 的描述,EventParser 记录的 binlog 位点是上一次 parse 到的位点,这种行为是不是会导致 server 重启时丢弃事件?
现象
提出这个问题是因为在实践的时候遇到了 binlog 事件丢失的问题,现象如下:
在 canal-server 有事件积压(大约 20 M,未达到设定的内存限制)时重启 canal-server、canal-client、zk(使用 docker-compose 部署,server、client 和 zk 均为单实例,server 使用镜像为 canal/canal-server:v1.1.0),canal 会丢弃一部分事件。
binlog 丢失原因猜测 根据 https://github.com/alibaba/canal/wiki/Introduction#eventparser%E8%AE%BE%E8%AE%A1 的描述,EventParser 只记录 parse 到的 binlog 位点,猜测原因是 server 端在积压事件的同时重启,重启后从上次 parse 到的位点进行消费,造成了内存中经过 parse、sink、store 但是还未被 get 的 binlog 丢失。
client 代码
client (基于 commit 节点 82f8a9f - fixed issue #483 , show slave hosts 修改)使用 com.alibaba.otter.canal.client.ClientLauncher 配合自定义的 CanalOuterAdapter 进行消费。为了记录接收到的 binlog 位点,对 com.alibaba.otter.canal.client.adapter.loader.CanalAdapterWorker 进行了如下修改:
while (running) { try { // if (switcher != null) { // switcher.get(); // } logger.info("=============> Start to connect destination: {} <=============", this.canalDestination); connector.connect(); logger.info("=============> Start to subscribe destination: {} <=============", this.canalDestination); connector.subscribe(); logger.info("=============> Subscribe destination: {} succeed <=============", this.canalDestination); while (running) { // try { // if (switcher != null) { // switcher.get(); // } // } catch (TimeoutException e) { // break; // }
// server配置canal.instance.network.soTimeout(默认: 30s)
// 范围内未与server交互,server将关闭本次socket连接
// 下面是添加的部分
Message message = connector.getWithoutAck(BATCH_SIZE); // 获取指定数量的数据
for (CanalEntry.Entry entry : message.getEntries()) {
if (!entry.getEntryType().equals(CanalEntry.EntryType.ROWDATA)) {
continue;
}
logger.info("receive binlog event ,file {} ,offset {}", entry.getHeader().getLogfileName(), entry.getHeader().getLogfileOffset());
}
检查 client 日志,发现接收到的 binlog 不连续,范围与 canal 整体丢弃的 binlog 范围相同。由于是在 client 的入口处打印的 binlog 位点,所以我认为 client 没有接收到 binlog 事件,server 处丢弃了这一部分事件。
配置
instance.xml 与 canal/deployer/src/main/resources/spring/default-instance.xml 的 diff 如下:
<bean class="com.alibaba.otter.canal.parse.index.ZooKeeperLogPositionManager"> <constructor-arg index="0" ref="zkClientx"/>
<bean class="com.alibaba.otter.canal.parse.support.AuthenticationInfo">
<bean class="com.alibaba.otter.canal.parse.support.AuthenticationInfo">
143,144d133 < <
请大神指点迷津,是我的配置有误,还是 server 确实会在重启后丢失积压的事件?
原提问者GitHub用户fotguuu
重启读取的是上一次client ack的位点,内存数据虽然会丢失,但会基于最后一次消费成功的位点继续dump binlog,所以架构上不存在消息丢失,只要正确ack位点
你这是配置问题,必须参考file/default-instance.xml里的com.alibaba.otter.canal.parse.index.FailbackLogPositionManager的配置,它在重新启动时会读取到MetaLogPositionManager (ack的位点)
原回答者GitHub用户agapple
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。