ETCD 使用 Raft 算法来实现分布式一致性,其选举机制是 Raft 的核心部分。Raft 通过选举选出一个领导者(Leader),领导者负责处理所有客户端请求并管理日志复制。以下是 ETCD 的选举机制,分别针对首次选举和变更选举进行说明。
1. 首次选举
当 ETCD 集群刚启动时,所有节点都处于 Follower 状态,此时集群中没有领导者。首次选举的过程如下:
-
Follower 等待超时:
- 每个 Follower 会启动一个随机的选举超时计时器(Election Timeout),通常为 150ms 到 300ms。
- 如果 Follower 在超时时间内没有收到来自 Leader 的心跳(Heartbeat),它会认为集群中没有 Leader,并开始选举。
-
转换为 Candidate:
- Follower 转换为 Candidate 状态,并增加自己的任期号(Term)。
- 它向集群中的其他节点发送 RequestVote RPC 请求,请求投票。
-
投票规则:
- 每个节点在同一任期内只能投一次票,且遵循“先到先得”的原则。
- Candidate 需要获得集群中大多数节点(超过半数)的投票才能当选为 Leader。
-
选举结果:
- 如果 Candidate 获得大多数投票,它将成为 Leader,并开始向其他节点发送心跳以维持领导地位。
- 如果 Candidate 没有获得大多数投票(例如,出现平票),它会等待选举超时后重新发起选举。
-
Leader 开始工作:
- Leader 开始接收客户端请求,并将日志复制到其他 Follower 节点。
2. 变更选举
变更选举发生在 Leader 失效或网络分区等情况下,集群需要重新选举新的 Leader。过程如下:
-
Leader 失效:
- 如果 Leader 崩溃或网络分区导致 Follower 无法收到 Leader 的心跳,Follower 会等待选举超时。
-
Follower 转换为 Candidate:
- 和首次选举类似,Follower 会转换为 Candidate,增加任期号,并向其他节点发送 RequestVote RPC。
-
投票与选举:
- 其他节点会根据 Candidate 的日志完整性(Log Completeness)决定是否投票。
- Raft 要求 Leader 必须拥有最新的日志,因此只有日志较新的 Candidate 才能获得投票。
-
新 Leader 产生:
- 如果 Candidate 获得大多数投票,它将成为新的 Leader。
- 新 Leader 会立即发送心跳,阻止其他节点发起新的选举。
-
日志同步:
- 新 Leader 会将自己的日志同步给其他 Follower,确保集群状态一致。
选举的关键点
-
任期号(Term):
- 每次选举都会增加任期号,用于区分不同的选举周期。
- 节点会拒绝来自旧任期的请求,确保只有最新任期的 Leader 有效。
-
日志完整性:
- Candidate 必须拥有最新的日志才能获得投票,这保证了数据的一致性。
-
大多数原则:
- Leader 必须获得大多数节点的支持,确保集群中只有一个合法的 Leader。
-
随机选举超时:
- 随机超时机制减少了多个 Candidate 同时发起选举的可能性,避免选举冲突。
总结
- 首次选举:集群启动时,Follower 等待超时后发起选举,获得大多数投票的 Candidate 成为 Leader。
- 变更选举:当 Leader 失效时,Follower 重新发起选举,确保集群快速恢复并选出新的 Leader。
- Raft 的选举机制通过任期号、日志完整性和大多数原则,保证了 ETCD 集群的高可用性和数据一致性。
举个例子
我们可以用一个班级选班长的例子来形象地说明 ETCD 的选举过程。假设班级里有若干名学生,他们要选出一名班长(Leader),而选举规则和 Raft 算法的选举机制非常相似。
场景设定
- 班级:一个分布式系统(ETCD 集群)。
- 学生:集群中的节点(Follower、Candidate、Leader)。
- 班长:Leader,负责管理班级事务。
-
选举规则:
- 每个学生可以投票,但只能投一次。
- 必须获得超过半数的投票才能当选班长。
- 如果选举失败(比如平票),就重新选举。
1. 首次选举(班级刚成立,没有班长)
-
初始状态:
- 班级刚成立,所有学生都是普通学生(Follower),没有班长。
- 每个学生都在等待,看是否有人主动站出来竞选班长。
-
等待超时:
- 每个学生都有一个随机的“耐心时间”(Election Timeout),比如 1 分钟到 3 分钟。
- 如果在这个时间内没有听到班长的消息(比如班长没有发通知),就会有人觉得自己可以当班长。
-
有人站出来竞选:
- 一个学生(Candidate)站出来说:“我要当班长,请大家支持我!”(发送 RequestVote RPC)。
- 他还会告诉大家:“这是第 1 届选举!”(Term = 1)。
-
投票:
- 其他学生根据他的表现(比如他是不是靠谱,是不是最新的消息都知道)决定是否投票。
- 如果这个学生获得了超过半数的支持,他就成为班长(Leader)。
-
班长开始工作:
- 班长开始管理班级事务,比如收发作业、组织活动(处理客户端请求)。
- 他还会定期给其他学生发通知(心跳),告诉大家:“我还在,班级一切正常!”
2. 变更选举(班长突然请假了)
-
班长失效:
- 有一天,班长突然请假了(Leader 崩溃或网络分区)。
- 其他学生收不到班长的通知,开始觉得不对劲。
-
等待超时:
- 学生们又开始等待,看班长会不会回来。
- 如果等待时间到了还没消息,就会有人站出来竞选新班长。
-
新的竞选者:
- 一个学生(Candidate)站出来说:“班长请假了,我要竞选新班长,这是第 2 届选举!”(Term = 2)。
- 他还会告诉大家:“我知道班长之前做的所有事情!”(日志完整性)。
-
投票:
- 其他学生根据他的表现和知道的班级事务决定是否支持他。
- 如果他获得了超过半数的支持,他就成为新班长。
-
新班长上任:
- 新班长开始管理班级,并确保所有学生都知道最新的班级事务(日志同步)。
- 他也会定期发通知,防止其他学生再发起选举。
关键点总结
- 超过半数支持:班长必须得到大多数学生的支持,确保只有一个合法的班长。
- 随机等待时间:每个学生的耐心时间不同,避免同时有太多人竞选。
- 日志完整性:竞选者必须知道班级的最新事务,才能获得支持。
- 任期号:每次选举都有一个届数(Term),确保大家知道这是最新的选举。
通过这个例子,可以很直观地理解 ETCD 的选举机制:无论是首次选举还是变更选举,都是通过投票、超时和大多数原则来选出一个合法的 Leader,确保系统的高可用性和一致性。