开发者社区> 问答> 正文

对position内存的竞争导致的定位错误问题

前提:使用PeriodMixedMetaManager.java作为metaManager 问题描述:

在CanalServerWithEmbedded.java的subscribe()方法中存在这样一段代码:

    Position position = canalInstance.getMetaManager().getCursor(clientIdentity);
    if (position == null) {
        position = canalInstance.getEventStore().getFirstPosition();// 获取一下store中的第一条
        if (position != null) {
            canalInstance.getMetaManager().updateCursor(clientIdentity, position); // 更新一下cursor
        }
        logger.info("subscribe successfully, {} with first position:{} ", clientIdentity, position);

根据上下文,当内存中的position为null时,这段代码会先取出eventStore中的position,再根据此position更新zk中的cursor位置。但是在PeriodMixedMetaManager中更新方法的代码如下:

public void updateCursor(ClientIdentity clientIdentity, Position position) throws CanalMetaManagerException {
    updateCursorTasks.add(clientIdentity);// 添加到任务队列中进行触发
    super.updateCursor(clientIdentity, position);
}

此方法会先将调度任务加入任务队列,然后再更新内存中的position。而调度线程则会先去取内存中的position,再更新zookeeper中的cursor。两个线程处于并发竞争态,可能会发生读后写情况。

问题解决办法(建议): 如果您认可这里的确可能有风险,把updateCursor里的两句话调换一下位置

问题背景: 在切换canal时发生了cursor定位错误(从0开始)的情况。我抱着“有问题”的心态来找问题,初步将问题定位在这里。如果存在风险更大的地方,请作者指点一二

原提问者GitHub用户ForaLake

展开
收起
绿子直子 2023-05-09 15:55:15 115 0
1 条回答
写回答
取消 提交回答
  • updateCursorTasks.add(clientIdentity);// 添加到任务队列中进行触发 这个只是一个标致位而已,具体更新的时候还是获取以下当前内存中的值进行写出,不会出现读到旧版本数据的问题,一般也建议subscribe是单客户端调用,避免并发

    原回答者GitHub用户agapple

    2023-05-10 10:49:09
    赞同 展开评论 打赏
问答分类:
问答标签:
问答地址:
问答排行榜
最热
最新

相关电子书

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