先讨论DistroConsistencyServiceImpl AP最终一致性的实现。
我们知道当添加实例时会调用到put方法:
@Override
public void put(String key, Record value) throws NacosException {
onPut(key, value);
// 一致性协议的同步数据。这里同步数据是异步任务执行的,也就是说先返回客户端put成功再同步,弱一致性。 AP模型
distroProtocol.sync(new DistroKey(key, KeyBuilder.INSTANCE_LIST_KEY_PREFIX), ApplyAction.CHANGE,
globalConfig.getTaskDispatchPeriod() / 2);
}
onPut是本机节点的Notifier通知change事件。 distroProtocol.sync是最终一致性的数据同步。
onPut
public void onPut(String key, Record value) {
if (KeyBuilder.matchEphemeralInstanceListKey(key)) {
//创建临时数据
Datum<Instances> datum = new Datum<>();
datum.value = (Instances) value;
datum.key = key;
datum.timestamp.incrementAndGet();
//放进一个map里
dataStore.put(key, datum);
}
//没有监听器就返回
if (!listeners.containsKey(key)) {
return;
}
//有监听立即通知服务有改变
notifier.addTask(key, ApplyAction.CHANGE);
}
主要就是最后一行notifier.addTask(key, ApplyAction.CHANGE); 就是往tasks队列中添加数据:
public void addTask(String datumKey, ApplyAction action) {
// 如果services包含key,并且类型是change,则直接返回
if (services.containsKey(datumKey) && action == ApplyAction.CHANGE) {
return;
}
if (action == ApplyAction.CHANGE) {
// 如果是change,services添加一个空数据
services.put(datumKey, StringUtils.EMPTY);
}
// 数据对 加入队列中
tasks.offer(Pair.with(datumKey, action));
}
我们之前分析到,notifier中有一个无限循环的任务,会从tasks中一直take数据,当取到新的任务时,则会发起通知:
@Override
public void run() {
Loggers.DISTRO.info("distro notifier started");
// 无限循环
for (; ; ) {
try {
// 消费队列
Pair<String, ApplyAction> pair = tasks.take();
handle(pair);
} catch (Throwable e) {
Loggers.DISTRO.error("[NACOS-DISTRO] Error while handling notifying task", e);
}
}
}
private void handle(Pair<String, ApplyAction> pair) {
try {
String datumKey = pair.getValue0();
ApplyActi