Raft篇-1
Raft篇-1 raft库只实现核心的raft算法部分,使用raft库时,用户需要自己实现其中的网络传输以及存储,以分别支持raft节点内部的通信和raft log的持久化等。 raftexample是etcd库中一个使用raft库的例子,其中实现了上述所需的网络传输和存储能力,以及提供了http服务给外部调用,包括读写数据等。 从raftexample的实现来看etcd是怎么设计和实现raft协议的。 启动结构 newRaftNode(*id, strings.Split(*cluster, ","), *join, getSnapshot, proposeC, confChangeC) newKVStore(<-snapshotterReady, proposeC, commitC, errorC) serveHttpKVAPI(kvs, *kvport, confChangeC, errorC) newRaftNode:启动raft node节点,raft算法核心实现部分 newKVStore:每个节点的存储实现 serveHttpKVAPI:提供给外部的http接口,提供读写数据,增删节点能力(这个不是raft node节点之间的通信实现) 写入数据 首先在raftexample文档中可以看到写入数据是通过PUT请求实现的 curl -L http://127.0.0.1:12380/my-key -XPUT -d foo PUT实现如下: // contrib/raftexample/httpapi.go#L36 case r.Method == "PUT": h.store.Propose(key, string(v)) // Propose函数实现 // contrib/raftexample/kvstore.go#L70 s.proposeC <- buf.String() 最终是往 kvstore 的 proposeC channel中写入了数据,这个proposeC就是在启动时同时给raft node和kvstore用于初始化的channel。因此粗略得到如下关系图 处理proposeC的流程 // contrib/raftexample/raft.go#L402 func (rc *raftNode) serveChannels() { // ... for rc.proposeC != nil && rc....