RAFT实现之leader election

2024-08-28 21:32
文章标签 实现 leader raft election

本文主要是介绍RAFT实现之leader election,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

RAFT实现之leader election
测试全部通过
在这里插入图片描述
leader选举基本流程
所有节点以follower启动
follower的选举时钟超时,转为candidate
candidate向其他节点发送投票请求,如果收到过半节点的投票,则成为leader
leader周期性向其他节点发送心跳包以维持权威
实现关键点:
1.状态转移:
raft节点的状态转移要严格依据下图,不管节点处于什么状态,只要发现更大的Term,都转为follower。对于candidate,如果收到新leader的心跳包,则转为follower。
在这里插入图片描述
2.选举时钟
如果节点状态不是leader,选举时钟需要周期性的检查是否过期:

func (rf Raft) PeriodicRequestVote() {
for {
rf.mu.Lock()
//检查状态是不是leader,如果不是,检查election time 有没有超时 ,超时,则状态转为candidate
if rf.state != leader && rf.electionTimer+rf.timeperiod < time.Now().UnixNano() {
//转到c尝试成为leader
rf.mu.Unlock()
rf.AttemptBeLeader()
} else {
rf.mu.Unlock()
}
// rf.mu.Unlock()
time.Sleep(electionInterval
time.Millisecond)
}
}
重置选举时钟的3种情形:
1.从leader处收到appendentriesRPC调用(如果leader的term过期则不用重置)
2.开始新的一轮选举
3.给其他节点投票(收到requestVoteRPC调用)

3.RequestVoteRPC
在这里插入图片描述

接受者(follow,candidate,leader)实现除了图中的1、2,还需要注意:
检查是否收到更大的term,如果收到,更新term并转为follower状态,如果已经是follower,则更新term和重置votedFor

//如果候选人的term小于自己的term
if term<rf.currentTerm {
reply.VoteGranted = false
return
} else if term > rf.currentTerm { //收到更高的term,更新term,转为follwer
rf.convertToFollwer(term)
}
如果决定给候选人投票,需要将自己的当前term返回,这里强调当前term(currentTerm)是因为follower可能因为在正式返回投票结果前更新了自己的currentTerm(比如收到更大的term)

if (rf.votedFor==-1 || rf.votedForcandidateid) && (lastLogTerm > lastTerm ||
lastLogTerm
lastTerm && lastLogIndex>=lastIndex) {
reply.Term = rf.currentTerm
reply.VoteGranted = true
//将投票人修改(add my)
rf.votedFor=candidateid
发送者收到RPC调用结果后,需要注意:
是否是过期的rpc回复(即term小于自己的term),丢弃不处理
//如果收到过期的term,丢弃

if rf.state!=candidate || reply.Term < rf.currentTerm {
return false
}
返回的term是否大于自己的term,是则转为follower
//收到的trem大于自己的term,转为follwer

if reply.Term > rf.currentTerm {
rf.convertToFollwer(reply.Term)
}
candidate统计选票时得把自己算上
守护进程定时检查节点是否成为leader,成为leader后定时周期发起AppendEntriesRPC。

func (rf Raft) PeriodicAppendEnties() {
for {
rf.mu.Lock()
if rf.state == leader {
rf.mu.Unlock()
rf.AttemptReplication()
} else {
rf.mu.Unlock()
}
time.Sleep(heartbeatInterval
time.Millisecond)
}
}

这篇关于RAFT实现之leader election的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1115935

相关文章

mybatis执行insert返回id实现详解

《mybatis执行insert返回id实现详解》MyBatis插入操作默认返回受影响行数,需通过useGeneratedKeys+keyProperty或selectKey获取主键ID,确保主键为自... 目录 两种方式获取自增 ID:1. ​​useGeneratedKeys+keyProperty(推

Spring Boot集成Druid实现数据源管理与监控的详细步骤

《SpringBoot集成Druid实现数据源管理与监控的详细步骤》本文介绍如何在SpringBoot项目中集成Druid数据库连接池,包括环境搭建、Maven依赖配置、SpringBoot配置文件... 目录1. 引言1.1 环境准备1.2 Druid介绍2. 配置Druid连接池3. 查看Druid监控

Linux在线解压jar包的实现方式

《Linux在线解压jar包的实现方式》:本文主要介绍Linux在线解压jar包的实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录linux在线解压jar包解压 jar包的步骤总结Linux在线解压jar包在 Centos 中解压 jar 包可以使用 u

c++ 类成员变量默认初始值的实现

《c++类成员变量默认初始值的实现》本文主要介绍了c++类成员变量默认初始值,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录C++类成员变量初始化c++类的变量的初始化在C++中,如果使用类成员变量时未给定其初始值,那么它将被

Qt使用QSqlDatabase连接MySQL实现增删改查功能

《Qt使用QSqlDatabase连接MySQL实现增删改查功能》这篇文章主要为大家详细介绍了Qt如何使用QSqlDatabase连接MySQL实现增删改查功能,文中的示例代码讲解详细,感兴趣的小伙伴... 目录一、创建数据表二、连接mysql数据库三、封装成一个完整的轻量级 ORM 风格类3.1 表结构

基于Python实现一个图片拆分工具

《基于Python实现一个图片拆分工具》这篇文章主要为大家详细介绍了如何基于Python实现一个图片拆分工具,可以根据需要的行数和列数进行拆分,感兴趣的小伙伴可以跟随小编一起学习一下... 简单介绍先自己选择输入的图片,默认是输出到项目文件夹中,可以自己选择其他的文件夹,选择需要拆分的行数和列数,可以通过

Python中将嵌套列表扁平化的多种实现方法

《Python中将嵌套列表扁平化的多种实现方法》在Python编程中,我们常常会遇到需要将嵌套列表(即列表中包含列表)转换为一个一维的扁平列表的需求,本文将给大家介绍了多种实现这一目标的方法,需要的朋... 目录python中将嵌套列表扁平化的方法技术背景实现步骤1. 使用嵌套列表推导式2. 使用itert

Python使用pip工具实现包自动更新的多种方法

《Python使用pip工具实现包自动更新的多种方法》本文深入探讨了使用Python的pip工具实现包自动更新的各种方法和技术,我们将从基础概念开始,逐步介绍手动更新方法、自动化脚本编写、结合CI/C... 目录1. 背景介绍1.1 目的和范围1.2 预期读者1.3 文档结构概述1.4 术语表1.4.1 核

在Linux中改变echo输出颜色的实现方法

《在Linux中改变echo输出颜色的实现方法》在Linux系统的命令行环境下,为了使输出信息更加清晰、突出,便于用户快速识别和区分不同类型的信息,常常需要改变echo命令的输出颜色,所以本文给大家介... 目python录在linux中改变echo输出颜色的方法技术背景实现步骤使用ANSI转义码使用tpu

Python使用python-can实现合并BLF文件

《Python使用python-can实现合并BLF文件》python-can库是Python生态中专注于CAN总线通信与数据处理的强大工具,本文将使用python-can为BLF文件合并提供高效灵活... 目录一、python-can 库:CAN 数据处理的利器二、BLF 文件合并核心代码解析1. 基础合