分布式一致性算法Raft

news/2025/3/11 15:45:12/文章来源:https://www.cnblogs.com/chenny7/p/7657696.html

 Raft算法

 

在了解Raft之前,我们先了解一致性(Consensus)这个概念,它是指多个服务器在状态达成一致,但是在一个分布式系统中,因为各种意外可能,有的服务器可能会崩溃或变得不可靠,它就不能和其他服务器达成一致状态。这样就需要一种Consensus协议,一致性协议是为了确保容错性,也就是即使系统中有一两个服务器当机,也不会影响其处理过程。

为了以容错方式达成一致,我们不可能要求所有服务器100%都达成一致状态,只要超过半数的大多数服务器达成一致就可以了,假设有N台服务器,N/2 +1 就超过半数,代表大多数了。

 

角色

在一个由 Raft 协议组织的集群中有三类角色: 

  1. follower
  2. candidate
  3. leader

三类角色的变迁图如下,结合后面的选举过程来看很容易理解:

就像一个民主社会,领袖由民众投票选出。刚开始没有领袖,集群中的所有参与者都是群众,那么首先开启一轮大选,在大选期间所有群众都能参与竞选,这时所有群众的角色就变成了候选人,民主投票选出领袖后就开始了这届领袖的任期(用术语 Term 表达),然后选举结束,所有除领袖的候选人又变回群众角色服从领袖领导。

 

 

选主(Leader Election)

  • 系统在初始状态下,所有node都是follower;
  • follower在没有监听到leader的时候,会变为candidate;
  • cadidate会向其它node发送投票请求,如果得票数过半就变为leader(candidate可以给自己投票);
  • 选出 Leader 后,Leader 通过定期向所有 Follower 发送心跳信息(Heart Beat)维持其统治;
  • 若 Follower 一段时间未收到 Leader 的心跳则认为 Leader 可能已经挂了再次发起选主过程。

  

考虑极简的例子,一个最小的 Raft 民主集群需要三个参与者(如下图:A、B、C),这样才可能投出多数票。初始状态 ABC 都是 Follower,然后发起选举这时有三种可能情形发生。下图中前二种都能选出 Leader,第三种则表明本轮投票无效(Split Votes),每方都投给了自己,结果没有任何一方获得多数票。之后每个参与方随机休息一阵(Election Timeout,150~300ms之间的随机数)重新发起投票直到一方获得多数票。这里的关键就是随机 timeout,最先从 timeout 中恢复发起投票的一方向还在 timeout 中的另外两方请求投票,这时它们就只能投给对方了,很快达成一致。

 

任期(term)

在 Raft 算法中,所有的节点在发送 RPC 消息时(请求或响应),都会带上 term 字段,

  • 如果收到的消息的 term 号小于自身的任期号,则该消息会被视为过期信息并被忽略;
  • 如果一个节点收到了一个包含较新 term 的消息,它会立即更新自己的当前任期到这个新的任期,并将自己的状态切换为 follower;

 

 

日志复制(Log Replication)

  • 预写日志(Write-Ahead-Log, WAL),WAL 目标是在系统发生故障时保证数据的一致性和可靠性。当进行状态改变的操作时,系统首先将这些操作记录到日志中,然后再实际执行这些操作。
    • 只有当一个日志(即写入请求)得到了集群超过半数节点的认同后,它才会被提交并将修改应用到状态机中;
    • 如果过程中发生了故障,例如系统崩溃或者电源中断,可以通过重新执行日志中的操作来恢复之前的状态(redo);
  • 状态机,节点用来实际存储数据的仓库。每个写入请求的最终步骤都是把结果保存到状态机里面,同时,读取请求也需要从这个状态机中提取数据以便响应;

 

 

Raft 协议强依赖 Leader 节点的可用性来确保集群数据的一致性。数据的流向只能从 Leader 节点向 Follower 节点转移。当 Client 向集群 Leader 节点提交数据后,Leader 节点接收到的数据处于未提交状态(Uncommitted),接着 Leader 节点会并发向所有 Follower 节点复制数据并等待接收响应,确保至少集群中超过半数节点已接收到数据后再向 Client 确认数据已接收。一旦向 Client 发出数据接收 Ack 响应后,表明此时数据状态进入已提交(Committed),Leader 节点再向 Follower 节点发通知告知该数据状态已提交。

 

数据更新的流程(两阶段提交,proposal - commit ):

  • 所有的修改会写入 leader 节点的 WAL 日志中,写入 WAL 的每条记录都有一个自增的 索引号;
    • 客户端如何知道 leader 节点的位置呢?可以让客户端先随机访问一个节点,如果访问到的不是 leader 节点,拒绝访问,并提供 leader 的地址给客户端。
  • leader 将此次修改通过心跳请求发给所有的 follower,这个过程称为 proposal;
  • follower 节点收到请求后,会在写入 WLA 日志后再返回;
  • leader 收到超半数的 follower 节点同意的响应后,leader 节点会再次请求所有 follower 节点提交修改(写入状态机),这个过程称为 commit;
    • 如果要求立即一致性的话,leader 需要先修改状态机,然后响应客户端;
    • 如果只要求最终一致性的话,leader 可以先响应客户端,再异步写入状态机;

 

 

脑裂(Brain Split)

假如一个集群有 5 个节点,节点 1 是 leader,

 

 

case1、发生脑裂后,原 leader 在多数节点的分区上,

 分区后,节点 4、5 在一个分区,1、2、3 在一个分区 。此时 4、5 收不到 leader 的心跳,成为candidate 后由于得不到多数票所以选举失败,都不会成为leader;

 

 case2、发生脑裂后,原 leader 在少数节点的分区上,

分区后,节点 1、2 在一个分区,3、4、5 在一个分区,1 还是 leader,3、4、5 也会选出一个新的 leader 出来(假设是节点 3),且 term 值更新;此时,

  • 如果写请求到节点1,由于 1 只能与 2通信,得不到多数节点的确认,请求会处于无法 commit 的状态;
    • 如果从节点 1 读取数据,由于它们所在分区的数据无法更新,会出现脏读。如何解决脏读呢?可以要求 leader 节点在响应只读请求之前,必须通过心跳先获取多数节点的确认。
  • 如果写请求到节点3,能得到多数节点的返回,可以正常提交;

 如果出现脑裂,可能会有多个 leader 节点,此时两个 partition 的数据会分叉。如果后面网络又好了,会再合并成一个集群,并以新 leader 的数据为准。

 

 

参考文档:

http://www.jdon.com/artichect/raft.html

http://thesecretlivesofdata.com/raft/

http://www.cnblogs.com/mindwind/p/5231986.html

 

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

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

相关文章

LeetCode24 两两交换链表中的节点

两两交换链表中的节点LeetCode24 两两交换链表中的节点 题目链接:LeetCode24 描述 给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。示例输入:head = [1,2,3,4] 输出:[2,1,4,3]思路代码 class Solution {public ListNode swapPairs(ListNode head) {ListNo…

51单片机入门:LED灯控制(01)

第一篇博客,博客园注册很久却一直没有好好利用,今天把以前的文章都删掉,就当开个好头吧。 希望在以后的时间中,自己能够认真、努力、珍惜时间。 零基础入门51单片机 单片机(Microcontroller Unit,MCU)是一种集成电路芯片,它将计算机的CPU、存储器(RAM和ROM)、输入/输…

解读Graph+AI白皮书:LLM浪潮下,Graph尚有何为?

蚂蚁&之江实验室牵头的《Graph+AI:大模型浪潮下的图计算》白皮书发布,详细探讨了图计算与人工智能技术的融合发展,涵盖数据处理、算法创新、应用实践及未来挑战,强调图技术在提升模型解释性和处理复杂关系数据方面的重要性。历时半年,由蚂蚁集团和之江实验室牵头,联合…

C#/.NET/.NET Core技术前沿周刊 | 第 14 期(2024年11.18-11.24)

前言 C#/.NET/.NET Core技术前沿周刊,你的每周技术指南针!记录、追踪C#/.NET/.NET Core领域、生态的每周最新、最实用、最有价值的技术文章、社区动态、优质项目和学习资源等。让你时刻站在技术前沿,助力技术成长与视野拓宽。欢迎投稿、推荐或自荐优质文章、项目、学习资源等…

24.10.25 远程连接以及排错

一.Typora的使用 ctrl+数字 表示几级标题 ctrl+shift+[ 表示有序列表 ctrl+shift+] 表示无序列表 enter两次列表消失 英文下的点,三点bash+回车表示代码块 英文下的点,三点sh+回车表示代码块 二.VMware使用 1.VMware只能双击一次出现这个提示,表示已经打开一个…

TIA做交通信号灯练习2

今晚在昨天的基础上增加要求,三种灯在计时还剩下5秒时进行闪烁。 在昨天项目基础上新建一个FB,定义下面的变量。在此FB内部写下面的程序在OB1调用这个FB,分配参数在wincc新建变量关联TIA中的变量在WINCC画面上放置2个按钮和3个圆形,2个按钮的鼠标按下使start1和stop1为1,弹…

ISSCC2025 Computing-In-Memory Session 趋势整理

今天下午ISSCC 2025发布会开完,CIM Session花落谁家终于清楚了。今年被CIM放到了Session 14,共录取七篇,投稿数如果和去年差不多的话,那么录取率应该是进一步下降了(去年录取了九篇)。只能说体感上来说就明显越来越卷。 还是先来看一下录取的Paper:7篇都来自远东,两篇台…

Nuxt.js 应用中的 webpack:error 事件钩子

title: Nuxt.js 应用中的 webpack:error 事件钩子 date: 2024/11/25 updated: 2024/11/25 author: cmdragon excerpt: webpack:error 钩子是用于在 Webpack 编译过程中捕获和处理错误的一个重要机制。当发生编译错误时,这个钩子会被调用,通常用于在 UI 上给出反馈或者处理…

异步与资源调度 以浏览器事件循环为例

初次发布于我的个人文档 参考: chromiun官方文档 w3c官方文档 针对一个异步的程序应该如何对它进行资源的调度呢?本文以浏览器为典型范例进行简单介绍。 1.查看浏览器的多进程图景 打开任意一个浏览器这里以edge为例。 然后打开Windows的任务管理器,你看到的可能是这样:事实…

dl dt dd 标签【示例】

代码示例 <!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>Title</title> </head> <body> <dl><dt>HTML</dt><dd>HyperText Markup Language,是一种用于…

【Azure 环境】从Azure AD(Entra ID)中获取的Token在访问自定义的接口应用时验证不通过

“IDX10503: Signature validation failed. Keys tried: Microsoft.IdentityModel.Tokens.X509SecurityKey , KeyId: xxxxxxxxxxxxxxxxxxx”问题描述 集成Azure AD(新名称Microsoft Entra ID),拿到对应的accessToken作为登录用的凭证。这个 AccessToken 能够正常返回,并作为M…

多平台数据集成的实践案例:吉客云到MySQL

测试-查询销售渠道信息(已删除数据)-dange:吉客云数据集成到MySQL的技术案例分享 在现代企业的数据管理中,如何高效、可靠地实现多平台间的数据集成是一个关键问题。本次我们将聚焦于一个具体的系统对接案例,即将吉客云中的销售渠道信息(包括已删除数据)集成到MySQL数据库…