欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

[etcd]raftpd protobuf

程序员文章站 2024-03-19 21:44:40
...

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文章中的图:

[etcd]raftpd protobuf

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 etcd