文件路径nacos/naming/src/main/java/com/alibaba/nacos/naming/consistency/ephemeral/distro/DataSyncer.java
submit方法中,第120行的代码片段1
Map<String, Datum> datumMap = dataStore.batchGet(keys);
这里面从dataStore取出了keys对应的数据,并在接下来132行将其序列化后,发送到其他naming节点。 132行代码
boolean success = NamingProxy.syncData(data, task.getTargetServer());
但是在发送成功前(执行121至132行间的逻辑时),taskMap中的keys依旧存在,发送成功后才会从taskMap移除,这里存在并发问题。 我们先看88行至105行的代码逻辑
if (task.getRetryCount() == 0) {
Iterator<String> iterator = task.getKeys().iterator();
while (iterator.hasNext()) {
String key = iterator.next();
if (StringUtils.isNotBlank(taskMap.putIfAbsent(buildKey(key, task.getTargetServer()), key))) {
// associated key already exist:
if (Loggers.DISTRO.isDebugEnabled()) {
Loggers.DISTRO.debug("sync already in process, key: {}", key);
}
iterator.remove();
}
}
}
if (task.getKeys().isEmpty()) {
// all keys are removed:
return;
}
当其他线程执行到88行至105行间的代码时,如果相同的key存在于taskMap中,这个key将不会再执行后续的流程,会导致第一个线程执行132行同步到其他节点的数据是旧的
这里在很极限的情况下的确可能存在问题,但是这个Distro本身就是AP协议,还有对账机制可以修复遗漏的同步信息,详见/checksum接口。
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。