共识算法Raft(day11)

引入

在分布式系统中,为了消除单点提高系统可用性,通常会创建副本来进行容错,但这会带来另一个问题就是,如何保证多个副本之间的数据一致性。

为了解决这个问题,计算机行内就提出了共识算法,它允许多个分布式节点就某个值或一系列值达成一致性协议,即使在一些节点发生故障、网络分区或其他问题的情况下,共识算法也能保证系统的一致性和数据的可靠性。

常见的共识算法有:Zab、Paxos、Raft。

  • Paxos:一种经典的共识算法,用于解决分布式系统中的一致性问题。业内某知名程序猿曾经提经过说,共识算法本质上只有Paxos一种,其他就是对该共识算法的变种。
  • Raft:一种较新的共识算法,Paxos不易实现,Raft则是对其的简化和改进,旨在易于理解和实现。
  • Zab:ZooKeeper使用的共识算法,基于Paxos算法,并且大部分和Raft相同。主要区别就是对于Leader的任期,Zap叫做epoch,Raft叫做term;还有就是Raft是Leader向Follower发送心跳包,而Zab则刚好相反。
  • Gossip:该算法没有Leader和Follower之分,每个节点都是对等的。当节点中数据改动时,都会告知其他节点。

概述

总的来说,Raft算法是一种共识算法,他的作用就是实现多个节点的数据一致性。

当我们构建一个Raft集群,并对其内部进行一系列的读写操作时,集群内部是如何工作的呢?

1. Raft集群必须存在一个主节点,客户端向集群发起的写操作必须由主节点处理,所以Raft核心算法的第一部分就是选主。假设当前Raft集群没有主节点,那就没法工作,先选出一个主节点之后,再去考虑其他的内容。这部分工作在Raft中称为选主。

2. 有了主节点之后,当客户端发送过来写请求时,主节点就会将其进行包装同步给其他节点。在保证大多数节点都同步了本次操作之后,主节点就会给客户端发起响应了。这部分工作在Raft中称为日志复制。

3. 主节点在Raft算法中承担着非常大的责任,所以只有符合条件的节点才能当选主节点。为了保证集群对外展现的一致性,主节点在处理日志时,也一定要谨慎。这部分工作在Raft中称为安全性。

综上所述,Raft算法将一致性问题分解成了选主、日志复制以及安全性。

基本概念

领导者

领导者(Leader),负责处理客户端的所有修改请求,并将这些请求作为日志复制给跟随者(Follower)。在Raft中,Leader会定期向Follower发送心跳消息,以维持自己的领导地位,防止Follower进入选举过程。

跟随者

跟随者(Follower),接受来自Leader的日志,并将这些日志进行转换,应用为自己的内容。跟随者不会直接处理客户端的修改操作,但是可以处理客户端的读请求。

跟随者

候选者(Candidate),当Follower在一段时间内没有收到Leader发送过来的心跳消息时,Follower就会将自己的身份转变,并开始尝试通过投票成为新的Leader。

在Raft算法中,只能存在一个Leader,并且在集群启动时,所有节点的状态都是跟随者的状态,然后一段时间之内没有收到心跳包时,才会把自己转变成候选者,从而发起选举,使得集群出现了领导者,然后领导者就会一直工作直到他发生异常。

任期

在Raft中,领导者是没有固定任期的,当某一节点成为领导者之后,都是持续工作直到它出现异常为止。假设A点开始选举,然后成为领导者直到它发生异常的这段时间之内,都属于该节点的任期。因此,一段任期的开始时间都是从选举开始,然后到领导者不工作为止。假设在选举时间内没有选举成功,那么也算是一个任期,只不过该任期是以没有领导者而结束的。

任期更像是一个逻辑时钟的作用,有了它,就可以发现哪些节点已经过期,每一个节点都会保持一个任期号,然后在通信的时候带上这个值。

任期号会随着时间单调递增,并且每个节点都会存储一个任期号。节点之间通信时都会携带该任期号,如果一个节点的任期号比其他节点小,那么他就会变更自己的任期号到较大那个值。如果一个候选者或者领导者发现自己的任期号过期了,那么他就会变更成跟随者的状态。如果一个节点收到了一个带着过期任期号的节点,那么他就会忽略这次请求。

Raft算法中服务器节点之间采用RPC进行通信,主要有两类RPC请求:

RequestVote RPCs:请求投票,由候选者选举时发出。

AppendEntries RPCs:由领导者发出,用来做日志复制和发送心跳消息。

选主

1. Raft服务集群启动时,所有的节点都是跟随者的角色,并且每个节点都会有一个超时时间,当等待时间超过过期时间时,跟随者就会进入候选者的角色。

2. 由于启动时,并没有领导者,所以等到等待时间超过超时时间之后,跟随者就会转换成候选者的角色,继而发起投票(此时是因为没有刚启动没有领导者,也有可能是领导者宕机了,或者领导者和跟随者之间发生了网络故障问题等)。

3. 当跟随者成为候选者之后,任期号就会自动增长,同时投给自己一票,紧接着就会发生RPC请求,请其他节点也投自己一票,然后就是等待其他节点的响应。

到了此阶段,就会出现三种情况:

4.1 赢得选举(选举成功的定义是超过半数节点同意自己成为领导者)之后,就会立刻广发消息给其他节点,说自己选举成功了,大家都变成跟随者的状态吧。然后其他节点一看自己的任期号并没有人家的大,那就只能乖乖变成跟随者的状态了。

4.2 还没有等到半数票同意呢,并且等待时间没有超过超时时间,结果此时突然发来个消息说你跟随我吧,现在我是领导者。然后自己一看,人家的任期号比自己大会跟自己相等,那就只能老老实实跟着人家了,自己当个跟随者。

4.3 没有得到半数票同意,又超过了等待时间,那就只能保持候选者状态了,然后增加自己的任期号,重新发起一轮选举,此时就又成为了这三种情况的开头。(出现这种情况的原因可能有所有的节点超时时间相同,那么同一时间过期,导致所有的节点只会投自己一票,从而使得永远没有节点能达不到半数票同意,导致始终没有领导者出现。解决这种现象可以给节点搞一个随机超时时间,这就不会造成同一时间过期的现象了,即使有那也是个例,不影响整体架构)。

投票要求:

一个节点只能投一票。

候选者的任期号必须不能比投票者的小。

日志复制

当有写请求过来之后,Leader通过日志复制管理实现各个节点间的数据同步。

状态机

Raft算法一致性的实现,是基于日志复印状态机的。状态机最大的特征就是,不同节点的状态机若当前状态相同,然后接收了相同的输入,则一定会得到相同结果的输出。

流程

1. 领导者在收到客户端的写请求时,就会把请求的内容和自己的任期号进行封装,然后发送给跟随者,征求大家对此内容的意见,并同时将该请求内容封装为日志。

2. 跟随者收到此次请求之后,首先对比任期号。只要任期号不比自己小,并且两者的日志编号等内容相同,那么就会回复领导者同意,并将此内容封装成日志。

3. 当收到半数同意之后,领导者就会将此日志提交到自己的状态机,状态机会输出一个结果,同时日志状态变成了已提交。

4. 然后领导者还会向跟随者发送请求,告诉跟随者把日志进行提交。

5. 跟随者对日志进行了提交,日志状态也就变成了已提交。

6. 领导者向跟随者发送要求提交的请求时,还会给客户端发出响应。

日志是由任期号、日志的索引和命令组成的,为了保证可用性,各个节点的日志可以不完全相同,但是领导者会持续不断的发送内容给跟随者,以促使各个节点的日志最终达到相同。因此,Raft算法是保持最终一致性。

脑裂

脑裂指的是本来是在一个集群中处理消息的节点,因为某些原因而不能通信,导致两端都开始处理消息,从而使得系统混乱,数据错误的现象。

Redis集群存在脑裂现象,在多机房部署中,由于网络连接问题,很容易生成多个分区,而多分区的形成,很容易产生脑裂,从而导致数据出现问题。

在日常生产环境中,三机房的容灾能力是最强的,所以以三机房为例,来进行分析断网之后,出现的五种情况的后果:

情况一

在这种情况中,B与领导者A之间发生了网络问题,B的超时时间一过,B就会成为候选者,给C一发请求,C一看任期号比自己大,所以自己就会成为B的跟随者,而A与B此时不能进行交互,导致A也是领导者,B也是领导者。当有请求来时,A接受请求,但是最终由于票数没有大于一半,不会响应该请求,不过B能够成功响应。这就导致了读请求来时,A给出的数据可能不是正确数据。

综上所述,当领导者和某一跟随者之间无法通信时,就会出现脑裂现象。

情况二:

当B和C同时与A发生了网络故障时,两个跟随者无论谁先到达超时时间都会决出新的领导者,这就导致了三机房中出现了两位领导者,从而出现了脑裂问题。

情况三:

当ABC三者之间都出现了网络故障,此时虽然BC都会去进行选举,但是没有一个能选举成功,所以此时只有A可以提供读服务,BC则不能提供服务。

情况四:

 当出现上述情况时,B会进行选举,但是并不能选举成功,因为它永远得不到半数票的同意,所以并不会出现脑裂现象。并且,B不会对外提供服务,A和C则可以继续正常对外服务。

情况五:

当出现上述情况时,系统仍会正常工作,不会出现任何问题。

综上所述,在三个机房可能出现的五种情况中,也不是都会出现脑裂现象。并且我们发现,出现脑裂现象之后,从前的领导者都是不能响应写请求,因此我们可以在写项目中,加上一个判断就是当领导者长期不能应对写请求时,就自动下线或者进行其他处理。 

领导者宕机处理

请求到达领导者之前挂了:此时请求并没有到达Raft集群,所以Raft集群中并没有任何一个节点会对此请求有任何的处理。当新领导者上线以后,也不会认为有任何的不妥。此时如果客户端有重试机制的话,就会重新发送请求过来,Raft集群进行正常处理。

请求到达领导者,但是领导者还没有发送数据时挂了:新领导者选举出来之后,由于新领导者并没有该请求的任何消息,所以并不会进行任何响应。并且当新领导者同步各个节点时,由于之前的旧领导者有这条消息,旧领导者还会将此消息丢弃出来。

请求向跟随者发送部分之后挂掉了:此时选举出领导者之后,会有两种情况出现。第一种是新领导者有该消息的存在,所以会进行同步,最后返回响应;第二种就是恰好不存在该消息,那么就不会进行同步,也不会发起响应。

领导者向跟随者发送提交后挂掉了:此时已经成功发送了提交,并且提交的同时还会向客户端响应,那已经成功了,此时新领导者上来也不会处理啥,因为已经成功了。

在日志复制中,对一些较为详细的内容并没有介绍到。其实,向跟随者发送日志条目的啥时候,有很多的内容,因为要保证节点的数据一致性,所以就要判断以前的日志条目是否相同。但是由于并不是详细了解其工作原理,所以只进行了一个大致介绍,同学们也只需要大致了解就能应对面试官的大多数问题了。

概述来说,由于各个节点之间数据是不可能每次都能同步成功,并且由于宕机等问题,数据可能确实很多。所以日志复制,基本上是上述的简单流程,不过假设某一结点数据或缺许多时,领导者也会慢慢找到或缺的数据,然后给他全部补上,保持一个数据的最终一致性。

总的来说,Raft共识算法就是用来保证集群中数据一致性的。为了保证其数据一致性,内部大概分成了选主、日志复制、安全性等内容。 

应用场景

1. 在Redis中,使用哨兵机制时,当Redis主节点发生问题之后,哨兵节点就会进行选主,然后对主从集群进行操作,选主的过程就是使用的Raft算法。

2. 在RabbitMQ构建集群中,仲裁队列内部使用的也是Raft算法。本身创建的是普通队列,这就导致单点问题。不过创建仲裁队列之后,利用Raft算法就可以将队列和消息在不同的节点都进行存储。假设创建队列的节点出现故障之后,其他节点依然能够针对该队列进行工作。

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

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

相关文章

27.9 调用go-ansible执行playbook拷贝json文件重载采集器

本节重点介绍 : go-ansible执行playbook编写分发重载的playbook编译执行 测试停掉一个节点测试停掉的节点再回来 go-ansible执行playbook 新增 goansiblerun/run.go package goansiblerunimport ("context""github.com/apenella/go-ansible/pkg/execute&qu…

【数学二】多元函数积分学-重积分-二重积分定义、性质、计算

考试要求 1、了解多元函数的概念,了解二元函数的几何意义. 2、了解二元函数的极限与连续的概念,了解有界闭区域上二元连续函数的性质. 3、了解多元函数偏导数与全微分的概念,会求多元复合函数一阶、二阶偏导数,会求全微分&#x…

【Dv2Admin】Django配置线上ws反向代理

在 Web 应用程序的部署过程中,安全性、稳定性和实时通信是开发者们普遍关注的重点。Django 是一个非常流行的 Web 框架,常与 Nginx 配合使用,以便实现反向代理、负载均衡以及 SSL 加密等功能。除此之外,实时功能(如 WebSocket)也是现代应用中经常使用的技术。 在项目中实…

分布式文件系统Minio实战

分布式文件存储系统Minio实战 1、分布式文件系统应用场景1.1 Minio介绍1.1.1 Minio优点 1.2 MinIO的基础概念1.3 纠删码EC(Erasure Code)1.4 存储形式1.5 存储方案 2、Minio环境搭建2.1 单机部署2.1.1 non-erasure code mode2.1.2 erasure code mode2.1.…

算法题总结(十九)——图论

图论 DFS框架 void dfs(参数) { if (终止条件) {存放结果;return; }for (选择:本节点所连接的其他节点) {处理节点;dfs(图,选择的节点); // 递归回溯,撤销处理结果 } }深搜三部曲 确认递归函数,参数确认终止条件处理目前搜索节…

【网络协议栈】Tcp协议(下)的可靠性和高效性(超时重传、快速重传、拥塞控制、流量控制)

绪论: 承接上文,上文写到Tcp协议的结构以及对tcp协议的性能优化的滑动窗口,本章我们将继续了解Tcp协议的可靠性和高效性的具体展示。后面我将继续完善网络协议栈的网络层协议敬请期待! 话不多说安全带系好,发车啦(建议…

【Qt】窗口——Qt窗口的概念、常用的窗口函数、菜单栏、工具栏、状态栏、浮动窗口、对话框

文章目录 Qt窗口Qt窗口的概念菜单栏工具栏状态栏浮动窗口对话框 Qt 窗口 Qt窗口的概念 QMainWindow 类概述: QMainWindow 是一个为用户提供主窗口程序的类,它继承自 QWidget 类,并且提供了一个预定义的布局。 菜单栏 菜单栏常用属性&#xf…

C语言初阶:十.结构体基础

♥感谢您阅读本篇文章,文章内容为个人对所学内容的整理总结,欢迎大佬在评论区指点一二。♥ ♥个人主页:折枝寄北-CSDN博客折枝寄北擅长C语言初阶,等方面的知识,折枝寄北关注python,c,java,qt,c语言领域.https://blog.csdn.net/2303_80170533?…

Android Kotlin中协程详解

博主前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住也分享一下给大家, 👉点击跳转到教程 前言 Kotlin协程介绍: Kotlin 协程是 Kotlin 语言中的一种用于处理异步编程的机制。它提供了一…

《Python网络安全项目实战》

《Python网络安全项目实战》 项目1 Python 环境安装任务1.1 Windows上安装Python任务1.2 Ubuntu环境下安装Python 项目2 Python基础练习任务2.1 使用数据类型任务2.2 使用组合数据类型任务2.3 使用控制结构任务2.4 使用函数任务2.5 使用模块 项目3 处理文件中的数据任务3.1 读文…

雷赛L6N伺服驱动器基本参数设置——EtherCAT 总线型

1、指令脉冲设置 PA0.08代表电机转一圈,所需要的指令脉冲数,该值驱动器默认值为0,该值更改后断电重启后生效。 2、编码器反馈脉冲设置 PA0.11,代表编码器输出每转脉冲数,实际反馈的脉冲数做了4倍频处理,设…

MySql数据库中数据类型

本篇将介绍在 MySql 中的所有数据类型,其中主要分为四类:数值类型、文本和二进制类型、时间日期、String 类型。如下(图片来源:MySQL数据库): 目录如下: 目录 数值类型 1. 整数类型 2. …

【论文笔记】MLSLT: Towards Multilingual Sign Language Translation

🍎个人主页:小嗷犬的个人主页 🍊个人网站:小嗷犬的技术小站 🥭个人信条:为天地立心,为生民立命,为往圣继绝学,为万世开太平。 基本信息 标题: MLSLT: Towards Multiling…

系统架构设计师教程 第2章 2.6 计算机语言 笔记

2.6计算机语言 ★★★★☆ 2.6.1计算机语言的组成 计算机语言 (Computer Language) 是指用于人与计算机之间交流的一种语言,是人与计算机之间传递信息的媒介。 计算机语言主要由一套指令组成,指令一般包括表达式、流程控制和集合三大部分内容。 表达…

基于JSP的高校食堂食材选购管理系统【附源码】

基于JSP的高校食堂食材选购管理系统 效果如下: 系统首页界面 用户登录页面 食材信息页面 论坛交流界面 管理员登录界面 管理员功能主界面 食材信息管理界面 订单配送管理界面 用户功能主界面 商家功能主界面 司机功能主界面 研究背景 近年来互联网技术的发展使得…

新王Claude 3.5的6大应用场景

Anthropic AI深夜发布了备受期待的Claude 3.5系列更新,包括了全新升级的Claude 3.5 Sonnet和首发的Claude 3.5 Haiku。 Claude 3.5 Sonnet能够理解细微的指令和上下文,识别并纠正自身错误,还能从复杂数据中生成深入的分析和洞察。 结合最先进…

java项目之在线考试系统设计与实现(springboot)

风定落花生,歌声逐流水,大家好我是风歌,混迹在java圈的辛苦码农。今天要和大家聊的是一款基于springboot的在线考试系统设计与实现。项目源码以及部署相关请联系风歌,文末附上联系信息 。 项目简介: 基于JavaWeb技术…

PostgreSQL C++客户端API libpqxx的使用

PostgreSQL是一个先进的、开源的、免费的、功能强大的关系型数据库,缩写版是postgres。它使用一种客户端/服务器(C/S)的模型。一次PostgreSQL会话由下列相关的进程(程序)组成: (1).一个服务器进程,它管理数据库文件、接受来自客户端应用与数据…

C++研发笔记8——C语言程序设计初阶学习笔记6

在第一部分——课前准备的学习中,我就提到了学习C语言的过程中,练习是必不可少的环节,所以本篇笔记我们来进行记录我们学习《C语言程序设计初阶》阶段的第一篇练习文章。 题目一 下面哪个不是C语言内置的数据类型: A.char B.d…

mysql5.7.44 arm 源码编译安装

一、:下载源码:mysql官网:MySQL :: MySQL Downloads #####下载mysql安装包 : 网址:https://www.mysql.com/ 可在页面下载后上传或直接下载。 官网地址首页,拉到最底部,找到社区版本下载&#xf…