0. 环境
- nacos版本:1.4.1
- Spring Cloud : 2020.0.2
- Spring Boot :2.4.4
- Spring Cloud alibaba: 2.2.5.RELEASE
在一文中我们着重介绍了nacos 对于raft协议实现的落地,介绍了它的选举,它的心跳是怎样运转的,其实重要的还是term 与随机时间这块还有获得半数+1票
,本文就要看看基于这套raft 协议的数据同步是怎样进行的,主要是写操作。
1. 回顾一下服务注册流程
当一个服务注册请求打到nacos服务器的时候,它会根据根据你这个实例的namespace, serviceName,group
信息获取到对应的service
,如果不存在就创建,然后就是进行根据你这个service里面原来的实例列表信息在加上这个新的实例信息,整合出来一个新的实例列表信息,接着就是找到一致性服务(consistencyService
)进行put
操作,这个consistencyService
会根据实例是临时节点(默认就是这个临时节点)还是永久节点选择对应的consistencyService
,其实对于临时节点对应的就是DistroConsistencyServiceImpl
,它节点之间数据同步是peer to peer
的,跟那个eureka
差不多,对于永久节点对应的是PersistentConsistencyServiceDelegateImp
l,这个里面有2个实现一个是RaftConsistencyServiceImpl
的,一个是PersistentServiceProcessor
,RaftConsistencyServiceImpl
是1.4之前版本使用的,也是我们今天要介绍的,后面这个PersistentServiceProcessor
是1.4包括以上的版本使用的(这里我们先不介绍)。 大概就是下图这个样子:
本文主要就是介绍下红框中的基于raft 协议数据同步的部分。
2. 基于raft的写操作同步
我们可以对照着上图红框部分来看看RaftConsistencyServiceImpl# put
:
@Override
public void put(String key, Record value) throws NacosException {
// 检查有没有停止
checkIsStopWork();
try {
// todo 找到这个
raftCore.signalPublish(key, value);
} catch (Exception e) {
Loggers.RAFT.error("Raft put failed.", e);
throw new NacosException(NacosException.SERVER_ERROR, "Raft put failed, key:" + key + ", value:" + value,
e);
}
}
复制代码
这里没什么好说的,就是检查下状态,然后找到这个raftCore
的signalPublish
来进行存储,同步。接下来看看signalPublish
这个方法:
public void signalPublish(String key, Record value) throws Exception {
if (stopWork) {
throw