[etcd]raftpd protobuf
Raft中的序列化是借助于Proto buff来实现的,这个文件夹就定义了需要序列化的几个数据结构,Proto buff(https://github.com/protocolbuffers/protobuf/releases/tag/v3.7.1)是序列化和结构化数据的方法,常用于用于通信协议,数据存储,实现跨平台的数据结构转换。
Raft中的序列化数据结构在raftpb/raft.proto文件中。
syntax = "proto2"; 使用proto2版本进行转换
1、枚举Entry类型有三种: Entry在Raft中是状态机,其类型反映了当前状态机的运行状态,Normal是普通状态,EntryConfChange EntryConfChangeV2 分别对应配置变化的两种状态
enum EntryType {
EntryNormal = 0;
EntryConfChange = 1; // corresponds to pb.ConfChange
EntryConfChangeV2 = 2; // corresponds to pb.ConfChangeV2
}
2、Entry有4个数据,leader的任期Term,任期中的第几个消息Index,Entry的类型Type,消息的数据Data
message Entry {
optional uint64 Term = 2 [(gogoproto.nullable) = false]; // must be 64-bit aligned for atomic operations
optional uint64 Index = 3 [(gogoproto.nullable) = false]; // must be 64-bit aligned for atomic operations
optional EntryType Type = 1 [(gogoproto.nullable) = false];
optional bytes Data = 4;
}
3、SnapshotMetadata 是snaoshot的元信息(包括集群当前的配置状态、日志索引、该条索引日志对应的任期号)有三个参数,conf_state是配置状态信息(配置状态信息里面包括了voters和learners,在paxos中,Learners可以看做是所有被确认消息的执行器,一旦有Client的消息请求被Acceptors确认之后,Learners会做相应的处理(如:执行消息内容,发送回复给Client)。Learner可以有多个。Acceptor (Voters)可以看做是消息请求的存储器。一般来说Acceptors是由一定数量的服务组成的,当消息被发送给Acceptor, 只有大部分Acceptor确认接收此消息,该消息才会被存储,否则该消息将被丢弃。),index是日志索引,term是任期号
message SnapshotMetadata {
optional ConfState conf_state = 1 [(gogoproto.nullable) = false];
optional uint64 index = 2 [(gogoproto.nullable) = false];
optional uint64 term = 3 [(gogoproto.nullable) = false];
}
message ConfState {
// The voters in the incoming config. (If the configuration is not joint,
// then the outgoing config is empty).
repeated uint64 voters = 1;
// The learners in the incoming config.
repeated uint64 learners = 2;
// The voters in the outgoing config.
repeated uint64 voters_outgoing = 3;
// The nodes that will become learners when the outgoing config is removed.
// These nodes are necessarily currently in nodes_joint (or they would have
// been added to the incoming config right away).
repeated uint64 learners_next = 4;
// If set, the config is joint and Raft will automatically transition into
// the final config (i.e. remove the outgoing config) when this is safe.
optional bool auto_leave = 5 [(gogoproto.nullable) = false];
}
4、Snapshot 包括两个参数,一个是上面的SnapshotMetadata 存放了这次snapshot的配置信息,data是snap的数据
message Snapshot {
optional bytes data = 1;
optional SnapshotMetadata metadata = 2 [(gogoproto.nullable) = false];
}
5、MessageType,Raft集群中节点之间的通讯的各种消息类型,借用我们之前看的Raft文章中的图:
Hup表示Follower timers out,开始新的选举
Beat表示
Prop表示是外部客户端访问集群的请求消息
App/AppResp表示当选成为Leader后发给大家的消息和回复的消息
Vote/VoteResp表示投票和回应的消息
Snap是Leader向follower发送的快照
Heartbeat/HeartbeatResp是Leader发送给Follower的心跳信息和反馈
enum MessageType {
MsgHup MessageType = 0 //当Follower节点的选举计时器超时,会发送MsgHup消息
MsgBeat MessageType = 1 //Leader发送心跳,主要作用是探活,Follower接收到MsgBeat会重置选举计时器,防止Follower发起新一轮选举
MsgProp MessageType = 2 //客户端发往到集群的写请求是通过MsgProp消息表示的
MsgApp MessageType = 3 //当一个节点通过选举成为Leader时,会发送MsgApp消息
MsgAppResp MessageType = 4 //MsgApp的响应消息
MsgVote MessageType = 5 //当PreCandidate状态节点收到半数以上的投票之后,会发起新一轮的选举,即向集群中的其他节点发送MsgVote消息
MsgVoteResp MessageType = 6 //MsgVote选举消息响应的消息
MsgSnap MessageType = 7 //Leader向Follower发送快照信息
MsgHeartbeat MessageType = 8 //Leader发送的心跳消息
MsgHeartbeatResp MessageType = 9 //Follower处理心跳回复返回的消息类型
MsgUnreachable MessageType = 10 //Follower消息不可达
MsgSnapStatus MessageType = 11 //如果Leader发送MsgSnap消息时出现异常,则会调用Raft接口发送MsgUnreachable和MsgSnapStatus消息
MsgCheckQuorum MessageType = 12 //Leader检测是否保持半数以上的连接
MsgTransferLeader MessageType = 13 //Leader节点转移时使用,本地消息
MsgTimeoutNow MessageType = 14 //Leader节点转移超时,会发该类型的消息,使Follower的选举计时器立即过期,并发起新一轮的选举
MsgReadIndex MessageType = 15 //客户端发往集群的只读消息使用MsgReadIndex消息(只读的两种模式:ReadOnlySafe和ReadOnlyLeaseBased)
MsgReadIndexResp MessageType = 16 //MsgReadIndex消息的响应消息
MsgPreVote MessageType = 17 //PreCandidate状态下的节点发送的消息
MsgPreVoteResp MessageType = 18 //预选节点收到的响应消息
}
6、Message
涵盖了Raft集群中节点之间的通讯的各种消息所需的字段,Message结构如下
Type:当前传递的消息类型,它的取值有很多种,比如用来请求投票的MsgVote、用来处理网络分区的MsgPreVote2、用来发给leader节点,让它在日志中增加数据的MsgProp(ose)、用来复制日志的MsgApp(end)、用来安装snapshot的MsgSnap。不同类型的消息也会用到下面不同的字段。
To, From分别代表了这个消息的接受者和发送者。
Term:这个消息发出时整个集群所处的任期。
LogTerm:消息发出者所保存的日志中最后一条的任期号,一般MsgVote会用到这个字段。
Index:日志索引号。如果当前消息是MsgVote的话,代表这个candidate最后一条日志的索引号,它跟上面的LogTerm一起代表这个candidate所拥有的最新日志信息,这样别人就可以比较自己的日志是不是比candidata的日志要新,从而决定是否投票。
Entries:需要存储的日志。
Commit:已经提交的日志的索引值,用来向别人同步日志的提交信息。
Snapshot:一般跟MsgSnap合用,用来放置具体的Snapshot值。
Reject,RejectHint:代表对方节点拒绝了当前节点的请求(MsgVote/MsgApp/MsgSnap…)
message Message {
optional MessageType type = 1 [(gogoproto.nullable) = false];
optional uint64 to = 2 [(gogoproto.nullable) = false];
optional uint64 from = 3 [(gogoproto.nullable) = false];
optional uint64 term = 4 [(gogoproto.nullable) = false];
optional uint64 logTerm = 5 [(gogoproto.nullable) = false];
optional uint64 index = 6 [(gogoproto.nullable) = false];
repeated Entry entries = 7 [(gogoproto.nullable) = false];
optional uint64 commit = 8 [(gogoproto.nullable) = false];
optional Snapshot snapshot = 9 [(gogoproto.nullable) = false];
optional bool reject = 10 [(gogoproto.nullable) = false];
optional uint64 rejectHint = 11 [(gogoproto.nullable) = false];
optional bytes context = 12;
}
7、HardState硬状态,与软状态相反,需要写入持久化存储中,包括:节点当前Term、Vote、Commit
message HardState {
optional uint64 term = 1 [(gogoproto.nullable) = false];
optional uint64 vote = 2 [(gogoproto.nullable) = false];
optional uint64 commit = 3 [(gogoproto.nullable) = false];
}
8、集群配置变化的类型和消息
enum ConfChangeType {
ConfChangeAddNode = 0; //增加节点
ConfChangeRemoveNode = 1; //移除节点
ConfChangeUpdateNode = 2; //更新节点
ConfChangeAddLearnerNode = 3; //增加Learner节点
}
message ConfChange { //集群配置变化的消息内容
optional ConfChangeType type = 2 [(gogoproto.nullable) = false]; //变化的类型
optional uint64 node_id = 3 [(gogoproto.nullable) = false, (gogoproto.customname) = "NodeID" ]; //节点的id
optional bytes context = 4;
// NB: this is used only by etcd to thread through a unique identifier.
// Ideally it should really use the Context instead. No counterpart to
// this field exists in ConfChangeV2.
optional uint64 id = 1 [(gogoproto.nullable) = false, (gogoproto.customname) = "ID" ];
}
上一篇: raft入门--算法实现2
下一篇: CI 的pdo driver一处bug