在 ETCD 源码学习过程,不会讲解太多的源码知识,只讲解相关的实现机制,需要关注源码细节的朋友可以自行根据文章中的提示,找到相关源码进行学习。
主要文件
/etcdserver/api/v3rpc/watch.go watch 服务端实现
/mvcc/watcher.go 主要封装 watchStream 的实现
/mvcc/watchable_store.go watch 版本的 KV 存储实现
/mvcc/watchable_store_txn.go 主要实现事务提交后 End() 函数的处理
/mvcc/watcher_group.go
主要流程
主要数据结构
//文件:/etcdserver/api/v3rpc/watch.go
type watchServer struct {
...
watchable mvcc.WatchableKV // 键值存储
....
}
type serverWatchStream struct {
...
watchable mvcc.WatchableKV //kv 存储
...
gRPCStream pb.Watch_WatchServer //与客户端进行连接的 Stream
watchStream mvcc.WatchStream //key 变动的消息管道
ctrlStream chan *pb.WatchResponse //响应客户端请求的消息管道
...
progress map[mvcc.WatchID]bool //该类型的 watch,服务端会定时发送类似心跳消息
prevKV map[mvcc.WatchID]bool //该类型表明,对于/a/b 这样的监听范围, 如果 b 变化了, 前缀/a也需要通知
fragment map[mvcc.WatchID]bool //该类型表明,传输数据量大于阈值,需要拆分发送
}
//文件:/mvcc/watcher.go
//响应结构体
type WatchResponse struct {
WatchID WatchID
Revision int64 //当前 watchResponse 实例创建时对应的 revision 值
CompactRevision int64 //压缩操作对应的 revison
}
type watchStream struct {
watchable watchable //用来记录关联的 watchableStore
ch chan WatchResponse // event 事件写入通道
...
cancels map[WatchID]cancelFunc
watchers map[WatchID]*watcher //用来记录唯一标识与 watcher 的实例的关系
}
//文件:/mvcc/watcher_group.go
type eventBatch struct {
//其中记录的 Event 实例是按照 revision 排序的
evs []mvccpb.Event
//记录当前 eventBatch 中,有多少个来自不同的 main revison,
revs int
//当前 eventBatch 记录的 Event 个数达到上限之后,后续 Event 实例无法加入该 eventBatch 中
//该字段记录了无法加入该 eventBatch 实例的第一个main revision
moreRev int64
}
type watcherBatch map[*watcher]*eventBatch
type watcherSet map[*watcher]struct{}
type watcherSetByKey map[string]watcherSet
type watcherGroup struct {
keyWatchers watcherSetByKey //记录监听单