Raft共识算法

前提条件

Raft不考虑拜庭将军问题,即消息会延迟、丢失但不会错误。

Raft的特性

  • Strong leader:在 Raft 中,日志条目(log entries)只从 leader 流向其他服务器。 这简化了复制日志的管理,使得 raft 更容易理解。
  • Leader 选举:Raft 使用随机计时器进行 leader 选举。 这只需在任何一致性算法都需要的心跳(heartbeats)上增加少量机制,同时能够简单快速地解决冲突。
  • 成员变更:Raft 使用了一种新的联合一致性方法,其中两个不同配置的大多数在过渡期间重叠。 这允许集群在配置更改期间继续正常运行。

通过选举一个 leader 的方式,Raft 将一致性问题分解成了三个相对独立的子问题:

  • Leader 选举:当前的 leader 宕机时,一个新的 leader 必须被选举出来。(5.2 节)
  • 日志复制:Leader 必须从客户端接收日志条目然后复制到集群中的其他节点,并且强制要求其他节点的日志和自己的保持一致。
  • 安全性:Raft 中安全性的关键是图 3 中状态机的安全性:如果有任何的服务器节点已经应用了一个特定的日志条目到它的状态机中,那么其他服务器节点不能在同一个日志索引位置应用一条不同的指令。章节 5.4 阐述了 Raft 算法是如何保证这个特性的;该解决方案在选举机制(5.2 节)上增加了额外的限制。

Raft算法的RPC和设置

Raft 算法中服务器节点之间通信使用远程过程调用(RPCs),并且基本的一致性算法只需要两种类型的 RPCs。

RPC有三种:

  1. RequestVote RPC:候选人在选举期间发起
  2. AppendEntries RPC:领导人发起的一种心跳机制,复制日志也在该命令中完成
  3. InstallSnapshot RPC: 领导者使用该RPC来发送快照给太落后的追随者。

超时设置:

  1. BroadcastTime : 领导者的心跳超时时间
  2. Election Timeout: 追随者设置的候选超时时间
  3. MTBT :指的是单个服务器发生故障的间隔时间的平均数

BroadcastTime << ElectionTimeout << MTBF
两个原则:

  1. BroadcastTime应该比ElectionTimeout小一个数量级,为的是使领导人能够持续发送心跳信息(heartbeat)来阻止追随者们开始选举;
  2. ElectionTimeout也要比MTBF小几个数量级,为的是使得系统稳定运行。

一般BroadcastTime大约为0.5毫秒到20毫秒,ElectionTimeout一般在10ms到500ms之间。大多数服务器的MTBF都在几个月甚至更长。

Leader选举

一个 Raft 集群包含若干个服务器节点;通常是 5 个,这样的系统可以容忍 2 个节点的失效。在任何时刻,每一个服务器节点都处于这三个状态之一:leader、follower 或者 candidate 。在正常情况下,集群中只有一个 leader 并且其他的节点全部都是 follower 。

  • Follower 都是被动的:他们不会发送任何请求,只是简单的响应来自 leader 和 candidate 的请求。
  • Leader: 处理所有的客户端请求(如果一个客户端和 follower 通信,follower 会将请求重定向给 leader)。
  • candidate: 用来选举一个新的 leader

在这里插入图片描述

Raft 把时间分割成任意长度的任期(term),如图 5 所示。任期用连续的整数标记。每一段任期从一次选举开始,一个或者多个 candidate 尝试成为 leader 。

如果一个服务器的当前任期号比其他的小,该服务器会将自己的任期号更新为较大的那个值。如果一个 candidate 或者 leader 发现自己的任期号过期了,它会立即回到 follower 状态。如果一个节点接收到一个包含过期的任期号的请求,它会直接拒绝这个请求。

Leader选举过程

Raft 使用一种心跳机制(每个节点都维护一个随机时钟)来触发 leader 选举。当服务器程序启动时,他们都是 follower 。一个服务器节点只要能从 leader 或 candidate 处接收到有效的 RPC 就一直保持 follower 状态。Leader 周期性地向所有 follower 发送心跳(不包含日志条目的 AppendEntries RPC)来维持自己的地位。

触发条件:

  1. 一般情况下,追随者接到领导者的心跳时,把ElectionTimeout清零,不会触发;
  2. 领导者故障,追随者的ElectionTimeout超时发生时,会变成候选者,触发领导人选取;

候选操作过程:

追随者自增当前任期,转换为Candidate,对自己投票,并发起RequestVote RPC,等待下面三种情形发生;

  1. 获得超过半数服务器的投票,赢得选举,成为领导者;
  2. 另一台服务器赢得选举,并接收到对应的心跳,成为追随者;
  3. 选举超时,没有任何一台服务器赢得选举,自增当前任期,重新发起选举;

注意事项:

  1. 服务器在一个任期内,最多能给一个候选人投票,采用先到先服务原则;
  2. 候选者等待投票时,可能会接收到来自其它声明为领导人的的AppendEntries RPC。如果该领导人的任期(RPC中有)比当前候选人的当前任期要大,则候选人认为该领导人合法,并转换成追随者;如果RPC中的任期小于候选人的当前任期,则候选人拒绝此次RPC,继续保持候选人状态;
  3. 候选人既没有赢得选举也没有输掉选举:如果许多追随者在同一时刻都成为了候选人,选票会被分散,可能没有候选人能获得大多数的选票。当这种情形发生时,每一个候选人都会超时,并且通过自增任期号和发起另一轮 RequestVote RPC 来开始新的选举。然而,如果没有其它手段来分配选票的话,这种情形可能会无限的重复下去。所以Raft使用的随机的选举超时时间(150~300ms之间),来避免这种情况发生。

日志复制

只要过半的服务器能正常运行,Raft 就能够接受,复制并应用新的日志条目;在正常情况下,新的日志条目可以在一个 RPC 来回中被复制给集群中的过半机器;并且单个运行慢的 follower 不会影响整体的性能。

Leader接受命令的过程:

  1. 领导者接受客户端请求;
  2. 领导者把指令追加到日志;
  3. 发送AppendEntries RPC到追随者;
  4. 领导者收到半数以上追随者的确认后,领导者Commit该日志,把日志在状态机中回放,并返回结果给客户端;

提交过程:

  1. 在下一个心跳阶段,领导者再次发送AppendEntries RPC给追随者,日志已经commited;
  2. 追随者收到Commited日志后,将日志在状态机中回放。

安全性(保证日志顺序)

到目前为止描述的机制并不能充分的保证每一个状态机会按照相同的顺序执行相同的指令。

为了保证安全性增加以下限制:

1. 领导者追加日志(Append-Only)

领导者永远不会覆盖已经存在的日志条目;

日志永远只有一个流向:从领导者到追随者;

2. 选举限制:投票阻止没有全部日志条目的服务器赢得选举

如果投票者的日志比候选人的新,拒绝投票请求;
这意味着要赢得选举,候选者的日志至少和大多数服务器的日志一样新,那么它一定包含全部的已经提交的日志条目。

3. 永远不提交任期之前的日志条目(只提交任期内的日志条目)

在Raft算法中,当一个日志被安全的复制到绝大多数的机器上面,即AppendEntries RPC在绝大多数服务器正确返回了,那么这个日志就是被提交了,然后领导者会更新commit index。

总结

Raft明确了集群的功能+集群的实现细节。所有角色都可以接收用户请求,leader对所有的读写请求负责,也就是说,只有leader对最终的读写有解释权。通过这可以了解到,raft承担的是强一致性场景,其读和写其实是差不多的过程,不会存在读比写快。那么follower如果接收到请求会会怎么办呢?会进行请求转发,这样会多增加一些rpc的请求。
Raft集群将工作状态分成两种,一种是日志复制,另一种是领导选举。其中领导选举是一种不稳定的状态,在这种不稳定的状态中,会出现数据安全、成员状态变更等问题。另外一种日志复制是一种稳定状态,在leader确定的情况下,leader指导所有机器按规定来完成数据的读写要求,其中规定包括如下:

  1. 所有请求需要经过leader才能完成,包括读写
  2. 半数集群成员同意某个数据的写入后,才能完成数据的写入。
  3. 使用2PC模式进行数据写入。

参考

  • Raft论文翻译
  • Raft一致性算法笔记
  • Raft演示动画
  • Raft算法总结

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/330045.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

直方图 帕累托图_如何发现现象背后的关键因素?帕累托图,质量管理的利器...

大家好&#xff1a;无论在日常生活还是工作中&#xff0c;都会发生一些事情或者结果&#xff0c;是我们不希望发生的。我们也希望从根本上解决掉&#xff0c;但有时候却无从下手&#xff0c;比如本来打算用来看书的时间不知道去哪里了&#xff1b;本来打算存款的钱也不知道去哪…

centos8上安装nginx

参考自 https://www.jianshu.com/p/9b2dd37a5af9 &#xff1b; 【1】安装步骤 step1&#xff09;安装nginx sudo yum install -y nginx step2&#xff09;启动nginx服务 -- 开机自启动 sudo systemctl enable nginx -- 开启nginx 服务 sudo systemctl start nginx step3&am…

简单分析KafKa工作原理

架构图 Producer&#xff1a;Producer即生产者&#xff0c;消息的产生者&#xff0c;是消息的入口。 kafka cluster&#xff1a; Broker&#xff1a;Broker是kafka实例&#xff0c;每个服务器上有一个或多个kafka的实例&#xff0c;我们姑且认为每个broker对应一台服务器。每…

Java7/8 中的 HashMap 和 ConcurrentHashMap 全解析

转载自 Java7/8 中的 HashMap 和 ConcurrentHashMap 全解析网上关于 HashMap 和 ConcurrentHashMap 的文章确实不少&#xff0c;不过缺斤少两的文章比较多&#xff0c;所以才想自己也写一篇&#xff0c;把细节说清楚说透&#xff0c;尤其像 Java8 中的 ConcurrentHashMap&#…

kali mysql停止服务器_MySQL 的主从复制(高级篇)

首先要明白为什么要用 mysql 的主从复制&#xff1a;1–在从服务器可以执行查询工作 (即我们常说的读功能)&#xff0c;降低主服务器压力&#xff1b;&#xff08;主库写&#xff0c;从库读&#xff0c;降压&#xff09;2–在从主服务器进行备份&#xff0c;避免备份期间影响主…

centos8安装并启动tomcat9

【1】 步骤如下 step1&#xff09; 下载tomcat9 step2&#xff09;centos8 输入 rz命令&#xff0c;把tomcat9 压缩包上传到centos8 没有rz命令&#xff0c; 安装使用 yum -y install lrzsz step3&#xff09;压缩包解压到tomcat9 step4&#xff09;配置jdk环境 vim /et…

unity 3d shaderlab 开发实战详解_vue实战开发011:使用router-view嵌套路由详解

前面已经把首页的顶部header和底部的footer页面写完&#xff0c;现在开始写内容区域了&#xff0c;在写内容之前我们先要将路由配置好&#xff0c;不然无法在页面上查看效果&#xff0c;所以这里我在components目录下先建了一个home.vue文件&#xff0c;里面简单的写了一句“我…

go 语言 error 处理的最佳实践

今天分享 go 语言 error 处理的最佳实践&#xff0c;了解当前 error 的缺点、妥协以及使用时注意事项。文章内容较长&#xff0c;干货也多&#xff0c;建议收藏 什么是 error 大家都知道 error[1] 是源代码内嵌的接口类型。根据导出原则&#xff0c;只有大写的才能被其它源码…

请求nginx静态资源报403

【README】 请求nginx静态资源报403&#xff1b; 【1】原因 静态资源防止在某个家目录下&#xff0c;如 /root 目录下 【2】 解决方法1 nginx.conf 文件没有指定用户 # user nobody 修改为 user root; # 设置为root用户 &#xff1b; 【例子】 user root; #使用r…

DDD中聚合的概念

DDD中的聚合模式是最难弄清楚的一种模式&#xff0c;在如何确定聚合边界这个问题上&#xff0c;更没有一个明确的指导原则&#xff0c;这导致DDD的落地比较难。不过&#xff0c;相信你读了这篇文章应该对聚合会有更深刻的理解。 本文分三部分来讲&#xff1a; 1、什么是聚合&a…

docker 打包镜像_Spring Boot2 系列教程(四十一)部署 Spring Boot 到远程 Docker 容器

不知道各位小伙伴在生产环境都是怎么部署 Spring Boot 的&#xff0c;打成 jar 直接一键运行&#xff1f;打成 war 扔到 Tomcat 容器中运行&#xff1f;不过据松哥了解&#xff0c;容器化部署应该是目前的主流方案。不同于传统的单体应用&#xff0c;微服务由于服务数量众多&am…

MySQL日志:binlog、事务日志(redo、undo)

事务的隔离性是通过锁实现&#xff0c;而事务的原子性、一致性和持久性则是通过日志实现。Mysql的日志可以分为&#xff1a; binlog&#xff1a;server层实现事务日志&#xff1a;包括redo log、undo log&#xff0c;引擎层&#xff08;innodb&#xff09;实现 redo log red…

vmware安装centos8步骤

【readme】 vmware 安装centos8&#xff1b; 【1】新建虚拟机 step1&#xff09; 下载 centos8 http://download.nus.edu.sg/mirror/centos/8-stream/isos/x86_64/ 补充&#xff0c;通过代理服务器下载会快很多&#xff1b; step2&#xff09;vmare&#xff0c;点击文件&…

并发编程 – Concurrent 用户指南

转载自 并发编程 – Concurrent 用户指南1. java.util.concurrent – Java 并发工具包Java 5 添加了一个新的包到 Java 平台&#xff0c;java.util.concurrent 包。这个包包含有一系列能够让 Java 的并发编程变得更加简单轻松的类。在这个包被添加以前&#xff0c;你需要自己去…

小微企业名录查询系统_欢迎访问辽宁小微企业名录系统

欢迎访问辽宁小微企业名录系统http://xwqy.lngs.gov.cn辽宁小微企业名录系统是小微企业扶持政策的实施公示台、集装箱&#xff0c;通过访问该系统网站&#xff0c;及时全面知晓小微企业复工复产、“个转企”等各类扶持政策。按照《国务院关于扶持小型微型企业健康发展的意见》(…

常用限流算法分析

一、计数器&#xff08;固定窗口&#xff09;算法 计数器算法是使用计数器在周期内累加访问次数&#xff0c;当达到设定的限流值时&#xff0c;触发限流策略。下一个周期开始时&#xff0c;进行清零&#xff0c;重新计数。 此算法在单机还是分布式环境下实现都非常简单&#…

nginx学习小结

nginx 【0】README 本文po处理 nginx的主要内容&#xff0c;包括反向代理&#xff0c;负载均衡&#xff0c;动静分离&#xff0c;高可用集群等&#xff1b; 本文引用链接&#xff1a; vmware安装centos8&#xff0c;refer2 https://blog.csdn.net/PacosonSWJTU/article/detail…

缓存与数据库的一致性:先操作缓存还是先操作数据库?

数据缓存 在我们实际的业务场景中&#xff0c;一定有很多需要做数据缓存的场景&#xff0c;比如售卖商品的页面&#xff0c;包括了许多并发访问量很大的数据&#xff0c;它们可以称作是是“热点”数据&#xff0c;这些数据有一个特点&#xff0c;就是更新频率低&#xff0c;读…

Object.hashCode()与Object.equals()

【README】 本文旨在po出 hashCode &#xff0c; equals的api描述&#xff0c;以加深理解&#xff1b; 本文翻译自 jdk 文档&#xff1b; 【1】Object.hashCode() 1&#xff09;介绍&#xff1a;返回对象的哈希码值。支持此方法是为了有利于哈希表&#xff0c;例如由 java.u…