etcd raft
1 环境
https://github.com/etcd-io/etcd/releases/tag/v3.5.18
raftexample 是 etcd 提供的一个使用 etcd raft 共识算法库的示例。raftexample 最终实现了一个对外提供 REST API 的分布式键值存储服务。
2 代码结构
raftexample 的结构非常简洁,其主要文件如下:
main.go: 负责 raft 模块,httpapi 模块和 kvstore 模块之间的交互方式的组织;
raft.go: 提供网络基础通信、raft 协议推进执行能力。
httpapi.go: 向客户端 client 提供服务,主要提供 Get、Put、Post、Delete 接口服务。这三个服务的作用分别是检索KV、存储KV、新增 raft 节点、删除 raft 节点。
kvstore.go: 提供持久化存储功能。raft 协议本身并不提供存储能力,所以所有的 KV 最终的归属是这个kvstore。
get post delete put
| | | |
| | | |
+-V-----V--------------V-----V--+
| HTTP Service |
+------+------------------------+
|
|
+------V------+ ---> +----------+
| KVStore | | raftNode |
+-------------+ <--- +----------+
首先 client 向 raft 节点发送请求,假设调用 Put 方法,存储一个新的 kv。
节点收到这个请求之后,将 KV 对传递给 kvstore。
kvstore 拿到 kv 之后,并不急着将其进行持久化存储,而是将这个 kv 投递给 raftNode,
通过 raftNode 对这个 kv 进行决议,决议通过后,再将这个 kv 回送给 kvstore。
最后 kvstore 进行持久化存储。
3 代码实现
3.1 http service
http service 的实现比较简单,它自定义了 httpKVAPI 结构体,其重写了 ServeHTTP 方法。然后通过serveHttpKVAPI 方法启动服务。需要注意的是,其内部持有 kvstore 对象,Get 方法和 Put 方法分别调用了 kvstore 的 Propose 方法和 Lookup 方法。
3.2 kvstore
type kvstore struct {
proposeC chan<- string // channel for proposing updates
mu sync.RWMutex
kvStore map[string]string // current committed key-value pairs
snapshotter *snap.Snapshotter
}
kvstore 的定义中,kvStore 是存储结构,用了简单的 map 进行存储。mu负责多线程同步。除此之外,还有两个非常关键的属性,分别是 proposeC 管道和 snapshotter。这个结构说明,如果要实现一个kvstore,除了基本的存储结构之外,至少还需要一个管道和一个 snapshotter。
+----------------------------------+
| HTTP Service |
+---------+------------------------+
|
|
+------V------+ +-------------+
| | | |
| +---------+ | | |
| |proposeC +------->| |
| +---------+ | | |
| | | |
| | | +---------+ |
| |<-------+ commitC | |
| | | +---------+ |
| | | +---------+ |
| |<-------+ errorC | |
| | | +---------+ |
| | | |
| | | |
| KVStore | | raftNode |
+-------------+ +-------------+
kvstore 和raftNode 之间使用了三个管道,分别是 proposeC(提议)、commitC、errorC。
kvstore使用proposeC将从http service传来的数据提交给raftNode;
raftNode将通过决议的数据,从commitC回送给kvstore。异常信息通过errorC进行传输。
3.3 raftNode
Last updated