前提:使用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
updateCursorTasks.add(clientIdentity);// 添加到任务队列中进行触发 这个只是一个标致位而已,具体更新的时候还是获取以下当前内存中的值进行写出,不会出现读到旧版本数据的问题,一般也建议subscribe是单客户端调用,避免并发
原回答者GitHub用户agapple
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。