开发者社区> 问答> 正文

canal-server 在积压事件时重启会丢弃内存中的积压事件吗?

问题

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 如下:

112,120c112,113 < < < < < < < < <

                  <bean class="com.alibaba.otter.canal.parse.index.ZooKeeperLogPositionManager">
                          <constructor-arg index="0" ref="zkClientx"/>

129c122 <

                  <bean class="com.alibaba.otter.canal.parse.support.AuthenticationInfo">

133,134d125 < < 139c130 <

                  <bean class="com.alibaba.otter.canal.parse.support.AuthenticationInfo">

143,144d133 < <

请大神指点迷津,是我的配置有误,还是 server 确实会在重启后丢失积压的事件?

原提问者GitHub用户fotguuu

展开
收起
Java工程师 2023-05-08 17:58:17 238 0
1 条回答
写回答
取消 提交回答
  • 重启读取的是上一次client ack的位点,内存数据虽然会丢失,但会基于最后一次消费成功的位点继续dump binlog,所以架构上不存在消息丢失,只要正确ack位点

    你这是配置问题,必须参考file/default-instance.xml里的com.alibaba.otter.canal.parse.index.FailbackLogPositionManager的配置,它在重新启动时会读取到MetaLogPositionManager (ack的位点)

    原回答者GitHub用户agapple

    2023-05-09 18:49:21
    赞同 展开评论 打赏
问答排行榜
最热
最新

相关电子书

更多
内存取证与IaaS云平台恶意行 为的安全监控 立即下载
云服务器ECS内存增强型实例re6全新发布 立即下载
低代码开发师(初级)实战教程 立即下载