源码解读etcd heartbeat,election timeout之间的拉锯
转一个我在知乎上回答的有关raft election timeout/ heartbeat interval 的回答吧。
答:准确来讲: election是timeout,而heartbeat 是interval, 这样就很容易理解了。
heartbeat interval 是leader 安抚folower的时间,这个时间间隔是体现在leader上,是leader发送心跳的周期 (我xxxx ms 来一次)。
election timeout 是follower能容忍多久没收到心跳开始骚动的时间 (我等你xxxx ms,没来我就起义)。
为压制follower随时起义的骚动,heartbeat timeout 一般小于 election timeout。
楼主说两个配置超时,都会成为候选者,实际上,heartbeat interval/election timeout 是一个此消彼长的拉锯。
想象一个刚初始化的集群,大家都是follower,没有heartbeat压制, 各follower节点的election timeout之后开始骚动。
在一次选举周期没有选出leader,很可能是选票瓜分了, 需要发起新的选举; 为缓解选票瓜分的情况, 每个节点的election timeout骚动时间是随机的。
发生网络分区的时候, 少数派分区的follower收不到leader 的安抚,是不是又要起义,这个时候election timeout也起作用了。
我们结合etcd的默认配置和源码理解:
目前etcd默认heartbeat = 100ms, election = 1000ms
https://github.com/etcd-io/etcd/blob/5fd69102ce785136aeb3168c56adce7957b99e2d/raft/raft.go#L1718
raft 为节点定义了以下状态:
const (
StateFollower StateType = iota
StateCandidate
StateLeader
StatePreCandidate
numStates
)
becomeLeader 注册了定期发送心跳的动作 r.tick = r.tickHeartbeat ;
becomeFollower becomeCandidate becomePreCandidate 都注册了(没收到安抚而)起义的动作 r.tick = r.tickElection;
我们以follower节点为例:
func (r *raft) becomeFollower(term uint64, lead uint64) {
r.step = stepFollower
r.reset(term)
r.tick = r.tickElection
r.lead = lead
r.state = StateFollower
r.logger.Infof("%x became follower at term %d", r.id, r.Term)
}
r.reset(term)==> r.resetRandomizedElectionTimeout()会接受传播过来的term,并计算随机选举超时时间。
func (r *raft) resetRandomizedElectionTimeout() {
r.randomizedElectionTimeout = r.electionTimeout + globalRand.Intn(r.electionTimeout)
}
从上面源码看出,etcd默认配置产生的节点随机超时时间是 [1000,2000]ms。
r.tickElection会判断:如果当前经历的时间electionElapsed大于随机超时时间,就开始起义,并重置electionElapsed时间。
func (r *raft) tickElection() {
r.electionElapsed++
if r.promotable() && r.pastElectionTimeout() {
r.electionElapsed = 0
if err := r.Step(pb.Message{From: r.id, Type: pb.MsgHup}); err != nil {
r.logger.Debugf("error occurred during election: %v", err)
}
}
}
func (r *raft) pastElectionTimeout() bool {
return r.electionElapsed >= r.randomizedElectionTimeout
}
becomePreCandidate 没有r.reset(term)动作,这是一个预投票状态,也称prevote,这也是etcd的常见面试题。
prevote 是论文作者为解决“分区少数派重新加入集群,因为高term导致集群瞬间不稳定”的提出的方案,etcd 默认加入prevote机制, 在成为真正意义的候选者之前不自增term,先预投票,因为其他节点一直收到心跳,并不会起义,故该节点预投票拿不到多数投票,等到该节点收到leader心跳,自行降为follower,term和Leader一致, 现在这一机制已经插入到每次follower-->Candidate之间。
switch m.Type {
case pb.MsgHup:
if r.preVote {
r.hup(campaignPreElection)
} else {
r.hup(campaignElection)
}
源码解读etcd heartbeat,election timeout之间的拉锯的更多相关文章
- etcd学习(6)-etcd实现raft源码解读
etcd中raft实现源码解读 前言 raft实现 看下etcd中的raftexample newRaftNode startRaft serveChannels 领导者选举 启动并初始化node节点 ...
- php-msf 源码解读【转】
php-msf: https://github.com/pinguo/php-msf 百度脑图 - php-msf 源码解读: http://naotu.baidu.com/file/cc7b5a49 ...
- Prometheus 源码解读(一)
Prometheus 源码解读(一) Prometheus 是云原生监控领域的事实标准,越来越来的开源项目开始支持 Prometheus 监控数据格式.从本篇开始,我将和大家一起阅读分析 Promet ...
- AFNetworking 3.0 源码解读 总结(干货)(上)
养成记笔记的习惯,对于一个软件工程师来说,我觉得很重要.记得在知乎上看到过一个问题,说是人类最大的缺点是什么?我个人觉得记忆算是一个缺点.它就像时间一样,会自己消散. 前言 终于写完了 AFNetwo ...
- AFNetworking 3.0 源码解读(五)之 AFURLSessionManager
本篇是AFNetworking 3.0 源码解读的第五篇了. AFNetworking 3.0 源码解读(一)之 AFNetworkReachabilityManager AFNetworking 3 ...
- YYModel 源码解读(二)之NSObject+YYModel.h (1)
本篇文章主要介绍 _YYModelPropertyMeta 前边的内容 首先先解释一下前边的辅助函数和枚举变量,在写一个功能的时候,这些辅助的东西可能不是一开始就能想出来的,应该是在后续的编码过程中 ...
- AFNetworking 3.0 源码解读 总结
终于写完了 AFNetworking 的源码解读.这一过程耗时数天.当我回过头又重头到尾的读了一篇,又有所收获.不禁让我想起了当初上学时的种种情景.我们应该对知识进行反复的记忆和理解.下边是我总结的 ...
- 线程本地变量ThreadLocal源码解读
一.ThreadLocal基础知识 原始线程现状: 按照传统经验,如果某个对象是非线程安全的,在多线程环境下,对对象的访问必须采用synchronized进行线程同步.但是Spring中的各种模板 ...
- 第二十三课:jQuery.event.add的原理以及源码解读
本课主要来讲解一下jQuery是如何实现它的事件系统的. 我们先来看一个问题: 如果有一个表格有100个tr元素,每个都要绑定mouseover/mouseout事件,改成事件代理的方式,可以节省99 ...
随机推荐
- 在原生CSS中使用变量
本文首发于我的博客 一直以来,CSS作为一种申明式的样式标记语言,很难像如javascript等命令式编程语言一样通过定义和使用变量的方式来维护和追踪某些状态.后来随着scss,less等CSS预处理 ...
- 纯CSS实现柱形图
CSS在处理排版之强大,没有做不到,只有想不到.下面我们将一同实现一个柱状图. 先打好一个具体的框架.我们利用无序列表做整体,里面的东西我们根本选择内联无素span,strong,em来填充. < ...
- H5: 表单验证失败的提示语
前言 前端的童鞋在写页面时, 都不可避免的总会踩到表单验证这个坑. 这时候, 我们就要跪了, 因为要写一堆js来检查. 但是自从H5出现后, 很多常见的表达验证, 它都已经帮我们实现了, 让我 ...
- js判断输入数字是否是整数,金额、数字
function isIntNum(strNum){//js判断输入数字是否是整数 仅供学习思想 var strCheckNum = strNum+""; if(strCheckN ...
- 解决vue安装时出现vue --version或vue不是内部命令的问题
1. 试图全局配置 vue 的环境变量,找到 vue.cmd 的路径,然后进行配置. 问题:在文件搜索中,没有找到 vue.cmd,失败. 1.npm i npm -g 全局 update 了 npm ...
- maven导入依赖了提示can't resolved
maven导入依赖显红报错 网上有很多解决方案,我试过几个但是都不是很好用,推荐一个我自己一直在用的解决方案 在终端执行命令 mvn idea:idea 无法解析的原因基本上是因为包没下载完整,执行这 ...
- selenium打开指定Chrome账号
selenium打开指定Chrome账号 获取User Data路径 打开目标Chrome,在搜索栏输入chrome://version,找到"个人资料路径". 这里获取到的路径为 ...
- C++篇:第四章_函数_知识点大全
C++篇为本人学C++时所做笔记(特别是疑难杂点),全是硬货,虽然看着枯燥但会让你收益颇丰,可用作学习C++的一大利器 五.函数 (一)函数使用规则 函数的定义不能嵌套但调用可以嵌套 在函数调用时,如 ...
- 界面优化--如何提升用户体验(Velocity.js和GSAP)
Velocity.js和GSAP 我们需要提升代码质量来留住用户.作为用户界面的建设者,我们的工作是迅速引导和引导用户的注意力,指导他们如何有效地使用我们的应用程序. 1. 如何提升代码质量 定向聚焦 ...
- Nuxt 的介绍与安装
Nuxt.js(一.介绍与安装) 1.为什么使用Nuxt 渐进式Vue.js框架给前后端分离带来无限的乐趣,越来越多的程序员选择Vue.在我们使用Vue框架的过程中不免会出现以下的一些问题: 如何更好 ...