源码解读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 ...
随机推荐
- HTML5相关文章和资源
Polyfills HTML5 Cross Browser Polyfills canvas HTML5 JS实现毛玻璃效果(高斯模糊) 高斯模糊的算法Canvas 内部元素添加事件处理 应用场景 P ...
- call、apply和 bind的简单使用方法
- call.apply:在 javascript 中,call 和 apply 都是为了改变某个函数运行时的上下文(context)而存在的,换句话说,就是为了改变函数体内部 this 的指向. J ...
- dva+react+antd+webpack 项目开发配置
如何搭建一个dva项目如何搭建一个dva项目 后期项目会在github上进行书写,同时也会在segmentfault上进行同步-3Q拜读-
- ES6-11学习笔记--数组遍历
ES5中数组遍历方式: for循环 forEach():没有返回值,只是针对每个元素调用func map():返回新的Array,每个元素为调用func的结果 filter():返回符合func条件的 ...
- uView的DatetimePicker详解
uView UI号称: 是全面兼容nvue的uni-app生态框架,全面的组件和便捷的工具会让您信手拈来,如鱼得水 亲身感受,用起来真的坑太多, 官方文档太简洁, 很多配置都没说明也没代码, 上百度查 ...
- EMS查看单个邮箱的已用空间
Exchange查询单个邮箱用户使用状态. 查看用户"wsj"的邮箱使用状态 键入以下命令: Get-MailboxStatistics wsj | FL DiplayName,T ...
- 【UWP】实现一个波浪进度条
好久没写 blog 了,一个是忙,另外一个是觉得没啥好写.废话不多说,直接上效果图: 可能看到这波浪线你觉得会很难,但看完这篇 blog 后应该你也会像我一样恍然大悟.图上的图形,我们可以考虑是由 3 ...
- MySQL---增删改查数据库、表、记录
对库的操作 # 增 create database db1 charset utf8; # 删 drop database db1; # 改 alter database db1 charget gb ...
- CVE 公开披露的网络安全漏洞列表
CVE®是一份公开披露的网络安全漏洞列表, 官方地址为 : https://cve.mitre.org/cve/ 比如 mavenrepository 上阿里的Druid修复的漏洞的列表如下:
- echarts饼图调整悬浮提示框的位置
默认是跟随鼠标的位置 通过数组表示提示框浮层的位置,数字设置绝对位置,百分比设置相对位置. position: [10,10] //绝对位置,相对于容器左侧10px,上侧10px position: ...