Skip to content

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

@ForaLake

Description

@ForaLake

前提:使用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开始)的情况。我抱着“有问题”的心态来找问题,初步将问题定位在这里。如果存在风险更大的地方,请作者指点一二

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions