etcd之raft协议学习(摸了两天鱼,我有罪,我忏悔)

本文深入探讨了Raft一致性协议的目的、基础概念、选举机制和日志管理。在选举过程中,详细阐述了节点如何发起和赢得选举,以及解决选举过程中可能遇到的问题。在日志管理方面,解释了日志的保存、同步和复制策略,并讨论了在网络合并时的日志处理策略。此外,还分析了raft协议如何处理选举和日志同步中可能出现的各种异常情况。

目录

一、raft协议的目的

二、raft协议的基础概念

三、raft协议的选举

1、发起选举的条件

2、赢得选举的条件

3、选举过程

四、raft协议的日志

1、本地日志保存

2、日志同步方式

3、日志复制时机

五、选举存在的问题以及raft协议的解决方式

1、如果选举的节点没有超过半数怎么办?

2、如果选举的时候两个candidate节点相遇怎么办?

3、如果选举的时候遇到leader节点怎么办?

4、如果leader节点相遇怎么办?

六、日志存在的问题以及raft协议的解决方式

1、leader节点相遇时日志操作?


一、raft协议的目的

        raft是一种一致性协议,在分布式系统中,确保在大部分ongoing的情况下,集群能正常工作并且给出一个正确的结果(业务可用)

二、raft协议的基础概念

        节点角色:leader节点,follower节点

        节点状态:leader状态,follower状态,candidate状态

        term值:任期,每进行一次选举,任期值+1

        commitIndex:标识当前节点已知的最大的已提交的日志索引值

        lastApplied:当前节点已存储的最大索引

        nextIndex数组:需要发送给每个follower节点的下一跳日志的索引值(看似冗余的数组,实际是防止发送失败)

        matchIndex数组:已经复制给每个follower节点的最大的日志索引值

三、raft协议的选举

1、发起选举的条件

        节点长时间没有收到leader节点的心跳,节点的选举计时器超时,发起新一轮选举。

2、赢得选举的条件

        节点获得(包括失联节点在内的)集群中超过半数的选票。

3、选举过程

        节点A长时间收不到心跳,发起投票,成为candidate状态,节点B收到A的消息时,如果仍处于Follower状态,则将票投给A并且重置选举定时器,否则节点为candidate状态(不可能为leader状态,如果是leader状态则无需投票),则选举失败。

四、raft协议的日志

1、本地日志保存

        每个节点都会维护一个本地log用户记录更新操作,并且维护commitindex和lastApplied,主节点二外维护nextIndex和matchIndex数组。

2、日志同步方式

        raft选择批量复制

3、日志复制时机

        数据更新时日志会主动同步到从(follower)节点上
        数据读取时日志如何操作(这个日志有关读到的数据)?

五、选举存在的问题以及raft协议的解决方式

1、如果选举的节点没有超过半数怎么办?

        由于raft的半数节点是指集群中所有节点的半数,而不是可以收到心跳的半数,所以是有可能出现以下情况:部分集群连接不上,并且此集群的节点小于半数并且不包含leader节点。raft将先计算是否有超过半数的节点,如果不超过,则不进行选举。

2、如果选举的时候两个candidate节点相遇怎么办?

        如果term值相等,则重新进行选举;否则以term值更大的未candidate节点。

3、如果选举的时候遇到leader节点怎么办?

        选举的时候网突然好了,这个得翻源码。

4、如果leader节点相遇怎么办?

        选term值较大的为leader节点。

六、日志存在的问题以及raft协议的解决方式

1、leader节点相遇时日志操作?

        当集群被分为两个网络后又合并时,依据日志的任期号来决定日志如何保留(保留任期号大的),如果任期号相同,则使用索引比较大的。

### etcd 中的 Raft 共识算法源码 etcd 是一个分布式的键值存储系统,广泛用于高可用的服务发现和配置管理。etcd 实现了 Raft 一致性协议来确保数据的一致性和可靠性。 #### 源码结构概述 etcdRaft 实现在 `go.etcd.io/etcd/raft` 包中[^1]。以下是主要模块及其功能: - **raft.go**: 定义了核心的 Raft 结构体以及基本操作方法。 - **state_machine.go**: 描述了不同状态下(Follower, Candidate, Leader)的行为逻辑。 - **log.go**: 处理日志条目的追加、提交等功能。 - **node.go**: 提供了一个高层接口,封装了底层细节以便于应用集成。 #### 关键文件路径 对于想要深入研究 etcdRaft 协议的具体实现,可以从以下几个重要文件入手: - `/pkg/raft/raft.go`: 这里包含了整个 Raft 状态机的核心逻辑,包括选举、心跳检测等机制。 ```go // Node represents a node in the raft cluster. type Node struct { ... } ``` - `/pkg/raft/log.go`: 日志管理部分,负责持久化日志记录并维护副本间同步。 ```go func (l *Log) Append(entries []pb.Entry) uint64 { ... } ``` - `/pkg/raft/node.go`: 将低级别的 Raft API 抽象成易于使用的节点对象。 ```go n := NewNode(...) defer n.Stop() for msg := range n.Ready() { // handle message... } ``` 通过阅读上述提到的关键组件代码,能够更好地理解 etcd 如何利用 Go 语言特性高效地实现了 Raft 协议中的各项功能[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值