readOnly模式
在看MsgReadIndex类型的消息之前需要先对readOnly的模式有所了解,raft结构体中的readOnly作用是批量处理只读请求,只读请求有两种模式,分别是ReadOnlySafe和ReadOnlyLeaseBased,ReadOnlySafe是ETCD作者推荐的模式,因为这种模式不受节点之间时钟差异和网络分区的影响,我们主要看一下ReadOnlySafe使用的实现方式。
readOnly的模式的ReadOnlySafe模式会用到readOnly结构体,主要用于批量处理只读请求,readOnly的实现如下:
type readIndexStatus struct {
req pb.Message //记录了对应的MsgReadIndex请求
index uint64 //该MsgReadIndex请求到达时,对应的已提交位置
acks map[uint64]struct{} //记录了该MsgReadIndex相关的MsgHeartbeatResp响应的信息
}
type readOnly struct {
option ReadOnlyOption //当前只读请求的处理模式,ReadOnlySafe ReadOnlyOpt 和 ReadOnlyLeaseBased两种模式
/*
在etcd服务端收到MsgReadIndex消息时,会为其创建一个唯一的消息ID,并作为MsgReadIndex消息的第一条Entry记录。
在pendingReadIndex维护了消息ID与对应请求readIndexStatus实例的映射
*/
pendingReadIndex map[string]*readIndexStatus
readIndexQueue []string //记录了MsgReadIndex请求对应的消息ID,这样可以保证MsgReadIndex的顺序
}
//初始化readOnly
func newReadOnly(option ReadOnlyOption) *readOnly {
return &readOnly{
option: option,
pendingReadIndex: make(map[string]*readIndexStatus),
}
}
// addRequest adds a read only reuqest into readonly struct.
// `index` is the commit index of the raft state machine when it received
// the read only request.
// `m` is the original read only request message from the local or remote node.
//将已提交的位置(raftLog.committed)以及MsgReadIndex消息的相关信息存到readOnly中
/*
1.获取消息ID,在ReadIndex消息的第一个记录中记录了消息ID
2.判断该消息是否已经记录在pendingReadIndex中,如果已存在则直接返回
3.如果不存在,则维护到pendingReadIndex中,index是当前Leader已提交的位置,m是请求的消息
4.并将消