菜鸟一枚,最近几天看了下etcd-raft库的官方使用示例,本来俺的代码能力较差,网上关于这个库的使用的资料不多,所以希望写此文章以给同学们带来一丢丢的帮助-------
首先俺觉得应该初步认识一下raft算法,看这儿,这是大婶们翻译的官方论文,比较详细。还有这个,里边有raft运行的动态图,官方示例在这里,好了,咱言归正传
以官方示例的主函数作为入口
cluster := flag.String("cluster", "http://127.0.0.1:9021", "comma separated cluster peers")
id := flag.Int("id", 1, "node ID")
kvport := flag.Int("port", 9121, "key-value server port")
join := flag.Bool("join", false, "join an existing cluster")
flag.Parse()
join为true代表中途加入
这段的作用是执行示例程序时需要传入一些参数(集群信息)例如(编译好的可执行程序为etcd-raft):
./etcd-raft --id 1 --cluster http://127.0.0.1:12379,http://127.0.0.1:22379,http://127.0.0.1:32379 --port 12380
proposeC := make(chan string)
defer close(proposeC)
confChangeC := make(chan raftpb.ConfChange)
defer close(confChangeC)
重要的来了
var kvs *kvstore
getSnapshot := func() ([]byte, error) { return kvs.getSnapshot() }
commitC, errorC, snapshotterReady := newRaftNode(*id, strings.Split(*cluster, ","), *join, getSnapshot, proposeC, confChangeC)
kvs = newKVStore(<-snapshotterReady, proposeC, commitC, errorC)
// the key-value http handler will propose updates to raft
serveHttpKVAPI(kvs, *kvport, confChangeC, errorC)
首先定义一个键值对存储和获取快照函数,以及proposeC和confChangeC等传入newRaftNode函数,
newRaftNode可以理解为初始化一堆配置然后启动raft,
newKVStore返回一个kvstore
s := &kvstore{proposeC: proposeC, kvStore: make(map[string]string), snapshotter: snapshotter}.....return s
至于serveHttpKVAPI:serveHttpKVAPI starts a key-value server with a GET/PUT API and listens.启动键值服务
客户端的请求通过proposeC传递给raft内部,在httpapi.go:
func (h *httpKVAPI) ServeHTTP(w http.ResponseWriter, r *http.Request)中通过调用
h.store.Propose(key, string(v))把客户端的请求放入proposeC,raft取出做处理,提交过后的请求(也就是说leader告知了所有的follower)封装到commitC,应用在kvstore.go:func (s *kvstore) readCommits(commitC <-chan *string, errorC <-chan error)中遍历出commitC中的data,存储键值对(示例是放入内存)confChangeC和proposeC类似,存放的是配置信息(客户端的更改集群配置请求例如增加节点),至于snapshot:上面那个论文翻译里边有说,看了就懂了